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