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