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