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