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