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