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