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