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