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