]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiTabular.cpp
Use the command-alternatives sequence as defined in menus.bind
[lyx.git] / src / frontends / qt4 / GuiTabular.cpp
1 /**
2  * \file GuiTabular.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
7  * \author Jürgen Spitzmüller
8  * \author Herbert Voß
9  * \author Uwe Stöhr
10  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 #include <config.h>
15
16 #include "GuiTabular.h"
17
18 #include "GuiApplication.h"
19 #include "GuiSetBorder.h"
20 #include "GuiView.h"
21 #include "LengthCombo.h"
22 #include "qt_helpers.h"
23 #include "Validator.h"
24
25 #include "BufferView.h"
26 #include "Cursor.h"
27 #include "FuncRequest.h"
28 #include "FuncStatus.h"
29 #include "LyX.h"
30 #include "LyXRC.h"
31
32 #include "insets/InsetTabular.h"
33
34 #include "support/convert.h"
35 #include "support/debug.h"
36
37 #include <QCheckBox>
38 #include <QPushButton>
39 #include <QRadioButton>
40 #include <QLineEdit>
41
42 using namespace std;
43
44 namespace lyx {
45 namespace frontend {
46
47 GuiTabular::GuiTabular(QWidget * parent)
48         : InsetParamsWidget(parent), firstheader_suppressable_(false),
49           lastfooter_suppressable_(false)
50
51 {
52         setupUi(this);
53
54         tabularWidthED->setValidator(unsignedLengthValidator(tabularWidthED));
55         columnWidthED->setValidator(unsignedLengthValidator(columnWidthED));
56         multirowOffsetED->setValidator(new LengthValidator(multirowOffsetED));
57         topspaceED->setValidator(new LengthValidator(topspaceED));
58         bottomspaceED->setValidator(new LengthValidator(bottomspaceED));
59         interlinespaceED->setValidator(new LengthValidator(interlinespaceED));
60
61         tabularWidthUnitLC->setCurrentItem(Length::defaultUnit());
62         columnWidthUnitLC->setCurrentItem(Length::defaultUnit());
63         multirowOffsetUnitLC->setCurrentItem(Length::defaultUnit());
64         topspaceUnitLC->setCurrentItem(Length::defaultUnit());
65         bottomspaceUnitLC->setCurrentItem(Length::defaultUnit());
66         interlinespaceUnitLC->setCurrentItem(Length::defaultUnit());
67
68         connect(topspaceED, SIGNAL(textEdited(const QString &)),
69                 this, SLOT(checkEnabled()));
70         connect(topspaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
71                 this, SLOT(checkEnabled()));
72         connect(bottomspaceED, SIGNAL(textEdited(const QString &)),
73                 this, SLOT(checkEnabled()));
74         connect(bottomspaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
75                 this, SLOT(checkEnabled()));
76         connect(interlinespaceED, SIGNAL(textEdited(const QString &)),
77                 this, SLOT(checkEnabled()));
78         connect(interlinespaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
79                 this, SLOT(checkEnabled()));
80         connect(booktabsRB, SIGNAL(clicked(bool)),
81                 this, SLOT(checkEnabled()));
82         connect(borderDefaultRB, SIGNAL(clicked(bool)),
83                 this, SLOT(checkEnabled()));
84         connect(borderSetPB, SIGNAL(clicked()),
85                 this, SLOT(borderSet_clicked()));
86         connect(borderUnsetPB, SIGNAL(clicked()),
87                 this, SLOT(borderUnset_clicked()));
88         connect(hAlignCO, SIGNAL(activated(int)),
89                 this, SLOT(checkEnabled()));
90         connect(vAlignCO, SIGNAL(activated(int)),
91                 this, SLOT(checkEnabled()));
92         connect(multicolumnCB, SIGNAL(clicked()),
93                 this, SLOT(checkEnabled()));
94         connect(multirowCB, SIGNAL(clicked()),
95                 this, SLOT(checkEnabled()));
96         connect(multirowOffsetED, SIGNAL(textEdited(const QString &)),
97                 this, SLOT(checkEnabled()));
98         connect(multirowOffsetUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
99                 this, SLOT(checkEnabled()));
100         connect(newpageCB, SIGNAL(clicked()),
101                 this, SLOT(checkEnabled()));
102         connect(headerStatusCB, SIGNAL(clicked()),
103                 this, SLOT(checkEnabled()));
104         connect(headerBorderAboveCB, SIGNAL(clicked()),
105                 this, SLOT(checkEnabled()));
106         connect(headerBorderBelowCB, SIGNAL(clicked()),
107                 this, SLOT(checkEnabled()));
108         connect(firstheaderStatusCB, SIGNAL(clicked()),
109                 this, SLOT(checkEnabled()));
110         connect(firstheaderBorderAboveCB, SIGNAL(clicked()),
111                 this, SLOT(checkEnabled()));
112         connect(firstheaderBorderBelowCB, SIGNAL(clicked()),
113                 this, SLOT(checkEnabled()));
114         connect(firstheaderNoContentsCB, SIGNAL(clicked()),
115                 this, SLOT(checkEnabled()));
116         connect(footerStatusCB, SIGNAL(clicked()),
117                 this, SLOT(checkEnabled()));
118         connect(footerBorderAboveCB, SIGNAL(clicked()),
119                 this, SLOT(checkEnabled()));
120         connect(footerBorderBelowCB, SIGNAL(clicked()),
121                 this, SLOT(checkEnabled()));
122         connect(lastfooterStatusCB, SIGNAL(clicked()),
123                 this, SLOT(checkEnabled()));
124         connect(lastfooterBorderAboveCB, SIGNAL(clicked()),
125                 this, SLOT(checkEnabled()));
126         connect(lastfooterBorderBelowCB, SIGNAL(clicked()),
127                 this, SLOT(checkEnabled()));
128         connect(lastfooterNoContentsCB, SIGNAL(clicked()),
129                 this, SLOT(checkEnabled()));
130         connect(captionStatusCB, SIGNAL(clicked()),
131                 this, SLOT(checkEnabled()));
132         connect(specialAlignmentED, SIGNAL(textEdited(const QString &)),
133                 this, SLOT(checkEnabled()));
134         connect(columnWidthED, SIGNAL(textEdited(const QString &)),
135                 this, SLOT(checkEnabled()));
136         connect(columnWidthUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
137                 this, SLOT(checkEnabled()));
138         connect(borders, SIGNAL(topSet(bool)),
139                 this, SLOT(checkEnabled()));
140         connect(borders, SIGNAL(bottomSet(bool)),
141                 this, SLOT(checkEnabled()));
142         connect(borders, SIGNAL(rightSet(bool)),
143                 this, SLOT(checkEnabled()));
144         connect(borders, SIGNAL(leftSet(bool)),
145                 this, SLOT(checkEnabled()));
146         connect(rotateTabularCB, SIGNAL(clicked()),
147                 this, SLOT(checkEnabled()));
148         connect(rotateTabularAngleSB, SIGNAL(valueChanged(int)),
149                 this, SLOT(checkEnabled()));
150         connect(rotateCellCB, SIGNAL(clicked()),
151                 this, SLOT(checkEnabled()));
152         connect(rotateCellAngleSB, SIGNAL(valueChanged(int)),
153                 this, SLOT(checkEnabled()));
154         connect(TableAlignCO, SIGNAL(activated(int)),
155                 this, SLOT(checkEnabled()));
156         connect(longTabularCB, SIGNAL(clicked()),
157                 this, SLOT(checkEnabled()));
158         connect(leftRB, SIGNAL(clicked()),
159                 this, SLOT(checkEnabled()));
160         connect(centerRB, SIGNAL(clicked()),
161                 this, SLOT(checkEnabled()));
162         connect(rightRB, SIGNAL(clicked()),
163                 this, SLOT(checkEnabled()));
164         connect(tabularWidthED, SIGNAL(textEdited(const QString &)),
165                 this, SLOT(checkEnabled()));
166
167         decimalPointED->setInputMask("X; ");
168         decimalPointED->setMaxLength(1);
169
170         // initialize the length validator
171         addCheckedWidget(columnWidthED, columnWidthLA);
172         addCheckedWidget(multirowOffsetED, multirowOffsetLA);
173         addCheckedWidget(topspaceED, topspaceLA);
174         addCheckedWidget(bottomspaceED, bottomspaceLA);
175         addCheckedWidget(interlinespaceED, interlinespaceLA);
176         addCheckedWidget(tabularWidthED, tabularWidthLA);
177 }
178
179
180 void GuiTabular::on_topspaceCO_activated(int index)
181 {
182         bool const enable = (index == 2);
183         topspaceED->setEnabled(enable);
184         topspaceUnitLC->setEnabled(enable);
185 }
186
187
188 void GuiTabular::on_bottomspaceCO_activated(int index)
189 {
190         bool const enable = (index == 2);
191         bottomspaceED->setEnabled(enable);
192         bottomspaceUnitLC->setEnabled(enable);
193 }
194
195
196 void GuiTabular::on_interlinespaceCO_activated(int index)
197 {
198         bool const enable = (index == 2);
199         interlinespaceED->setEnabled(enable);
200         interlinespaceUnitLC->setEnabled(enable);
201 }
202
203
204 void GuiTabular::enableWidgets() const
205 {
206         // if there is a LaTeX argument, the width and alignment will be overwritten
207         // therefore disable them in this case
208         columnWidthED->setEnabled(specialAlignmentED->text().isEmpty());
209         columnWidthUnitLC->setEnabled(specialAlignmentED->text().isEmpty());
210         // if the column has a width, multirows are always left-aligned
211         // therefore disable hAlignCB in this case
212         hAlignCO->setEnabled(!(multirowCB->isChecked()
213                 && !widgetsToLength(columnWidthED, columnWidthUnitLC).empty())
214                 && specialAlignmentED->text().isEmpty());
215         // decimal alignment is only possible for non-multicol and non-multirow cells
216         if ((multicolumnCB->isChecked() || multirowCB->isChecked())
217                 && hAlignCO->findData(toqstr("decimal")))
218                 hAlignCO->removeItem(hAlignCO->findData(toqstr("decimal")));
219         else if (!multicolumnCB->isChecked() && !multirowCB->isChecked()
220                 && hAlignCO->findData(toqstr("decimal")) == -1)
221                 hAlignCO->addItem(qt_("At Decimal Separator"), toqstr("decimal"));
222         bool const dalign =
223                 hAlignCO->itemData(hAlignCO->currentIndex()).toString() == QString("decimal");
224         decimalPointED->setEnabled(dalign);
225         decimalLA->setEnabled(dalign);
226
227         bool const setwidth = TableAlignCO->currentText() == qt_("Middle")
228                 && !longTabularCB->isChecked();
229         tabularWidthLA->setEnabled(setwidth);
230         tabularWidthED->setEnabled(setwidth);
231         tabularWidthUnitLC->setEnabled(setwidth);
232
233         rotateTabularAngleSB->setEnabled(rotateTabularCB->isChecked());
234         rotateCellAngleSB->setEnabled(rotateCellCB->isChecked());
235
236         bool const enable_valign =
237                 !multirowCB->isChecked()
238                 && !widgetsToLength(columnWidthED, columnWidthUnitLC).empty()
239                 && specialAlignmentED->text().isEmpty();
240         vAlignCO->setEnabled(enable_valign);
241         vAlignLA->setEnabled(enable_valign);
242
243         topspaceED->setEnabled(topspaceCO->currentIndex() == 2);
244         topspaceED->setEnabled(topspaceCO->currentIndex() == 2);
245         topspaceUnitLC->setEnabled(topspaceCO->currentIndex() == 2);
246         bottomspaceED->setEnabled(bottomspaceCO->currentIndex() == 2);
247         bottomspaceUnitLC->setEnabled(bottomspaceCO->currentIndex() == 2);
248         interlinespaceED->setEnabled(interlinespaceCO->currentIndex() == 2);
249         interlinespaceUnitLC->setEnabled(interlinespaceCO->currentIndex() == 2);
250
251         // setting as longtable is not allowed when table is inside a float
252         bool const is_tabular_star = !tabularWidthED->text().isEmpty();
253         longTabularCB->setEnabled(!is_tabular_star && funcEnabled(Tabular::SET_LONGTABULAR));
254         bool const longtabular = longTabularCB->isChecked();
255         longtableGB->setEnabled(true);
256         newpageCB->setEnabled(longtabular);
257         alignmentGB->setEnabled(longtabular);
258         // longtables and tabular* cannot have a vertical alignment
259         TableAlignLA->setDisabled(is_tabular_star || longtabular);
260         TableAlignCO->setDisabled(is_tabular_star || longtabular);
261         // longtable cannot be rotated (with rotating package)
262         // FIXME: Add support for [pdf]lscape
263         rotateTabularCB->setDisabled(longtabular);
264         rotateTabularLA->setDisabled(longtabular);
265         // this one would also be disabled with [pdf]lscape
266         rotateTabularAngleSB->setDisabled(longtabular);
267
268         // FIXME: This Dialog is really horrible, disabling/enabling a checkbox
269         // depending on the cursor position is very very unintuitive...
270         // We need some edit boxes to show which rows are header/footer/etc
271         // without having to move the cursor first.
272         headerStatusCB->setEnabled(longtabular
273                 && (headerStatusCB->isChecked() ?
274                     funcEnabled(Tabular::UNSET_LTHEAD) :
275                     funcEnabled(Tabular::SET_LTHEAD)));
276         headerBorderAboveCB->setEnabled(longtabular
277                 && headerStatusCB->isChecked());
278         headerBorderBelowCB->setEnabled(longtabular
279                 && headerStatusCB->isChecked());
280
281         // first header can only be suppressed when there is a header
282         // firstheader_suppressable_ is set in paramsToDialog
283         firstheaderNoContentsCB->setEnabled(longtabular && firstheader_suppressable_);
284         // check if setting a first header is allowed
285         // additionally check firstheaderNoContentsCB because when this is
286         // the case a first header makes no sense
287         firstheaderStatusCB->setEnabled((firstheaderStatusCB->isChecked() ?
288                    funcEnabled(Tabular::UNSET_LTFIRSTHEAD) :
289                    funcEnabled(Tabular::SET_LTFIRSTHEAD))
290                 && longtabular && !firstheaderNoContentsCB->isChecked());
291         firstheaderBorderAboveCB->setEnabled(longtabular
292                 && firstheaderStatusCB->isChecked());
293         firstheaderBorderBelowCB->setEnabled(longtabular
294                 && firstheaderStatusCB->isChecked());
295
296         footerStatusCB->setEnabled(longtabular
297                 && (footerStatusCB->isChecked() ?
298                     funcEnabled(Tabular::UNSET_LTFOOT) :
299                     funcEnabled(Tabular::SET_LTFOOT)));
300         footerBorderAboveCB->setEnabled(longtabular
301                 && footerBorderAboveCB->isChecked());
302         footerBorderBelowCB->setEnabled(longtabular
303                 && footerBorderAboveCB->isChecked());
304
305         // last footer can only be suppressed when there is a footer
306         // lastfooter_suppressable_ is set in paramsToDialog
307         lastfooterNoContentsCB->setEnabled(longtabular && lastfooter_suppressable_);
308         // check if setting a last footer is allowed
309         // additionally check lastfooterNoContentsCB because when this is
310         // the case a last footer makes no sense
311         lastfooterStatusCB->setEnabled((lastfooterStatusCB->isChecked() ?
312                    funcEnabled(Tabular::UNSET_LTLASTFOOT) :
313                    funcEnabled(Tabular::SET_LTLASTFOOT))
314                 && longtabular && !lastfooterNoContentsCB->isChecked());
315         lastfooterBorderAboveCB->setEnabled(longtabular
316                 && lastfooterBorderAboveCB->isChecked());
317         lastfooterBorderBelowCB->setEnabled(longtabular
318                 && lastfooterBorderAboveCB->isChecked());
319
320         captionStatusCB->setEnabled(funcEnabled(Tabular::TOGGLE_LTCAPTION)
321                 && longtabular);
322
323         multicolumnCB->setEnabled(funcEnabled(Tabular::MULTICOLUMN)
324                 && !dalign && !multirowCB->isChecked());
325         multirowCB->setEnabled(funcEnabled(Tabular::MULTIROW)
326                 && !dalign && !multicolumnCB->isChecked());
327         bool const enable_mr = multirowCB->isChecked();
328         multirowOffsetLA->setEnabled(enable_mr);
329         multirowOffsetED->setEnabled(enable_mr);
330         multirowOffsetUnitLC->setEnabled(enable_mr);
331
332         // Vertical lines cannot be set in formal tables
333         borders->setLeftEnabled(!booktabsRB->isChecked());
334         borders->setRightEnabled(!booktabsRB->isChecked());
335 }
336
337
338 void GuiTabular::checkEnabled()
339 {
340         enableWidgets();
341         changed();
342 }
343
344
345 void GuiTabular::borderSet_clicked()
346 {
347         borders->setTop(true);
348         borders->setBottom(true);
349         borders->setLeft(true);
350         borders->setRight(true);
351         // repaint the setborder widget
352         borders->update();
353         checkEnabled();
354 }
355
356
357 void GuiTabular::borderUnset_clicked()
358 {
359         borders->setTop(false);
360         borders->setBottom(false);
361         borders->setLeft(false);
362         borders->setRight(false);
363         // repaint the setborder widget
364         borders->update();
365         checkEnabled();
366 }
367
368
369 static void setParam(string & param_str, Tabular::Feature f, string const & arg = string())
370 {
371         param_str += ' ';
372         param_str += featureAsString(f) + ' ' + arg;
373 }
374
375
376 void GuiTabular::setHAlign(string & param_str) const
377 {
378         Tabular::Feature num = Tabular::ALIGN_LEFT;
379         Tabular::Feature multi_num = Tabular::M_ALIGN_LEFT;
380         string const align =
381                 fromqstr(hAlignCO->itemData(hAlignCO->currentIndex()).toString());
382         if (align == "left") {
383                 num = Tabular::ALIGN_LEFT;
384                 multi_num = Tabular::M_ALIGN_LEFT;
385         } else if (align == "center") {
386                 num = Tabular::ALIGN_CENTER;
387                 multi_num = Tabular::M_ALIGN_CENTER;
388         } else if (align == "right") {
389                 num = Tabular::ALIGN_RIGHT;
390                 multi_num = Tabular::M_ALIGN_RIGHT;
391         } else if (align == "justified") {
392                 num = Tabular::ALIGN_BLOCK;
393                 //multi_num: no equivalent
394         } else if (align == "decimal") {
395                 num = Tabular::ALIGN_DECIMAL;
396                 //multi_num: no equivalent
397         }
398
399         if (multicolumnCB->isChecked())
400                 setParam(param_str, multi_num);
401         else
402                 setParam(param_str, num);
403 }
404
405
406 void GuiTabular::setVAlign(string & param_str) const
407 {
408         int const align = vAlignCO->currentIndex();
409         enum VALIGN { TOP, MIDDLE, BOTTOM };
410         VALIGN v = TOP;
411
412         switch (align) {
413                 case 0: v = TOP; break;
414                 case 1: v = MIDDLE; break;
415                 case 2: v = BOTTOM; break;
416         }
417
418         Tabular::Feature num = Tabular::VALIGN_MIDDLE;
419         Tabular::Feature multi_num = Tabular::M_VALIGN_MIDDLE;
420
421         switch (v) {
422                 case TOP:
423                         num = Tabular::VALIGN_TOP;
424                         multi_num = Tabular::M_VALIGN_TOP;
425                         break;
426                 case MIDDLE:
427                         num = Tabular::VALIGN_MIDDLE;
428                         multi_num = Tabular::M_VALIGN_MIDDLE;
429                         break;
430                 case BOTTOM:
431                         num = Tabular::VALIGN_BOTTOM;
432                         multi_num = Tabular::M_VALIGN_BOTTOM;
433                         break;
434         }
435         if (multicolumnCB->isChecked() || multirowCB->isChecked())
436                 setParam(param_str, multi_num);
437         else
438                 setParam(param_str, num);
439 }
440
441
442 void GuiTabular::setTableAlignment(string & param_str) const
443 {
444         int const align = TableAlignCO->currentIndex();
445         switch (align) {
446                 case 0: setParam(param_str, Tabular::TABULAR_VALIGN_TOP);
447                         break;
448                 case 1: setParam(param_str, Tabular::TABULAR_VALIGN_MIDDLE);
449                         break;
450                 case 2: setParam(param_str, Tabular::TABULAR_VALIGN_BOTTOM);
451                         break;
452         }
453 }
454
455
456 docstring GuiTabular::dialogToParams() const
457 {
458         string param_str = "tabular";
459
460         // table width
461         string tabwidth = widgetsToLength(tabularWidthED, tabularWidthUnitLC);
462         if (tabwidth.empty())
463                 tabwidth = "0pt";
464         setParam(param_str, Tabular::SET_TABULAR_WIDTH, tabwidth);
465
466         // apply the fixed width values
467         // this must be done before applying the column alignment
468         // because its value influences the alignment of multirow cells
469         string width = widgetsToLength(columnWidthED, columnWidthUnitLC);
470         if (width.empty())
471                 width = "0pt";
472         if (multicolumnCB->isChecked())
473                 setParam(param_str, Tabular::SET_MPWIDTH, width);
474         else
475                 setParam(param_str, Tabular::SET_PWIDTH, width);
476
477         // apply the column alignment
478         // multirows inherit the alignment from the column; if a column width
479         // is set, multirows are always left-aligned so that in this case
480         // its alignment must not be applied (see bug #8084)
481         if (!(multirowCB->isChecked() && width != "0pt"))
482                 setHAlign(param_str);
483
484         // SET_DECIMAL_POINT must come after setHAlign() (ALIGN_DECIMAL)
485         string decimal_point = fromqstr(decimalPointED->text());
486         if (decimal_point.empty())
487                 decimal_point = lyxrc.default_decimal_point;
488         setParam(param_str, Tabular::SET_DECIMAL_POINT, decimal_point);
489
490         setVAlign(param_str);
491         setTableAlignment(param_str);
492         //
493         if (booktabsRB->isChecked())
494                 setParam(param_str, Tabular::SET_BOOKTABS);
495         else
496                 setParam(param_str, Tabular::UNSET_BOOKTABS);
497
498         //
499         switch (topspaceCO->currentIndex()) {
500                 case 0:
501                         setParam(param_str, Tabular::SET_TOP_SPACE, "none");
502                         break;
503                 case 1:
504                         setParam(param_str, Tabular::SET_TOP_SPACE, "default");
505                         break;
506                 case 2:
507                         if (!topspaceED->text().isEmpty())
508                                 setParam(param_str, Tabular::SET_TOP_SPACE,
509                                          widgetsToLength(topspaceED, topspaceUnitLC));
510                         break;
511         }
512
513         //
514         switch (bottomspaceCO->currentIndex()) {
515                 case 0:
516                         setParam(param_str, Tabular::SET_BOTTOM_SPACE, "none");
517                         break;
518                 case 1:
519                         setParam(param_str, Tabular::SET_BOTTOM_SPACE, "default");
520                         break;
521                 case 2:
522                         if (!bottomspaceED->text().isEmpty())
523                                 setParam(param_str, Tabular::SET_BOTTOM_SPACE,
524                                         widgetsToLength(bottomspaceED,
525                                                         bottomspaceUnitLC));
526                         break;
527         }
528
529         //
530         switch (interlinespaceCO->currentIndex()) {
531                 case 0:
532                         setParam(param_str, Tabular::SET_INTERLINE_SPACE, "none");
533                         break;
534                 case 1:
535                         setParam(param_str, Tabular::SET_INTERLINE_SPACE, "default");
536                         break;
537                 case 2:
538                         if (!interlinespaceED->text().isEmpty())
539                                 setParam(param_str, Tabular::SET_INTERLINE_SPACE,
540                                         widgetsToLength(interlinespaceED,
541                                                         interlinespaceUnitLC));
542                         break;
543         }
544
545         //
546         if (borders->getTop() && borders->getBottom() && borders->getLeft()
547                 && borders->getRight())
548                 setParam(param_str, Tabular::SET_ALL_LINES);
549         else if (!borders->getTop() && !borders->getBottom() && !borders->getLeft()
550                 && !borders->getRight())
551                 setParam(param_str, Tabular::UNSET_ALL_LINES);
552         else {
553                 setParam(param_str, Tabular::SET_LINE_LEFT,
554                          borders->getLeft() ? "true" : "false");
555                 setParam(param_str, Tabular::SET_LINE_RIGHT,
556                          borders->getRight() ? "true" : "false");
557                 setParam(param_str, Tabular::SET_LINE_TOP,
558                          borders->getTop() ? "true" : "false");
559                 setParam(param_str, Tabular::SET_LINE_BOTTOM,
560                          borders->getBottom() ? "true" : "false");
561         }
562
563         // apply the special alignment
564         string special = fromqstr(specialAlignmentED->text());
565         if (special.empty())
566                 special = "none";
567         if (multicolumnCB->isChecked())
568                 setParam(param_str, Tabular::SET_SPECIAL_MULTICOLUMN, special);
569         else
570                 setParam(param_str, Tabular::SET_SPECIAL_COLUMN, special);
571
572         //
573         if (multicolumnCB->isChecked())
574                 setParam(param_str, Tabular::SET_MULTICOLUMN);
575         else
576                 setParam(param_str, Tabular::UNSET_MULTICOLUMN);
577
578         // apply the multirow offset
579         string mroffset = widgetsToLength(multirowOffsetED, multirowOffsetUnitLC);
580         if (mroffset.empty())
581                 mroffset = "0pt";
582         if (multirowCB->isChecked())
583                 setParam(param_str, Tabular::SET_MROFFSET, mroffset);
584         //
585         if (multirowCB->isChecked())
586                 setParam(param_str, Tabular::SET_MULTIROW);
587         else
588                 setParam(param_str, Tabular::UNSET_MULTIROW);
589         // store the table rotation angle
590         string const tabular_angle = convert<string>(rotateTabularAngleSB->value());
591         if (rotateTabularCB->isChecked())
592                 setParam(param_str, Tabular::SET_ROTATE_TABULAR, tabular_angle);
593         else
594                 setParam(param_str, Tabular::UNSET_ROTATE_TABULAR, tabular_angle);
595         // store the cell rotation angle
596         string const cell_angle = convert<string>(rotateCellAngleSB->value());
597         if (rotateCellCB->isChecked())
598                 setParam(param_str, Tabular::SET_ROTATE_CELL, cell_angle);
599         else
600                 setParam(param_str, Tabular::UNSET_ROTATE_CELL, cell_angle);
601         //
602         if (longTabularCB->isChecked())
603                 setParam(param_str, Tabular::SET_LONGTABULAR);
604         else
605                 setParam(param_str, Tabular::UNSET_LONGTABULAR);
606         //
607         if (newpageCB->isChecked())
608                 setParam(param_str, Tabular::SET_LTNEWPAGE);
609     else
610                 setParam(param_str, Tabular::UNSET_LTNEWPAGE);
611         //
612         if (captionStatusCB->isChecked())
613                 setParam(param_str, Tabular::SET_LTCAPTION);
614         else
615                 setParam(param_str, Tabular::UNSET_LTCAPTION);
616         //
617         if (headerStatusCB->isChecked())
618                 setParam(param_str, Tabular::SET_LTHEAD, "none");
619         else
620                 setParam(param_str, Tabular::UNSET_LTHEAD, "none");
621         //
622         if (headerBorderAboveCB->isChecked())
623                 setParam(param_str, Tabular::SET_LTHEAD, "dl_above");
624         else
625                 setParam(param_str, Tabular::UNSET_LTHEAD, "dl_above");
626         //
627         if (headerBorderBelowCB->isChecked())
628                 setParam(param_str, Tabular::SET_LTHEAD, "dl_below");
629         else
630                 setParam(param_str, Tabular::UNSET_LTHEAD, "dl_below");
631         if (firstheaderBorderAboveCB->isChecked())
632                 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "dl_above");
633         else
634                 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "dl_above");
635         if (firstheaderBorderBelowCB->isChecked())
636                 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "dl_below");
637         else
638                 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "dl_below");
639         if (firstheaderStatusCB->isChecked())
640                 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "none");
641         else
642                 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "none");
643         if (firstheaderNoContentsCB->isChecked())
644                 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "empty");
645         else
646                 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "empty");
647         if (footerStatusCB->isChecked())
648                 setParam(param_str, Tabular::SET_LTFOOT, "none");
649         else
650                 setParam(param_str, Tabular::UNSET_LTFOOT, "none");
651         if (footerBorderAboveCB->isChecked())
652                 setParam(param_str, Tabular::SET_LTFOOT, "dl_above");
653         else
654                 setParam(param_str, Tabular::UNSET_LTFOOT, "dl_above");
655         if (footerBorderBelowCB->isChecked())
656                 setParam(param_str, Tabular::SET_LTFOOT, "dl_below");
657         else
658                 setParam(param_str, Tabular::UNSET_LTFOOT, "dl_below");
659         if (lastfooterStatusCB->isChecked())
660                 setParam(param_str, Tabular::SET_LTLASTFOOT, "none");
661         else
662                 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "none");
663         if (lastfooterBorderAboveCB->isChecked())
664                 setParam(param_str, Tabular::SET_LTLASTFOOT, "dl_above");
665         else
666                 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "dl_above");
667         if (lastfooterBorderBelowCB->isChecked())
668                 setParam(param_str, Tabular::SET_LTLASTFOOT, "dl_below");
669         else
670                 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "dl_below");
671         if (lastfooterNoContentsCB->isChecked())
672                 setParam(param_str, Tabular::SET_LTLASTFOOT, "empty");
673         else
674                 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "empty");
675
676         if (leftRB->isChecked())
677                 setParam(param_str, Tabular::LONGTABULAR_ALIGN_LEFT);
678         else if (centerRB->isChecked())
679                 setParam(param_str, Tabular::LONGTABULAR_ALIGN_CENTER);
680         else if (rightRB->isChecked())
681                 setParam(param_str, Tabular::LONGTABULAR_ALIGN_RIGHT);
682
683         return from_utf8(param_str);
684 }
685
686
687 static Length getColumnPWidth(Tabular const & t, size_t cell)
688 {
689         return t.column_info[t.cellColumn(cell)].p_width;
690 }
691
692
693 static Length getMColumnPWidth(Tabular const & t, size_t cell)
694 {
695         if (t.isMultiColumn(cell) || t.isMultiRow(cell))
696                 return t.cellInfo(cell).p_width;
697         return Length();
698 }
699
700
701 static Length getMROffset(Tabular const & t, size_t cell)
702 {
703         if (t.isMultiRow(cell))
704                 return t.cellInfo(cell).mroffset;
705         return Length();
706 }
707
708
709 static docstring getAlignSpecial(Tabular const & t, size_t cell, int what)
710 {
711         if (what == Tabular::SET_SPECIAL_MULTICOLUMN)
712                 return t.cellInfo(cell).align_special;
713         return t.column_info[t.cellColumn(cell)].align_special;
714 }
715
716
717 void GuiTabular::paramsToDialog(Inset const * inset)
718 {
719         InsetTabular const * itab = static_cast<InsetTabular const *>(inset);
720         // Copy Tabular of current inset.
721         Tabular const & tabular = itab->tabular;
722
723         BufferView const * bv = guiApp->currentView()->currentBufferView();
724         size_t const cell = bv->cursor().idx();
725
726         Tabular::row_type const row = tabular.cellRow(cell);
727         Tabular::col_type const col = tabular.cellColumn(cell);
728
729         tabularRowED->setText(QString::number(row + 1));
730         tabularColumnED->setText(QString::number(col + 1));
731
732         bool const multicol = tabular.isMultiColumn(cell);
733         multicolumnCB->setChecked(multicol);
734
735         bool const multirow = tabular.isMultiRow(cell);
736         multirowCB->setChecked(multirow);
737
738         rotateCellCB->setChecked(tabular.getRotateCell(cell) != 0);
739         if (rotateCellCB->isChecked()) {
740                 if (tabular.getRotateCell(cell) != 0)
741                         rotateCellAngleSB->setValue(tabular.getRotateCell(cell));
742                 else
743                         rotateCellAngleSB->setValue(90);
744         }
745
746         rotateTabularCB->setChecked(tabular.rotate != 0);
747         if (rotateTabularCB->isChecked())
748                 rotateTabularAngleSB->setValue(tabular.rotate != 0 ? tabular.rotate : 90);
749
750         longTabularCB->setChecked(tabular.is_long_tabular);
751
752         borders->setTop(tabular.topLine(cell));
753         borders->setBottom(tabular.bottomLine(cell));
754         borders->setLeft(tabular.leftLine(cell));
755         borders->setRight(tabular.rightLine(cell));
756         // repaint the setborder widget
757         borders->update();
758
759         Length::UNIT const default_unit = Length::defaultUnit();
760
761         ///////////////////////////////////
762         // Set width and alignment
763
764         Length const tabwidth = tabular.tabularWidth();
765         if (tabwidth.zero()
766             && !(tabularWidthED->hasFocus() && tabularWidthED->text() == "0"))
767                 tabularWidthED->clear();
768         else
769                 lengthToWidgets(tabularWidthED, tabularWidthUnitLC,
770                         tabwidth.asString(), default_unit);
771
772         Length pwidth;
773         docstring special;
774         if (multicol) {
775                 special = getAlignSpecial(tabular, cell,
776                         Tabular::SET_SPECIAL_MULTICOLUMN);
777                 pwidth = getMColumnPWidth(tabular, cell);
778         } else {
779                 special = getAlignSpecial(tabular, cell,
780                         Tabular::SET_SPECIAL_COLUMN);
781                 pwidth = getColumnPWidth(tabular, cell);
782         }
783         string colwidth;
784         if (pwidth.zero()
785             && !(columnWidthED->hasFocus() && columnWidthED->text() == "0"))
786                 columnWidthED->clear();
787         else {
788                 colwidth = pwidth.asString();
789                 lengthToWidgets(columnWidthED, columnWidthUnitLC,
790                         colwidth, default_unit);
791         }
792         Length mroffset;
793         if (multirow)
794                 mroffset = getMROffset(tabular, cell);
795         string offset;
796         if (mroffset.zero()
797             && !(multirowOffsetED->hasFocus() && multirowOffsetED->text() == "0"))
798                 multirowOffsetED->clear();
799         else {
800                 offset = mroffset.asString();
801                 lengthToWidgets(multirowOffsetED, multirowOffsetUnitLC,
802                         offset, default_unit);
803         }
804         specialAlignmentED->setText(toqstr(special));
805         ///////////////////////////////////
806
807
808         borderDefaultRB->setChecked(!tabular.use_booktabs);
809         booktabsRB->setChecked(tabular.use_booktabs);
810
811         if (tabular.row_info[row].top_space.empty()
812             && !tabular.row_info[row].top_space_default) {
813                 topspaceCO->setCurrentIndex(0);
814         } else if (tabular.row_info[row].top_space_default) {
815                 topspaceCO->setCurrentIndex(1);
816         } else {
817                 topspaceCO->setCurrentIndex(2);
818                 lengthToWidgets(topspaceED,
819                                 topspaceUnitLC,
820                                 tabular.row_info[row].top_space.asString(),
821                                 default_unit);
822         }
823
824         if (tabular.row_info[row].bottom_space.empty()
825             && !tabular.row_info[row].bottom_space_default) {
826                 bottomspaceCO->setCurrentIndex(0);
827         } else if (tabular.row_info[row].bottom_space_default) {
828                 bottomspaceCO->setCurrentIndex(1);
829         } else {
830                 bottomspaceCO->setCurrentIndex(2);
831                 lengthToWidgets(bottomspaceED,
832                                 bottomspaceUnitLC,
833                                 tabular.row_info[row].bottom_space.asString(),
834                                 default_unit);
835         }
836
837         if (tabular.row_info[row].interline_space.empty()
838             && !tabular.row_info[row].interline_space_default) {
839                 interlinespaceCO->setCurrentIndex(0);
840         } else if (tabular.row_info[row].interline_space_default) {
841                 interlinespaceCO->setCurrentIndex(1);
842         } else {
843                 interlinespaceCO->setCurrentIndex(2);
844                 lengthToWidgets(interlinespaceED,
845                                 interlinespaceUnitLC,
846                                 tabular.row_info[row].interline_space.asString(),
847                                 default_unit);
848         }
849
850         hAlignCO->clear();
851         hAlignCO->addItem(qt_("Left"), toqstr("left"));
852         hAlignCO->addItem(qt_("Center"), toqstr("center"));
853         hAlignCO->addItem(qt_("Right"), toqstr("right"));
854         if (!multicol && !pwidth.zero())
855                 hAlignCO->addItem(qt_("Justified"), toqstr("justified"));
856         if (!multicol && !multirow)
857                 hAlignCO->addItem(qt_("At Decimal Separator"), toqstr("decimal"));
858
859         string align;
860         switch (tabular.getAlignment(cell)) {
861                 case LYX_ALIGN_LEFT:
862                         align = "left";
863                         break;
864                 case LYX_ALIGN_CENTER:
865                         align = "center";
866                         break;
867                 case LYX_ALIGN_RIGHT:
868                         align = "right";
869                         break;
870                 case LYX_ALIGN_BLOCK:
871                 {
872                         if (!multicol && !pwidth.zero())
873                                 align = "justified";
874                         break;
875                 }
876                 case LYX_ALIGN_DECIMAL:
877                 {
878                         if (!multicol && !multirow)
879                                 align = "decimal";
880                         break;
881                 }
882                 default:
883                         // we should never end up here
884                         break;
885         }
886         hAlignCO->setCurrentIndex(hAlignCO->findData(toqstr(align)));
887
888         //
889         QString decimal_point = toqstr(tabular.column_info[col].decimal_point);
890         if (decimal_point.isEmpty())
891                 decimal_point = toqstr(from_utf8(lyxrc.default_decimal_point));
892         decimalPointED->setText(decimal_point);
893
894         int valign = 0;
895         switch (tabular.getVAlignment(cell)) {
896         case Tabular::LYX_VALIGN_TOP:
897                 valign = 0;
898                 break;
899         case Tabular::LYX_VALIGN_MIDDLE:
900                 valign = 1;
901                 break;
902         case Tabular::LYX_VALIGN_BOTTOM:
903                 valign = 2;
904                 break;
905         default:
906                 valign = 0;
907                 break;
908         }
909         if (pwidth.zero())
910                 valign = 0;
911         vAlignCO->setCurrentIndex(valign);
912
913         int tableValign = 1;
914         switch (tabular.tabular_valignment) {
915         case Tabular::LYX_VALIGN_TOP:
916                 tableValign = 0;
917                 break;
918         case Tabular::LYX_VALIGN_MIDDLE:
919                 tableValign = 1;
920                 break;
921         case Tabular::LYX_VALIGN_BOTTOM:
922                 tableValign = 2;
923                 break;
924         default:
925                 tableValign = 0;
926                 break;
927         }
928         TableAlignCO->setCurrentIndex(tableValign);
929
930         if (!tabular.is_long_tabular) {
931                 headerStatusCB->setChecked(false);
932                 headerBorderAboveCB->setChecked(false);
933                 headerBorderBelowCB->setChecked(false);
934                 firstheaderStatusCB->setChecked(false);
935                 firstheaderBorderAboveCB->setChecked(false);
936                 firstheaderBorderBelowCB->setChecked(false);
937                 firstheaderNoContentsCB->setChecked(false);
938                 footerStatusCB->setChecked(false);
939                 footerBorderAboveCB->setChecked(false);
940                 footerBorderBelowCB->setChecked(false);
941                 lastfooterStatusCB->setChecked(false);
942                 lastfooterBorderAboveCB->setChecked(false);
943                 lastfooterBorderBelowCB->setChecked(false);
944                 lastfooterNoContentsCB->setChecked(false);
945                 newpageCB->setChecked(false);
946                 captionStatusCB->blockSignals(true);
947                 captionStatusCB->setChecked(false);
948                 captionStatusCB->blockSignals(false);
949                 checkEnabled();
950                 return;
951         } else {
952                 // longtables cannot have a vertical alignment
953                 TableAlignCO->setCurrentIndex(Tabular::LYX_VALIGN_MIDDLE);
954         }
955         switch (tabular.longtabular_alignment) {
956         case Tabular::LYX_LONGTABULAR_ALIGN_LEFT:
957                 leftRB->setChecked(true);
958                 break;
959         case Tabular::LYX_LONGTABULAR_ALIGN_CENTER:
960                 centerRB->setChecked(true);
961                 break;
962         case Tabular::LYX_LONGTABULAR_ALIGN_RIGHT:
963                 rightRB->setChecked(true);
964                 break;
965         default:
966                 centerRB->setChecked(true);
967                 break;
968         }
969         captionStatusCB->blockSignals(true);
970         captionStatusCB->setChecked(tabular.ltCaption(row));
971         captionStatusCB->blockSignals(false);
972
973         Tabular::ltType ltt;
974         bool use_empty;
975         bool row_set = tabular.getRowOfLTHead(row, ltt);
976         headerStatusCB->setChecked(row_set);
977         if (ltt.set) {
978                 headerBorderAboveCB->setChecked(ltt.topDL);
979                 headerBorderBelowCB->setChecked(ltt.bottomDL);
980                 use_empty = true;
981         } else {
982                 headerBorderAboveCB->setChecked(false);
983                 headerBorderBelowCB->setChecked(false);
984                 firstheaderNoContentsCB->setChecked(false);
985                 use_empty = false;
986         }
987
988         row_set = tabular.getRowOfLTFirstHead(row, ltt);
989         firstheaderStatusCB->setChecked(row_set);
990         if (ltt.set && (!ltt.empty || !use_empty)) {
991                 firstheaderBorderAboveCB->setChecked(ltt.topDL);
992                 firstheaderBorderBelowCB->setChecked(ltt.bottomDL);
993         } else {
994                 firstheaderBorderAboveCB->setChecked(false);
995                 firstheaderBorderBelowCB->setChecked(false);
996         }
997
998         row_set = tabular.getRowOfLTFoot(row, ltt);
999         footerStatusCB->setChecked(row_set);
1000         if (ltt.set) {
1001                 footerBorderAboveCB->setChecked(ltt.topDL);
1002                 footerBorderBelowCB->setChecked(ltt.bottomDL);
1003                 use_empty = true;
1004         } else {
1005                 footerBorderAboveCB->setChecked(false);
1006                 footerBorderBelowCB->setChecked(false);
1007                 lastfooterNoContentsCB->setChecked(false);
1008                 use_empty = false;
1009         }
1010
1011         row_set = tabular.getRowOfLTLastFoot(row, ltt);
1012         lastfooterStatusCB->setChecked(row_set);
1013         if (ltt.set && (!ltt.empty || !use_empty)) {
1014                 lastfooterBorderAboveCB->setChecked(ltt.topDL);
1015                 lastfooterBorderBelowCB->setChecked(ltt.bottomDL);
1016         } else {
1017                 lastfooterBorderAboveCB->setChecked(false);
1018                 lastfooterBorderBelowCB->setChecked(false);
1019         }
1020         newpageCB->setChecked(tabular.getLTNewPage(row));
1021
1022         // first header can only be suppressed when there is a header
1023         firstheader_suppressable_ = tabular.haveLTHead()
1024                         && !tabular.haveLTFirstHead();
1025         // last footer can only be suppressed when there is a footer
1026         lastfooter_suppressable_ = tabular.haveLTFoot()
1027                         && !tabular.haveLTLastFoot();
1028
1029         // after setting the features, check if they are enabled
1030         checkEnabled();
1031 }
1032
1033
1034 bool GuiTabular::checkWidgets(bool readonly) const
1035 {
1036         tabularRowED->setReadOnly(readonly);
1037         tabularColumnED->setReadOnly(readonly);
1038         tabularWidthED->setReadOnly(readonly);
1039         specialAlignmentED->setReadOnly(readonly);
1040         columnWidthED->setReadOnly(readonly);
1041         multirowOffsetED->setReadOnly(readonly);
1042         decimalPointED->setReadOnly(readonly);
1043
1044         if (readonly) {
1045                 multicolumnCB->setEnabled(false);
1046                 multirowCB->setEnabled(false);
1047                 rotateCellCB->setEnabled(false);
1048                 rotateCellAngleSB->setEnabled(false);
1049                 rotateTabularCB->setEnabled(false);
1050                 rotateTabularAngleSB->setEnabled(false);
1051                 longTabularCB->setEnabled(false);
1052                 borders->setEnabled(false);
1053                 tabularWidthUnitLC->setEnabled(false);
1054                 columnWidthUnitLC->setEnabled(false);
1055                 multirowOffsetUnitLC->setEnabled(false);
1056                 setBordersGB->setEnabled(false);
1057                 allBordersGB->setEnabled(false);
1058                 borderStyleGB->setEnabled(false);
1059                 booktabsRB->setEnabled(false);
1060                 topspaceCO->setEnabled(false);
1061                 topspaceUnitLC->setEnabled(false);
1062                 bottomspaceCO->setEnabled(false);
1063                 bottomspaceUnitLC->setEnabled(false);
1064                 interlinespaceCO->setEnabled(false);
1065                 interlinespaceUnitLC->setEnabled(false);
1066                 hAlignCO->setEnabled(false);
1067                 vAlignCO->setEnabled(false);
1068                 TableAlignCO->setEnabled(false);
1069                 longtableGB->setEnabled(false);
1070                 alignmentGB->setEnabled(false);
1071         } else
1072                 enableWidgets();
1073
1074         return InsetParamsWidget::checkWidgets();
1075 }
1076
1077
1078 bool GuiTabular::funcEnabled(Tabular::Feature f) const
1079 {
1080         FuncRequest r(LFUN_INSET_MODIFY, "tabular for-dialog" + featureAsString(f));
1081         return getStatus(r).enabled();
1082 }
1083
1084
1085 } // namespace frontend
1086 } // namespace lyx
1087
1088 #include "moc_GuiTabular.cpp"