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