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