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