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