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