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