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