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