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