]> git.lyx.org Git - features.git/blob - src/frontends/qt4/GuiTabular.cpp
GuiTabular.cpp: fix bug #8084
[features.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/debug.h"
35
36 #include <QCheckBox>
37 #include <QPushButton>
38 #include <QRadioButton>
39 #include <QLineEdit>
40
41 using namespace std;
42
43 namespace lyx {
44 namespace frontend {
45
46 GuiTabular::GuiTabular(QWidget * parent)
47         : InsetParamsWidget(parent)
48 {
49         setupUi(this);
50
51         tabularWidthED->setValidator(unsignedLengthValidator(tabularWidthED));
52         columnWidthED->setValidator(unsignedLengthValidator(columnWidthED));
53         multirowOffsetED->setValidator(new LengthValidator(multirowOffsetED));
54         topspaceED->setValidator(new LengthValidator(topspaceED));
55         bottomspaceED->setValidator(new LengthValidator(bottomspaceED));
56         interlinespaceED->setValidator(new LengthValidator(interlinespaceED));
57
58         tabularWidthUnitLC->setCurrentItem(Length::defaultUnit());
59         columnWidthUnitLC->setCurrentItem(Length::defaultUnit());
60         multirowOffsetUnitLC->setCurrentItem(Length::defaultUnit());
61         topspaceUnitLC->setCurrentItem(Length::defaultUnit());
62         bottomspaceUnitLC->setCurrentItem(Length::defaultUnit());
63         interlinespaceUnitLC->setCurrentItem(Length::defaultUnit());
64
65         connect(topspaceED, SIGNAL(textEdited(const QString &)),
66                 this, SLOT(checkEnabled()));
67         connect(topspaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
68                 this, SLOT(checkEnabled()));
69         connect(bottomspaceED, SIGNAL(textEdited(const QString &)),
70                 this, SLOT(checkEnabled()));
71         connect(bottomspaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
72                 this, SLOT(checkEnabled()));
73         connect(interlinespaceED, SIGNAL(textEdited(const QString &)),
74                 this, SLOT(checkEnabled()));
75         connect(interlinespaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
76                 this, SLOT(checkEnabled()));
77         connect(booktabsRB, SIGNAL(clicked(bool)),
78                 this, SLOT(checkEnabled()));
79         connect(borderDefaultRB, SIGNAL(clicked(bool)),
80                 this, SLOT(checkEnabled()));
81         connect(borderSetPB, SIGNAL(clicked()),
82                 this, SLOT(borderSet_clicked()));
83         connect(borderUnsetPB, SIGNAL(clicked()),
84                 this, SLOT(borderUnset_clicked()));
85         connect(hAlignCO, SIGNAL(activated(int)),
86                 this, SLOT(checkEnabled()));
87         connect(vAlignCO, SIGNAL(activated(int)),
88                 this, SLOT(checkEnabled()));
89         connect(multicolumnCB, SIGNAL(clicked()),
90                 this, SLOT(checkEnabled()));
91         connect(multirowCB, SIGNAL(clicked()),
92                 this, SLOT(checkEnabled()));
93         connect(multirowOffsetED, SIGNAL(textEdited(const QString &)),
94                 this, SLOT(checkEnabled()));
95         connect(multirowOffsetUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
96                 this, SLOT(checkEnabled()));
97         connect(newpageCB, SIGNAL(clicked()),
98                 this, SLOT(checkEnabled()));
99         connect(headerStatusCB, SIGNAL(clicked()),
100                 this, SLOT(checkEnabled()));
101         connect(headerBorderAboveCB, SIGNAL(clicked()),
102                 this, SLOT(checkEnabled()));
103         connect(headerBorderBelowCB, SIGNAL(clicked()),
104                 this, SLOT(checkEnabled()));
105         connect(firstheaderStatusCB, SIGNAL(clicked()),
106                 this, SLOT(checkEnabled()));
107         connect(firstheaderBorderAboveCB, SIGNAL(clicked()),
108                 this, SLOT(checkEnabled()));
109         connect(firstheaderBorderBelowCB, SIGNAL(clicked()),
110                 this, SLOT(checkEnabled()));
111         connect(firstheaderNoContentsCB, SIGNAL(clicked()),
112                 this, SLOT(checkEnabled()));
113         connect(footerStatusCB, SIGNAL(clicked()),
114                 this, SLOT(checkEnabled()));
115         connect(footerBorderAboveCB, SIGNAL(clicked()),
116                 this, SLOT(checkEnabled()));
117         connect(footerBorderBelowCB, SIGNAL(clicked()),
118                 this, SLOT(checkEnabled()));
119         connect(lastfooterStatusCB, SIGNAL(clicked()),
120                 this, SLOT(checkEnabled()));
121         connect(lastfooterBorderAboveCB, SIGNAL(clicked()),
122                 this, SLOT(checkEnabled()));
123         connect(lastfooterBorderBelowCB, SIGNAL(clicked()),
124                 this, SLOT(checkEnabled()));
125         connect(lastfooterNoContentsCB, SIGNAL(clicked()),
126                 this, SLOT(checkEnabled()));
127         connect(captionStatusCB, SIGNAL(clicked()),
128                 this, SLOT(checkEnabled()));
129         connect(specialAlignmentED, SIGNAL(editingFinished()),
130                 this, SLOT(checkEnabled()));
131         connect(columnWidthED, SIGNAL(textEdited(const QString &)),
132                 this, SLOT(checkEnabled()));
133         connect(columnWidthUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
134                 this, SLOT(checkEnabled()));
135         connect(borders, SIGNAL(topSet(bool)),
136                 this, SLOT(checkEnabled()));
137         connect(borders, SIGNAL(bottomSet(bool)),
138                 this, SLOT(checkEnabled()));
139         connect(borders, SIGNAL(rightSet(bool)),
140                 this, SLOT(checkEnabled()));
141         connect(borders, SIGNAL(leftSet(bool)),
142                 this, SLOT(checkEnabled()));
143         connect(rotateTabularCB, SIGNAL(clicked()),
144                 this, SLOT(checkEnabled()));
145         connect(rotateCellCB, SIGNAL(clicked()),
146                 this, SLOT(checkEnabled()));
147         connect(TableAlignCO, SIGNAL(activated(int)),
148                 this, SLOT(checkEnabled()));
149         connect(longTabularCB, SIGNAL(clicked()),
150                 this, SLOT(checkEnabled()));
151         connect(leftRB, SIGNAL(clicked()),
152                 this, SLOT(checkEnabled()));
153         connect(centerRB, SIGNAL(clicked()),
154                 this, SLOT(checkEnabled()));
155         connect(rightRB, SIGNAL(clicked()),
156                 this, SLOT(checkEnabled()));
157         connect(tabularWidthED, SIGNAL(textEdited(const QString &)),
158                 this, SLOT(checkEnabled()));
159
160         decimalPointED->setInputMask("X; ");
161         decimalPointED->setMaxLength(1);
162
163         // initialize the length validator
164         addCheckedWidget(columnWidthED, columnWidthLA);
165         addCheckedWidget(multirowOffsetED, multirowOffsetLA);
166         addCheckedWidget(topspaceED, topspaceLA);
167         addCheckedWidget(bottomspaceED, bottomspaceLA);
168         addCheckedWidget(interlinespaceED, interlinespaceLA);
169         addCheckedWidget(tabularWidthED, tabularWidthLA);
170 }
171
172
173 void GuiTabular::on_topspaceCO_activated(int index)
174 {
175         bool const enable = (index == 2);
176         topspaceED->setEnabled(enable);
177         topspaceUnitLC->setEnabled(enable);
178 }
179
180
181 void GuiTabular::on_bottomspaceCO_activated(int index)
182 {
183         bool const enable = (index == 2);
184         bottomspaceED->setEnabled(enable);
185         bottomspaceUnitLC->setEnabled(enable);
186 }
187
188
189 void GuiTabular::on_interlinespaceCO_activated(int index)
190 {
191         bool const enable = (index == 2);
192         interlinespaceED->setEnabled(enable);
193         interlinespaceUnitLC->setEnabled(enable);
194 }
195
196
197 void GuiTabular::checkEnabled()
198 {
199         // if there is a LaTeX argument, the width and alignment will be overwritten
200         // therefore disable them in this case
201         columnWidthED->setEnabled(specialAlignmentED->text().isEmpty());
202         // if the column has a width, multirows are always left-aligned
203         // therefore disable hAlignCB in this case
204         hAlignCO->setEnabled(!(multirowCB->isChecked()
205                 && !widgetsToLength(columnWidthED, columnWidthUnitLC).empty())
206                 && specialAlignmentED->text().isEmpty());
207         bool const dalign = 
208                 hAlignCO->itemData(hAlignCO->currentIndex()).toString() == QString("decimal");
209         decimalPointED->setEnabled(dalign);
210         decimalLA->setEnabled(dalign);
211
212         bool const setwidth = TableAlignCO->currentText() == qt_("Middle")
213                 && !longTabularCB->isChecked() && !rotateTabularCB->isChecked();
214         tabularWidthLA->setEnabled(setwidth);
215         tabularWidthED->setEnabled(setwidth);
216         tabularWidthUnitLC->setEnabled(setwidth);
217
218         bool const is_tabular_star = !tabularWidthED->text().isEmpty();
219         rotateTabularCB->setDisabled(is_tabular_star);
220
221         bool const enable_valign =
222                 !multirowCB->isChecked()
223                 && !widgetsToLength(columnWidthED, columnWidthUnitLC).empty()
224                 && specialAlignmentED->text().isEmpty();
225         vAlignCO->setEnabled(enable_valign);
226         vAlignLA->setEnabled(enable_valign);
227
228         topspaceED->setEnabled(topspaceCO->currentIndex() == 2);
229         topspaceED->setEnabled(topspaceCO->currentIndex() == 2);
230         topspaceUnitLC->setEnabled(topspaceCO->currentIndex() == 2);
231         bottomspaceED->setEnabled(bottomspaceCO->currentIndex() == 2);
232         bottomspaceUnitLC->setEnabled(bottomspaceCO->currentIndex() == 2);
233         interlinespaceED->setEnabled(interlinespaceCO->currentIndex() == 2);
234         interlinespaceUnitLC->setEnabled(interlinespaceCO->currentIndex() == 2);
235
236         // setting as longtable is not allowed when table is inside a float
237         longTabularCB->setEnabled(!is_tabular_star && funcEnabled(Tabular::SET_LONGTABULAR));
238         bool const longtabular = longTabularCB->isChecked();
239         longtableGB->setEnabled(true);
240         newpageCB->setEnabled(longtabular);
241         alignmentGB->setEnabled(longtabular);
242         // longtables and tabular* cannot have a vertical alignment
243         TableAlignLA->setDisabled(is_tabular_star || longtabular);
244         TableAlignCO->setDisabled(is_tabular_star || longtabular);
245
246         // FIXME: This Dialog is really horrible, disabling/enabling a checkbox
247         // depending on the cursor position is very very unintuitive...
248         // We need some edit boxes to show which rows are header/footer/etc
249         // without having to move the cursor first.
250         headerStatusCB->setEnabled(longtabular
251                 && (headerStatusCB->isChecked() ?
252                     funcEnabled(Tabular::UNSET_LTHEAD) :
253                     funcEnabled(Tabular::SET_LTHEAD)));
254         headerBorderAboveCB->setEnabled(longtabular
255                 && headerStatusCB->isChecked());
256         headerBorderBelowCB->setEnabled(longtabular
257                 && headerStatusCB->isChecked());
258
259         // first header can only be suppressed when there is a header
260         // firstheader_suppressable_ is set in paramsToDialog
261         firstheaderNoContentsCB->setEnabled(longtabular && firstheader_suppressable_);
262         // check if setting a first header is allowed
263         // additionally check firstheaderNoContentsCB because when this is
264         // the case a first header makes no sense
265         firstheaderStatusCB->setEnabled((firstheaderStatusCB->isChecked() ?
266                    funcEnabled(Tabular::UNSET_LTFIRSTHEAD) :
267                    funcEnabled(Tabular::SET_LTFIRSTHEAD))
268                 && longtabular && !firstheaderNoContentsCB->isChecked());
269         firstheaderBorderAboveCB->setEnabled(longtabular
270                 && firstheaderStatusCB->isChecked());
271         firstheaderBorderBelowCB->setEnabled(longtabular
272                 && firstheaderStatusCB->isChecked());
273
274         footerStatusCB->setEnabled(longtabular
275                 && (footerStatusCB->isChecked() ?
276                     funcEnabled(Tabular::UNSET_LTFOOT) :
277                     funcEnabled(Tabular::SET_LTFOOT)));
278         footerBorderAboveCB->setEnabled(longtabular
279                 && footerBorderAboveCB->isChecked());
280         footerBorderBelowCB->setEnabled(longtabular
281                 && footerBorderAboveCB->isChecked());
282
283         // last footer can only be suppressed when there is a footer
284         // lastfooter_suppressable_ is set in paramsToDialog
285         lastfooterNoContentsCB->setEnabled(longtabular && lastfooter_suppressable_);
286         // check if setting a last footer is allowed
287         // additionally check lastfooterNoContentsCB because when this is
288         // the case a last footer makes no sense
289         lastfooterStatusCB->setEnabled((lastfooterStatusCB->isChecked() ?
290                    funcEnabled(Tabular::UNSET_LTLASTFOOT) :
291                    funcEnabled(Tabular::SET_LTLASTFOOT))
292                 && longtabular && !lastfooterNoContentsCB->isChecked());
293         lastfooterBorderAboveCB->setEnabled(longtabular
294                 && lastfooterBorderAboveCB->isChecked());
295         lastfooterBorderBelowCB->setEnabled(longtabular
296                 && lastfooterBorderAboveCB->isChecked());
297
298         captionStatusCB->setEnabled(funcEnabled(Tabular::TOGGLE_LTCAPTION)
299                 && longtabular);
300
301         multicolumnCB->setEnabled(funcEnabled(Tabular::MULTICOLUMN));
302         multirowCB->setEnabled(funcEnabled(Tabular::MULTIROW));
303         bool const enable_mr = multirowCB->isChecked();
304         multirowOffsetLA->setEnabled(enable_mr);
305         multirowOffsetED->setEnabled(enable_mr);
306         multirowOffsetUnitLC->setEnabled(enable_mr);
307
308         changed();
309 }
310
311
312 void GuiTabular::borderSet_clicked()
313 {
314         borders->setTop(true);
315         borders->setBottom(true);
316         borders->setLeft(true);
317         borders->setRight(true);
318         // repaint the setborder widget
319         borders->update();
320         checkEnabled();
321 }
322
323
324 void GuiTabular::borderUnset_clicked()
325 {
326         borders->setTop(false);
327         borders->setBottom(false);
328         borders->setLeft(false);
329         borders->setRight(false);
330         // repaint the setborder widget
331         borders->update();
332         checkEnabled();
333 }
334
335
336 static void setParam(string & param_str, Tabular::Feature f, string const & arg = string())
337 {
338         param_str += ' ';
339         param_str += featureAsString(f) + ' ' + arg;
340 }
341
342
343 void GuiTabular::setHAlign(string & param_str) const
344 {
345         Tabular::Feature num = Tabular::ALIGN_LEFT;
346         Tabular::Feature multi_num = Tabular::M_ALIGN_LEFT;
347         string const align =
348                 fromqstr(hAlignCO->itemData(hAlignCO->currentIndex()).toString());
349         if (align == "left") {
350                 num = Tabular::ALIGN_LEFT;
351                 multi_num = Tabular::M_ALIGN_LEFT;
352         } else if (align == "center") {
353                 num = Tabular::ALIGN_CENTER;
354                 multi_num = Tabular::M_ALIGN_CENTER;
355         } else if (align == "right") {
356                 num = Tabular::ALIGN_RIGHT;
357                 multi_num = Tabular::M_ALIGN_RIGHT;
358         } else if (align == "justified") {
359                 num = Tabular::ALIGN_BLOCK;
360                 //multi_num: no equivalent
361         } else if (align == "decimal") {
362                 num = Tabular::ALIGN_DECIMAL;
363                 //multi_num: no equivalent
364         }
365
366         if (multicolumnCB->isChecked())
367                 setParam(param_str, multi_num);
368         else
369                 setParam(param_str, num);
370 }
371
372
373 void GuiTabular::setVAlign(string & param_str) const
374 {
375         int const align = vAlignCO->currentIndex();
376         enum VALIGN { TOP, MIDDLE, BOTTOM };
377         VALIGN v = TOP;
378
379         switch (align) {
380                 case 0: v = TOP; break;
381                 case 1: v = MIDDLE; break;
382                 case 2: v = BOTTOM; break;
383         }
384
385         Tabular::Feature num = Tabular::VALIGN_MIDDLE;
386         Tabular::Feature multi_num = Tabular::M_VALIGN_MIDDLE;
387
388         switch (v) {
389                 case TOP:
390                         num = Tabular::VALIGN_TOP;
391                         multi_num = Tabular::M_VALIGN_TOP;
392                         break;
393                 case MIDDLE:
394                         num = Tabular::VALIGN_MIDDLE;
395                         multi_num = Tabular::M_VALIGN_MIDDLE;
396                         break;
397                 case BOTTOM:
398                         num = Tabular::VALIGN_BOTTOM;
399                         multi_num = Tabular::M_VALIGN_BOTTOM;
400                         break;
401         }
402         if (multicolumnCB->isChecked() || multirowCB->isChecked())
403                 setParam(param_str, multi_num);
404         else
405                 setParam(param_str, num);
406 }
407
408
409 void GuiTabular::setTableAlignment(string & param_str) const
410 {
411         int const align = TableAlignCO->currentIndex();
412         switch (align) {
413                 case 0: setParam(param_str, Tabular::TABULAR_VALIGN_TOP);
414                         break;
415                 case 1: setParam(param_str, Tabular::TABULAR_VALIGN_MIDDLE);
416                         break;
417                 case 2: setParam(param_str, Tabular::TABULAR_VALIGN_BOTTOM);
418                         break;
419         }
420 }
421
422
423 docstring GuiTabular::dialogToParams() const
424 {
425         // FIXME: We should use Tabular directly.
426         string param_str = "tabular from-dialog";
427
428         // table width
429         string tabwidth = widgetsToLength(tabularWidthED, tabularWidthUnitLC);
430         if (tabwidth.empty())
431                 tabwidth = "0pt";
432         setParam(param_str, Tabular::SET_TABULAR_WIDTH, tabwidth);
433
434         // apply the fixed width values
435         // this must be done before applying the column alignment
436         // because its value influences the alignment of multirow cells
437         string width = widgetsToLength(columnWidthED, columnWidthUnitLC);
438         if (width.empty())
439                 width = "0pt";
440         if (multicolumnCB->isChecked())
441                 setParam(param_str, Tabular::SET_MPWIDTH, width);
442         else
443                 setParam(param_str, Tabular::SET_PWIDTH, width);
444
445         // apply the column alignment
446         // multirows inherit the alignment from the column; if a column width
447         // is set, multicolumns are always left-aligned so that in this case
448         // its alignment must not be applied (see bug #8084)
449         if (!(multirowCB->isChecked() && width != "0pt"))
450                 setHAlign(param_str);
451
452         // SET_DECIMAL_POINT must come after setHAlign() (ALIGN_DECIMAL)
453         string decimal_point = fromqstr(decimalPointED->text());
454         if (decimal_point.empty())
455                 decimal_point = lyxrc.default_decimal_point;
456         setParam(param_str, Tabular::SET_DECIMAL_POINT, decimal_point);
457
458         setVAlign(param_str);
459         setTableAlignment(param_str);
460         //
461         if (booktabsRB->isChecked())
462                 setParam(param_str, Tabular::SET_BOOKTABS);
463         else
464                 setParam(param_str, Tabular::UNSET_BOOKTABS);
465
466         //
467         switch (topspaceCO->currentIndex()) {
468                 case 0:
469                         setParam(param_str, Tabular::SET_TOP_SPACE, "none");
470                         break;
471                 case 1:
472                         setParam(param_str, Tabular::SET_TOP_SPACE, "default");
473                         break;
474                 case 2:
475                         if (!topspaceED->text().isEmpty())
476                                 setParam(param_str, Tabular::SET_TOP_SPACE,
477                                          widgetsToLength(topspaceED, topspaceUnitLC));
478                         break;
479         }
480
481         //
482         switch (bottomspaceCO->currentIndex()) {
483                 case 0:
484                         setParam(param_str, Tabular::SET_BOTTOM_SPACE, "none");
485                         break;
486                 case 1:
487                         setParam(param_str, Tabular::SET_BOTTOM_SPACE, "default");
488                         break;
489                 case 2:
490                         if (!bottomspaceED->text().isEmpty())
491                                 setParam(param_str, Tabular::SET_BOTTOM_SPACE,
492                                         widgetsToLength(bottomspaceED,
493                                                         bottomspaceUnitLC));
494                         break;
495         }
496
497         //
498         switch (interlinespaceCO->currentIndex()) {
499                 case 0:
500                         setParam(param_str, Tabular::SET_INTERLINE_SPACE, "none");
501                         break;
502                 case 1:
503                         setParam(param_str, Tabular::SET_INTERLINE_SPACE, "default");
504                         break;
505                 case 2:
506                         if (!interlinespaceED->text().isEmpty())
507                                 setParam(param_str, Tabular::SET_INTERLINE_SPACE,
508                                         widgetsToLength(interlinespaceED,
509                                                         interlinespaceUnitLC));
510                         break;
511         }
512
513         //
514         if (borders->getTop() && borders->getBottom() && borders->getLeft()
515                 && borders->getRight())
516                 setParam(param_str, Tabular::SET_ALL_LINES);
517         else if (!borders->getTop() && !borders->getBottom() && !borders->getLeft()
518                 && !borders->getRight())
519                 setParam(param_str, Tabular::UNSET_ALL_LINES);
520         else {
521                 setParam(param_str, Tabular::SET_LINE_LEFT,
522                          borders->getLeft() ? "true" : "false");
523                 setParam(param_str, Tabular::SET_LINE_RIGHT,
524                          borders->getRight() ? "true" : "false");
525                 setParam(param_str, Tabular::SET_LINE_TOP,
526                          borders->getTop() ? "true" : "false");
527                 setParam(param_str, Tabular::SET_LINE_BOTTOM,
528                          borders->getBottom() ? "true" : "false");
529         }
530
531         // apply the special alignment
532         string special = fromqstr(specialAlignmentED->text());
533         if (special.empty())
534                 special = "none";
535         if (multicolumnCB->isChecked())
536                 setParam(param_str, Tabular::SET_SPECIAL_MULTICOLUMN, special);
537         else
538                 setParam(param_str, Tabular::SET_SPECIAL_COLUMN, special);
539
540         //
541         if (multicolumnCB->isChecked())
542                 setParam(param_str, Tabular::SET_MULTICOLUMN);
543         else
544                 setParam(param_str, Tabular::UNSET_MULTICOLUMN);
545
546         // apply the multirow offset
547         string mroffset = widgetsToLength(multirowOffsetED, multirowOffsetUnitLC);
548         if (mroffset.empty())
549                 mroffset = "0pt";
550         if (multirowCB->isChecked())
551                 setParam(param_str, Tabular::SET_MROFFSET, mroffset);
552         //
553         if (multirowCB->isChecked())
554                 setParam(param_str, Tabular::SET_MULTIROW);
555         else
556                 setParam(param_str, Tabular::UNSET_MULTIROW);
557         //
558         if (rotateTabularCB->isChecked())
559                 setParam(param_str, Tabular::SET_ROTATE_TABULAR);
560         else
561                 setParam(param_str, Tabular::UNSET_ROTATE_TABULAR);
562         //
563         if (rotateCellCB->isChecked())
564                 setParam(param_str, Tabular::SET_ROTATE_CELL);
565         else
566                 setParam(param_str, Tabular::UNSET_ROTATE_CELL);
567         //
568         if (longTabularCB->isChecked())
569                 setParam(param_str, Tabular::SET_LONGTABULAR);
570         else
571                 setParam(param_str, Tabular::UNSET_LONGTABULAR);
572         //
573         if (newpageCB->isChecked())
574                 setParam(param_str, Tabular::SET_LTNEWPAGE);
575         //
576         if (captionStatusCB->isChecked())
577                 setParam(param_str, Tabular::SET_LTCAPTION);
578         else
579                 setParam(param_str, Tabular::UNSET_LTCAPTION);
580         //
581         if (headerStatusCB->isChecked())
582                 setParam(param_str, Tabular::SET_LTHEAD, "none");
583         else
584                 setParam(param_str, Tabular::UNSET_LTHEAD, "none");
585         //
586         if (headerBorderAboveCB->isChecked())
587                 setParam(param_str, Tabular::SET_LTHEAD, "dl_above");
588         else
589                 setParam(param_str, Tabular::UNSET_LTHEAD, "dl_above");
590         //
591         if (headerBorderBelowCB->isChecked())
592                 setParam(param_str, Tabular::SET_LTHEAD, "dl_below");
593         else
594                 setParam(param_str, Tabular::UNSET_LTHEAD, "dl_below");
595         if (firstheaderBorderAboveCB->isChecked())
596                 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "dl_above");
597         else
598                 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "dl_above");
599         if (firstheaderBorderBelowCB->isChecked())
600                 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "dl_below");
601         else
602                 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "dl_below");
603         if (firstheaderStatusCB->isChecked())
604                 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "none");
605         else
606                 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "none");
607         if (firstheaderNoContentsCB->isChecked())
608                 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "empty");
609         else
610                 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "empty");
611         if (footerStatusCB->isChecked())
612                 setParam(param_str, Tabular::SET_LTFOOT, "none");
613         else
614                 setParam(param_str, Tabular::UNSET_LTFOOT, "none");
615         if (footerBorderAboveCB->isChecked())
616                 setParam(param_str, Tabular::SET_LTFOOT, "dl_above");
617         else
618                 setParam(param_str, Tabular::UNSET_LTFOOT, "dl_above");
619         if (footerBorderBelowCB->isChecked())
620                 setParam(param_str, Tabular::SET_LTFOOT, "dl_below");
621         else
622                 setParam(param_str, Tabular::UNSET_LTFOOT, "dl_below");
623         if (lastfooterStatusCB->isChecked())
624                 setParam(param_str, Tabular::SET_LTLASTFOOT, "none");
625         else
626                 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "none");
627         if (lastfooterBorderAboveCB->isChecked())
628                 setParam(param_str, Tabular::SET_LTLASTFOOT, "dl_above");
629         else
630                 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "dl_above");
631         if (lastfooterBorderBelowCB->isChecked())
632                 setParam(param_str, Tabular::SET_LTLASTFOOT, "dl_below");
633         else
634                 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "dl_below");
635         if (lastfooterNoContentsCB->isChecked())
636                 setParam(param_str, Tabular::SET_LTLASTFOOT, "empty");
637         else
638                 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "empty");
639
640         if (leftRB->isChecked())
641                 setParam(param_str, Tabular::LONGTABULAR_ALIGN_LEFT);
642         else if (centerRB->isChecked())
643                 setParam(param_str, Tabular::LONGTABULAR_ALIGN_CENTER);
644         else if (rightRB->isChecked())
645                 setParam(param_str, Tabular::LONGTABULAR_ALIGN_RIGHT);
646
647         return from_utf8(param_str);
648 }
649
650
651 static Length getColumnPWidth(Tabular const & t, size_t cell)
652 {
653         return t.column_info[t.cellColumn(cell)].p_width;
654 }
655
656
657 static Length getMColumnPWidth(Tabular const & t, size_t cell)
658 {
659         if (t.isMultiColumn(cell) || t.isMultiRow(cell))
660                 return t.cellInfo(cell).p_width;
661         return Length();
662 }
663
664
665 static Length getMROffset(Tabular const & t, size_t cell)
666 {
667         if (t.isMultiRow(cell))
668                 return t.cellInfo(cell).mroffset;
669         return Length();
670 }
671
672
673 static docstring getAlignSpecial(Tabular const & t, size_t cell, int what)
674 {
675         if (what == Tabular::SET_SPECIAL_MULTICOLUMN)
676                 return t.cellInfo(cell).align_special;
677         return t.column_info[t.cellColumn(cell)].align_special;
678 }
679
680
681 void GuiTabular::paramsToDialog(Inset const * inset)
682 {
683         InsetTabular const * itab = static_cast<InsetTabular const *>(inset);
684         // Copy Tabular of current inset.
685         Tabular const & tabular = itab->tabular;
686
687         BufferView const * bv = guiApp->currentView()->currentBufferView();
688         size_t const cell = bv->cursor().idx();
689
690         Tabular::row_type const row = tabular.cellRow(cell);
691         Tabular::col_type const col = tabular.cellColumn(cell);
692
693         tabularRowED->setText(QString::number(row + 1));
694         tabularColumnED->setText(QString::number(col + 1));
695
696         bool const multicol = tabular.isMultiColumn(cell);
697         multicolumnCB->setChecked(multicol);
698
699         bool const multirow = tabular.isMultiRow(cell);
700         multirowCB->setChecked(multirow);
701
702         rotateCellCB->setChecked(tabular.getRotateCell(cell));
703         rotateTabularCB->setChecked(tabular.rotate);
704
705         longTabularCB->setChecked(tabular.is_long_tabular);
706
707         borders->setTop(tabular.topLine(cell));
708         borders->setBottom(tabular.bottomLine(cell));
709         borders->setLeft(tabular.leftLine(cell));
710         borders->setRight(tabular.rightLine(cell));
711         // repaint the setborder widget
712         borders->update();
713
714         Length::UNIT const default_unit = Length::defaultUnit();
715
716         ///////////////////////////////////
717         // Set width and alignment
718
719         Length const tabwidth = tabular.tabularWidth();
720         if (tabwidth.zero())
721                 tabularWidthED->clear();
722         else
723                 lengthToWidgets(tabularWidthED, tabularWidthUnitLC,
724                         tabwidth.asString(), default_unit);
725
726         Length pwidth;
727         docstring special;
728         if (multicol) {
729                 special = getAlignSpecial(tabular, cell,
730                         Tabular::SET_SPECIAL_MULTICOLUMN);
731                 pwidth = getMColumnPWidth(tabular, cell);
732         } else {
733                 special = getAlignSpecial(tabular, cell,
734                         Tabular::SET_SPECIAL_COLUMN);
735                 pwidth = getColumnPWidth(tabular, cell);
736         }
737         string colwidth;
738         if (pwidth.zero())
739                 columnWidthED->clear();
740         else {
741                 colwidth = pwidth.asString();
742                 lengthToWidgets(columnWidthED, columnWidthUnitLC,
743                         colwidth, default_unit);
744         }
745         Length mroffset;
746         if (multirow)
747                 mroffset = getMROffset(tabular, cell);
748         string offset;
749         if (mroffset.zero())
750                 multirowOffsetED->clear();
751         else {
752                 offset = mroffset.asString();
753                 lengthToWidgets(multirowOffsetED, multirowOffsetUnitLC,
754                         offset, default_unit);
755         }
756         specialAlignmentED->setText(toqstr(special));
757         ///////////////////////////////////
758
759
760         borderDefaultRB->setChecked(!tabular.use_booktabs);
761         booktabsRB->setChecked(tabular.use_booktabs);
762
763         if (tabular.row_info[row].top_space.empty()
764             && !tabular.row_info[row].top_space_default) {
765                 topspaceCO->setCurrentIndex(0);
766         } else if (tabular.row_info[row].top_space_default) {
767                 topspaceCO->setCurrentIndex(1);
768         } else {
769                 topspaceCO->setCurrentIndex(2);
770                 lengthToWidgets(topspaceED,
771                                 topspaceUnitLC,
772                                 tabular.row_info[row].top_space.asString(),
773                                 default_unit);
774         }
775
776         if (tabular.row_info[row].bottom_space.empty()
777             && !tabular.row_info[row].bottom_space_default) {
778                 bottomspaceCO->setCurrentIndex(0);
779         } else if (tabular.row_info[row].bottom_space_default) {
780                 bottomspaceCO->setCurrentIndex(1);
781         } else {
782                 bottomspaceCO->setCurrentIndex(2);
783                 lengthToWidgets(bottomspaceED,
784                                 bottomspaceUnitLC,
785                                 tabular.row_info[row].bottom_space.asString(),
786                                 default_unit);
787         }
788
789         if (tabular.row_info[row].interline_space.empty()
790             && !tabular.row_info[row].interline_space_default) {
791                 interlinespaceCO->setCurrentIndex(0);
792         } else if (tabular.row_info[row].interline_space_default) {
793                 interlinespaceCO->setCurrentIndex(1);
794         } else {
795                 interlinespaceCO->setCurrentIndex(2);
796                 lengthToWidgets(interlinespaceED,
797                                 interlinespaceUnitLC,
798                                 tabular.row_info[row].interline_space.asString(),
799                                 default_unit);
800         }
801
802         hAlignCO->clear();
803         hAlignCO->addItem(qt_("Left"), toqstr("left"));
804         hAlignCO->addItem(qt_("Center"), toqstr("center"));
805         hAlignCO->addItem(qt_("Right"), toqstr("right"));
806         if (!multicol && !pwidth.zero())
807                 hAlignCO->addItem(qt_("Justified"), toqstr("justified"));
808         if (!multicol)
809                 hAlignCO->addItem(qt_("At Decimal Separator"), toqstr("decimal"));
810
811         string align;
812         switch (tabular.getAlignment(cell)) {
813                 case LYX_ALIGN_LEFT:
814                         align = "left";
815                         break;
816                 case LYX_ALIGN_CENTER:
817                         align = "center";
818                         break;
819                 case LYX_ALIGN_RIGHT:
820                         align = "right";
821                         break;
822                 case LYX_ALIGN_BLOCK:
823                 {
824                         if (!multicol && !pwidth.zero())
825                                 align = "justified";
826                         break;
827                 }
828                 case LYX_ALIGN_DECIMAL:
829                 {
830                         if (!multicol)
831                                 align = "decimal";
832                         break;
833                 }
834                 default:
835                         // we should never end up here
836                         break;
837         }
838         hAlignCO->setCurrentIndex(hAlignCO->findData(toqstr(align)));
839
840         //
841         QString decimal_point = toqstr(tabular.column_info[col].decimal_point);
842         if (decimal_point.isEmpty())
843                 decimal_point = toqstr(from_utf8(lyxrc.default_decimal_point));
844         decimalPointED->setText(decimal_point);
845
846         int valign = 0;
847         switch (tabular.getVAlignment(cell)) {
848         case Tabular::LYX_VALIGN_TOP:
849                 valign = 0;
850                 break;
851         case Tabular::LYX_VALIGN_MIDDLE:
852                 valign = 1;
853                 break;
854         case Tabular::LYX_VALIGN_BOTTOM:
855                 valign = 2;
856                 break;
857         default:
858                 valign = 0;
859                 break;
860         }
861         if (pwidth.zero())
862                 valign = 0;
863         vAlignCO->setCurrentIndex(valign);
864
865         int tableValign = 1;
866         switch (tabular.tabular_valignment) {
867         case Tabular::LYX_VALIGN_TOP:
868                 tableValign = 0;
869                 break;
870         case Tabular::LYX_VALIGN_MIDDLE:
871                 tableValign = 1;
872                 break;
873         case Tabular::LYX_VALIGN_BOTTOM:
874                 tableValign = 2;
875                 break;
876         default:
877                 tableValign = 0;
878                 break;
879         }
880         TableAlignCO->setCurrentIndex(tableValign);
881
882         if (!tabular.is_long_tabular) {
883                 headerStatusCB->setChecked(false);
884                 headerBorderAboveCB->setChecked(false);
885                 headerBorderBelowCB->setChecked(false);
886                 firstheaderStatusCB->setChecked(false);
887                 firstheaderBorderAboveCB->setChecked(false);
888                 firstheaderBorderBelowCB->setChecked(false);
889                 firstheaderNoContentsCB->setChecked(false);
890                 footerStatusCB->setChecked(false);
891                 footerBorderAboveCB->setChecked(false);
892                 footerBorderBelowCB->setChecked(false);
893                 lastfooterStatusCB->setChecked(false);
894                 lastfooterBorderAboveCB->setChecked(false);
895                 lastfooterBorderBelowCB->setChecked(false);
896                 lastfooterNoContentsCB->setChecked(false);
897                 newpageCB->setChecked(false);
898                 captionStatusCB->blockSignals(true);
899                 captionStatusCB->setChecked(false);
900                 captionStatusCB->blockSignals(false);
901                 checkEnabled();
902                 return;
903         } else {
904                 // longtables cannot have a vertical alignment
905                 TableAlignCO->setCurrentIndex(Tabular::LYX_VALIGN_MIDDLE);
906         }
907         switch (tabular.longtabular_alignment) {
908         case Tabular::LYX_LONGTABULAR_ALIGN_LEFT:
909                 leftRB->setChecked(true);
910                 break;
911         case Tabular::LYX_LONGTABULAR_ALIGN_CENTER:
912                 centerRB->setChecked(true);
913                 break;
914         case Tabular::LYX_LONGTABULAR_ALIGN_RIGHT:
915                 rightRB->setChecked(true);
916                 break;
917         default:
918                 centerRB->setChecked(true);
919                 break;
920         }
921         captionStatusCB->blockSignals(true);
922         captionStatusCB->setChecked(tabular.ltCaption(row));
923         captionStatusCB->blockSignals(false);
924
925         Tabular::ltType ltt;
926         bool use_empty;
927         bool row_set = tabular.getRowOfLTHead(row, ltt);
928         headerStatusCB->setChecked(row_set);
929         if (ltt.set) {
930                 headerBorderAboveCB->setChecked(ltt.topDL);
931                 headerBorderBelowCB->setChecked(ltt.bottomDL);
932                 use_empty = true;
933         } else {
934                 headerBorderAboveCB->setChecked(false);
935                 headerBorderBelowCB->setChecked(false);
936                 firstheaderNoContentsCB->setChecked(false);
937                 use_empty = false;
938         }
939
940         row_set = tabular.getRowOfLTFirstHead(row, ltt);
941         firstheaderStatusCB->setChecked(row_set);
942         if (ltt.set && (!ltt.empty || !use_empty)) {
943                 firstheaderBorderAboveCB->setChecked(ltt.topDL);
944                 firstheaderBorderBelowCB->setChecked(ltt.bottomDL);
945         } else {
946                 firstheaderBorderAboveCB->setChecked(false);
947                 firstheaderBorderBelowCB->setChecked(false);
948         }
949
950         row_set = tabular.getRowOfLTFoot(row, ltt);
951         footerStatusCB->setChecked(row_set);
952         if (ltt.set) {
953                 footerBorderAboveCB->setChecked(ltt.topDL);
954                 footerBorderBelowCB->setChecked(ltt.bottomDL);
955                 use_empty = true;
956         } else {
957                 footerBorderAboveCB->setChecked(false);
958                 footerBorderBelowCB->setChecked(false);
959                 lastfooterNoContentsCB->setChecked(false);
960                 use_empty = false;
961         }
962
963         row_set = tabular.getRowOfLTLastFoot(row, ltt);
964         lastfooterStatusCB->setChecked(row_set);
965         if (ltt.set && (!ltt.empty || !use_empty)) {
966                 lastfooterBorderAboveCB->setChecked(ltt.topDL);
967                 lastfooterBorderBelowCB->setChecked(ltt.bottomDL);
968         } else {
969                 lastfooterBorderAboveCB->setChecked(false);
970                 lastfooterBorderBelowCB->setChecked(false);
971         }
972         newpageCB->setChecked(tabular.getLTNewPage(row));
973
974         // first header can only be suppressed when there is a header
975         firstheader_suppressable_ = tabular.haveLTHead()
976                         && !tabular.haveLTFirstHead();
977         // last footer can only be suppressed when there is a footer
978         lastfooter_suppressable_ = tabular.haveLTFoot()
979                         && !tabular.haveLTLastFoot();
980
981         // after setting the features, check if they are enabled
982         checkEnabled();
983 }
984
985
986 bool GuiTabular::funcEnabled(Tabular::Feature f) const
987 {
988         string cmd = "tabular " + featureAsString(f);
989         return getStatus(FuncRequest(LFUN_INSET_MODIFY, cmd)).enabled();
990 }
991
992
993 } // namespace frontend
994 } // namespace lyx
995
996 #include "moc_GuiTabular.cpp"