]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiTabular.cpp
do what the FIXME suggested
[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  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 #include <config.h>
14
15 #include "GuiTabular.h"
16
17 #include "BufferView.h"
18 #include "Cursor.h"
19 #include "FuncRequest.h"
20 #include "GuiSetBorder.h"
21 #include "LengthCombo.h"
22 #include "LyXRC.h"
23 #include "qt_helpers.h"
24 #include "Validator.h"
25
26 #include "insets/InsetTabular.h"
27
28 #include <QCheckBox>
29 #include <QPushButton>
30 #include <QRadioButton>
31 #include <QLineEdit>
32
33 using namespace std;
34
35 namespace lyx {
36 namespace frontend {
37
38 GuiTabular::GuiTabular(GuiView & lv)
39         : GuiDialog(lv, "tabular", qt_("Table Settings"))
40 {
41         active_cell_ = Tabular::npos;
42
43         setupUi(this);
44
45         widthED->setValidator(unsignedLengthValidator(widthED));
46         topspaceED->setValidator(new LengthValidator(topspaceED));
47         bottomspaceED->setValidator(new LengthValidator(bottomspaceED));
48         interlinespaceED->setValidator(new LengthValidator(interlinespaceED));
49
50         connect(topspaceED, SIGNAL(returnPressed()),
51                 this, SLOT(topspace_changed()));
52         connect(topspaceUnit, SIGNAL(selectionChanged(lyx::Length::UNIT)),
53                 this, SLOT(topspace_changed()));
54         connect(topspaceCO, SIGNAL(activated(int)), this, SLOT(topspace_changed()));
55         connect(bottomspaceED, SIGNAL(returnPressed()),
56                 this, SLOT(bottomspace_changed()));
57         connect(bottomspaceUnit, SIGNAL(selectionChanged(lyx::Length::UNIT)),
58                 this, SLOT(bottomspace_changed()));
59         connect(bottomspaceCO, SIGNAL(activated(int)), this, SLOT(bottomspace_changed()));
60         connect(interlinespaceED, SIGNAL(returnPressed()),
61                 this, SLOT(interlinespace_changed()));
62         connect(interlinespaceUnit, SIGNAL(selectionChanged(lyx::Length::UNIT)),
63                 this, SLOT(interlinespace_changed()));
64         connect(interlinespaceCO, SIGNAL(activated(int)), this, SLOT(interlinespace_changed()));
65         connect(booktabsRB, SIGNAL(clicked(bool)), this, SLOT(booktabsChanged(bool)));
66         connect(borderDefaultRB, SIGNAL(clicked(bool)), this, SLOT(booktabsChanged(bool)));
67         connect(borderSetPB, SIGNAL(clicked()), this, SLOT(borderSet_clicked()));
68         connect(borderUnsetPB, SIGNAL(clicked()), this, SLOT(borderUnset_clicked()));
69         connect(longTabularCB, SIGNAL(toggled(bool)), longtableGB, SLOT(setEnabled(bool)));
70         connect(longTabularCB, SIGNAL(toggled(bool)), newpageCB, SLOT(setEnabled(bool)));
71         connect(hAlignCB, SIGNAL(activated(int)), this, SLOT(hAlign_changed(int)));
72         connect(vAlignCB, SIGNAL(activated(int)), this, SLOT(vAlign_changed(int)));
73         connect(multicolumnCB, SIGNAL(clicked()), this, SLOT(multicolumn_clicked()));
74         connect(newpageCB, SIGNAL(clicked()), this, SLOT(ltNewpage_clicked()));
75         connect(headerStatusCB, SIGNAL(clicked()), this, SLOT(ltHeaderStatus_clicked()));
76         connect(headerBorderAboveCB, SIGNAL(clicked()), this, SLOT(ltHeaderBorderAbove_clicked()));
77         connect(headerBorderBelowCB, SIGNAL(clicked()), this, SLOT(ltHeaderBorderBelow_clicked()));
78         connect(firstheaderStatusCB, SIGNAL(clicked()), this, SLOT(ltFirstHeaderStatus_clicked()));
79         connect(firstheaderBorderAboveCB, SIGNAL(clicked()), this, SLOT(ltFirstHeaderBorderAbove_clicked()));
80         connect(firstheaderBorderBelowCB, SIGNAL(clicked()), this, SLOT(ltFirstHeaderBorderBelow_clicked()));
81         connect(firstheaderNoContentsCB, SIGNAL(clicked()), this, SLOT(ltFirstHeaderEmpty_clicked()));
82         connect(footerStatusCB, SIGNAL(clicked()), this, SLOT(ltFooterStatus_clicked()));
83         connect(footerBorderAboveCB, SIGNAL(clicked()), this, SLOT(ltFooterBorderAbove_clicked()));
84         connect(footerBorderBelowCB, SIGNAL(clicked()), this, SLOT(ltFooterBorderBelow_clicked()));
85         connect(lastfooterStatusCB, SIGNAL(clicked()), this, SLOT(ltLastFooterStatus_clicked()));
86         connect(lastfooterBorderAboveCB, SIGNAL(clicked()), this, SLOT(ltLastFooterBorderAbove_clicked()));
87         connect(lastfooterBorderBelowCB, SIGNAL(clicked()), this, SLOT(ltLastFooterBorderBelow_clicked()));
88         connect(lastfooterNoContentsCB, SIGNAL(clicked()), this, SLOT(ltLastFooterEmpty_clicked()));
89         connect(specialAlignmentED, SIGNAL(returnPressed()), this, SLOT(specialAlignment_changed()));
90         connect(widthED, SIGNAL(returnPressed()), this, SLOT(width_changed()));
91         connect(widthUnit, SIGNAL(selectionChanged(lyx::Length::UNIT)), this, SLOT(width_changed()));
92         connect(closePB, SIGNAL(clicked()), this, SLOT(close_clicked()));
93         connect(borders, SIGNAL(topSet(bool)), this, SLOT(topBorder_changed()));
94         connect(borders, SIGNAL(bottomSet(bool)), this, SLOT(bottomBorder_changed()));
95         connect(borders, SIGNAL(rightSet(bool)), this, SLOT(rightBorder_changed()));
96         connect(borders, SIGNAL(leftSet(bool)), this, SLOT(leftBorder_changed()));
97         connect(rotateTabularCB, SIGNAL(clicked()), this, SLOT(rotateTabular()));
98         connect(rotateCellCB, SIGNAL(clicked()), this, SLOT(rotateCell()));
99         connect(longTabularCB, SIGNAL(clicked()), this, SLOT(longTabular()));
100
101         bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
102         bc().setCancel(closePB);
103
104         bc().addReadOnly(topspaceED);
105         bc().addReadOnly(topspaceUnit);
106         bc().addReadOnly(topspaceCO);
107         bc().addReadOnly(bottomspaceED);
108         bc().addReadOnly(bottomspaceUnit);
109         bc().addReadOnly(bottomspaceCO);
110         bc().addReadOnly(interlinespaceED);
111         bc().addReadOnly(interlinespaceUnit);
112         bc().addReadOnly(interlinespaceCO);
113         bc().addReadOnly(borderDefaultRB);
114         bc().addReadOnly(booktabsRB);
115
116         bc().addReadOnly(multicolumnCB);
117         bc().addReadOnly(rotateCellCB);
118         bc().addReadOnly(rotateTabularCB);
119         bc().addReadOnly(specialAlignmentED);
120         bc().addReadOnly(widthED);
121         bc().addReadOnly(widthUnit);
122         bc().addReadOnly(hAlignCB);
123         bc().addReadOnly(vAlignCB);
124         bc().addReadOnly(borderSetPB);
125         bc().addReadOnly(borderUnsetPB);
126         bc().addReadOnly(borders);
127         bc().addReadOnly(longTabularCB);
128         bc().addReadOnly(headerStatusCB);
129         bc().addReadOnly(headerBorderAboveCB);
130         bc().addReadOnly(headerBorderBelowCB);
131         bc().addReadOnly(firstheaderStatusCB);
132         bc().addReadOnly(firstheaderBorderAboveCB);
133         bc().addReadOnly(firstheaderBorderBelowCB);
134         bc().addReadOnly(firstheaderNoContentsCB);
135         bc().addReadOnly(footerStatusCB);
136         bc().addReadOnly(footerBorderAboveCB);
137         bc().addReadOnly(footerBorderBelowCB);
138         bc().addReadOnly(lastfooterStatusCB);
139         bc().addReadOnly(lastfooterBorderAboveCB);
140         bc().addReadOnly(lastfooterBorderBelowCB);
141         bc().addReadOnly(lastfooterNoContentsCB);
142         bc().addReadOnly(newpageCB);
143
144         // initialize the length validator
145         bc().addCheckedLineEdit(widthED, fixedWidthColLA);
146         bc().addCheckedLineEdit(topspaceED, topspaceLA);
147         bc().addCheckedLineEdit(bottomspaceED, bottomspaceLA);
148         bc().addCheckedLineEdit(interlinespaceED, interlinespaceLA);
149 }
150
151
152 GuiTabular::~GuiTabular()
153 {
154 }
155
156
157 void GuiTabular::change_adaptor()
158 {
159         changed();
160 }
161
162
163 void GuiTabular::booktabsChanged(bool)
164 {
165         changed();
166         booktabs(booktabsRB->isChecked());
167         update_borders();
168 }
169
170
171 void GuiTabular::topspace_changed()
172 {
173         switch (topspaceCO->currentIndex()) {
174                 case 0: {
175                         set(Tabular::SET_TOP_SPACE, "");
176                         topspaceED->setEnabled(false);
177                         topspaceUnit->setEnabled(false);
178                         break;
179                 }
180                 case 1: {
181                         set(Tabular::SET_TOP_SPACE, "default");
182                         topspaceED->setEnabled(false);
183                         topspaceUnit->setEnabled(false);
184                         break;
185                 }
186                 case 2: {
187                         if (!topspaceED->text().isEmpty())
188                                 set(Tabular::SET_TOP_SPACE,
189                                         widgetsToLength(topspaceED, topspaceUnit));
190                         if (!bc().policy().isReadOnly()) {
191                                 topspaceED->setEnabled(true);
192                                 topspaceUnit->setEnabled(true);
193                         }
194                         break;
195                 }
196         }
197         changed();
198 }
199
200
201 void GuiTabular::bottomspace_changed()
202 {
203         switch (bottomspaceCO->currentIndex()) {
204                 case 0: {
205                         set(Tabular::SET_BOTTOM_SPACE, "");
206                                 bottomspaceED->setEnabled(false);
207                                 bottomspaceUnit->setEnabled(false);
208                         break;
209                 }
210                 case 1: {
211                         set(Tabular::SET_BOTTOM_SPACE, "default");
212                         bottomspaceED->setEnabled(false);
213                         bottomspaceUnit->setEnabled(false);
214                         break;
215                 }
216                 case 2: {
217                         if (!bottomspaceED->text().isEmpty())
218                                 set(Tabular::SET_BOTTOM_SPACE,
219                                         widgetsToLength(bottomspaceED, bottomspaceUnit));
220                         if (!bc().policy().isReadOnly()) {
221                                 bottomspaceED->setEnabled(true);
222                                 bottomspaceUnit->setEnabled(true);
223                         }
224                         break;
225                 }
226         }
227         changed();
228 }
229
230
231 void GuiTabular::interlinespace_changed()
232 {
233         switch (interlinespaceCO->currentIndex()) {
234                 case 0: {
235                         set(Tabular::SET_INTERLINE_SPACE, "");
236                                 interlinespaceED->setEnabled(false);
237                                 interlinespaceUnit->setEnabled(false);
238                         break;
239                 }
240                 case 1: {
241                         set(Tabular::SET_INTERLINE_SPACE, "default");
242                         interlinespaceED->setEnabled(false);
243                         interlinespaceUnit->setEnabled(false);
244                         break;
245                 }
246                 case 2: {
247                         if (!interlinespaceED->text().isEmpty())
248                                 set(Tabular::SET_INTERLINE_SPACE,
249                                         widgetsToLength(interlinespaceED, interlinespaceUnit));
250                         if (!bc().policy().isReadOnly()) {
251                                 interlinespaceED->setEnabled(true);
252                                 interlinespaceUnit->setEnabled(true);
253                         }
254                         break;
255                 }
256         }
257         changed();
258 }
259
260
261 void GuiTabular::close_clicked()
262 {
263         closeGUI();
264         slotClose();
265 }
266
267
268 void GuiTabular::borderSet_clicked()
269 {
270         set(Tabular::SET_ALL_LINES);
271         update_borders();
272         changed();
273 }
274
275
276 void GuiTabular::borderUnset_clicked()
277 {
278         set(Tabular::UNSET_ALL_LINES);
279         update_borders();
280         changed();
281 }
282
283
284 void GuiTabular::leftBorder_changed()
285 {
286         toggleLeftLine();
287         changed();
288 }
289
290
291 void GuiTabular::rightBorder_changed()
292 {
293         toggleRightLine();
294         changed();
295 }
296
297
298 void GuiTabular::topBorder_changed()
299 {
300         toggleTopLine();
301         changed();
302 }
303
304
305 void GuiTabular::bottomBorder_changed()
306 {
307         toggleBottomLine();
308         changed();
309 }
310
311
312 void GuiTabular::specialAlignment_changed()
313 {
314         string special = fromqstr(specialAlignmentED->text());
315         setSpecial(special);
316         changed();
317 }
318
319
320 void GuiTabular::width_changed()
321 {
322         changed();
323         string const width = widgetsToLength(widthED, widthUnit);
324         setWidth(width);
325 }
326
327
328 void GuiTabular::multicolumn_clicked()
329 {
330         toggleMultiColumn();
331         changed();
332 }
333
334
335 void GuiTabular::rotateTabular()
336 {
337         rotateTabular(rotateTabularCB->isChecked());
338         changed();
339 }
340
341
342 void GuiTabular::rotateCell()
343 {
344         rotateCell(rotateCellCB->isChecked());
345         changed();
346 }
347
348
349 void GuiTabular::hAlign_changed(int align)
350 {
351         GuiTabular::HALIGN h = GuiTabular::LEFT;
352
353         switch (align) {
354                 case 0: h = GuiTabular::LEFT; break;
355                 case 1: h = GuiTabular::CENTER; break;
356                 case 2: h = GuiTabular::RIGHT; break;
357                 case 3: h = GuiTabular::BLOCK; break;
358         }
359
360         halign(h);
361 }
362
363
364 void GuiTabular::vAlign_changed(int align)
365 {
366         GuiTabular::VALIGN v = GuiTabular::TOP;
367
368         switch (align) {
369                 case 0: v = GuiTabular::TOP; break;
370                 case 1: v = GuiTabular::MIDDLE; break;
371                 case 2: v = GuiTabular::BOTTOM; break;
372         }
373
374         valign(v);
375 }
376
377
378 void GuiTabular::longTabular()
379 {
380         longTabular(longTabularCB->isChecked());
381         changed();
382 }
383
384
385 void GuiTabular::ltNewpage_clicked()
386 {
387         set(Tabular::SET_LTNEWPAGE);
388         changed();
389 }
390
391
392 void GuiTabular::ltHeaderStatus_clicked()
393 {
394         bool enable = headerStatusCB->isChecked();
395         if (enable)
396                 set(Tabular::SET_LTHEAD, "");
397         else
398                 set(Tabular::UNSET_LTHEAD, "");
399         headerBorderAboveCB->setEnabled(enable);
400         headerBorderBelowCB->setEnabled(enable);
401         firstheaderNoContentsCB->setEnabled(enable);
402         changed();
403 }
404
405
406 void GuiTabular::ltHeaderBorderAbove_clicked()
407 {
408         if (headerBorderAboveCB->isChecked())
409                 set(Tabular::SET_LTHEAD, "dl_above");
410         else
411                 set(Tabular::UNSET_LTHEAD, "dl_above");
412         changed();
413 }
414
415
416 void GuiTabular::ltHeaderBorderBelow_clicked()
417 {
418         if (headerBorderBelowCB->isChecked())
419                 set(Tabular::SET_LTHEAD, "dl_below");
420         else
421                 set(Tabular::UNSET_LTHEAD, "dl_below");
422         changed();
423 }
424
425
426 void GuiTabular::ltFirstHeaderBorderAbove_clicked()
427 {
428         if (firstheaderBorderAboveCB->isChecked())
429                 set(Tabular::SET_LTFIRSTHEAD, "dl_above");
430         else
431                 set(Tabular::UNSET_LTFIRSTHEAD, "dl_above");
432         changed();
433 }
434
435
436 void GuiTabular::ltFirstHeaderBorderBelow_clicked()
437 {
438         if (firstheaderBorderBelowCB->isChecked())
439                 set(Tabular::SET_LTFIRSTHEAD, "dl_below");
440         else
441                 set(Tabular::UNSET_LTFIRSTHEAD, "dl_below");
442         changed();
443 }
444
445
446 void GuiTabular::ltFirstHeaderStatus_clicked()
447 {
448         bool enable = firstheaderStatusCB->isChecked();
449         if (enable)
450                 set(Tabular::SET_LTFIRSTHEAD, "");
451         else
452                 set(Tabular::UNSET_LTFIRSTHEAD, "");
453         firstheaderBorderAboveCB->setEnabled(enable);
454         firstheaderBorderBelowCB->setEnabled(enable);
455         changed();
456 }
457
458
459 void GuiTabular::ltFirstHeaderEmpty_clicked()
460 {
461         bool enable = firstheaderNoContentsCB->isChecked();
462         if (enable)
463                 set(Tabular::SET_LTFIRSTHEAD, "empty");
464         else
465                 set(Tabular::UNSET_LTFIRSTHEAD, "empty");
466         firstheaderStatusCB->setEnabled(!enable);
467         firstheaderBorderAboveCB->setEnabled(!enable);
468         firstheaderBorderBelowCB->setEnabled(!enable);
469         changed();
470 }
471
472
473 void GuiTabular::ltFooterStatus_clicked()
474 {
475         bool enable = footerStatusCB->isChecked();
476         if (enable)
477                 set(Tabular::SET_LTFOOT, "");
478         else
479                 set(Tabular::UNSET_LTFOOT, "");
480         footerBorderAboveCB->setEnabled(enable);
481         footerBorderBelowCB->setEnabled(enable);
482         lastfooterNoContentsCB->setEnabled(enable);
483         changed();
484 }
485
486
487 void GuiTabular::ltFooterBorderAbove_clicked()
488 {
489         if (footerBorderAboveCB->isChecked())
490                 set(Tabular::SET_LTFOOT, "dl_above");
491         else
492                 set(Tabular::UNSET_LTFOOT, "dl_above");
493         changed();
494 }
495
496
497 void GuiTabular::ltFooterBorderBelow_clicked()
498 {
499         if (footerBorderBelowCB->isChecked())
500                 set(Tabular::SET_LTFOOT, "dl_below");
501         else
502                 set(Tabular::UNSET_LTFOOT, "dl_below");
503         changed();
504 }
505
506
507 void GuiTabular::ltLastFooterStatus_clicked()
508 {
509         bool enable = lastfooterStatusCB->isChecked();
510         if (enable)
511                 set(Tabular::SET_LTLASTFOOT, "");
512         else
513                 set(Tabular::UNSET_LTLASTFOOT, "");
514         lastfooterBorderAboveCB->setEnabled(enable);
515         lastfooterBorderBelowCB->setEnabled(enable);
516         changed();
517 }
518
519
520 void GuiTabular::ltLastFooterBorderAbove_clicked()
521 {
522         if (lastfooterBorderAboveCB->isChecked())
523                 set(Tabular::SET_LTLASTFOOT, "dl_above");
524         else
525                 set(Tabular::UNSET_LTLASTFOOT, "dl_above");
526         changed();
527 }
528
529
530 void GuiTabular::ltLastFooterBorderBelow_clicked()
531 {
532         if (lastfooterBorderBelowCB->isChecked())
533                 set(Tabular::SET_LTLASTFOOT, "dl_below");
534         else
535                 set(Tabular::UNSET_LTLASTFOOT, "dl_below");
536         changed();
537 }
538
539
540 void GuiTabular::ltLastFooterEmpty_clicked()
541 {
542         bool enable = lastfooterNoContentsCB->isChecked();
543         if (enable)
544                 set(Tabular::SET_LTLASTFOOT, "empty");
545         else
546                 set(Tabular::UNSET_LTLASTFOOT, "empty");
547         lastfooterStatusCB->setEnabled(!enable);
548         lastfooterBorderAboveCB->setEnabled(!enable);
549         lastfooterBorderBelowCB->setEnabled(!enable);
550         changed();
551 }
552
553
554 void GuiTabular::update_borders()
555 {
556         Tabular::idx_type const cell = getActiveCell();
557         bool const isMulticolumnCell = tabular_.isMultiColumn(cell);
558
559         if (!isMulticolumnCell) {
560                 borders->setLeftEnabled(true);
561                 borders->setRightEnabled(true);
562                 borders->setTop(tabular_.topLine(cell, true));
563                 borders->setBottom(tabular_.bottomLine(cell, true));
564                 borders->setLeft(tabular_.leftLine(cell, true));
565                 borders->setRight(tabular_.rightLine(cell, true));
566                 // repaint the setborder widget
567                 borders->update();
568                 return;
569         }
570
571         borders->setTop(tabular_.topLine(cell));
572         borders->setBottom(tabular_.bottomLine(cell));
573         // pay attention to left/right lines: they are only allowed
574         // to set if we are in first/last cell of row or if the left/right
575         // cell is also a multicolumn.
576         if (tabular_.isFirstCellInRow(cell) || tabular_.isMultiColumn(cell - 1)) {
577                 borders->setLeftEnabled(true);
578                 borders->setLeft(tabular_.leftLine(cell));
579         } else {
580                 borders->setLeft(false);
581                 borders->setLeftEnabled(false);
582         }
583         if (tabular_.isLastCellInRow(cell) || tabular_.isMultiColumn(cell + 1)) {
584                 borders->setRightEnabled(true);
585                 borders->setRight(tabular_.rightLine(cell));
586         } else {
587                 borders->setRight(false);
588                 borders->setRightEnabled(false);
589         }
590         // repaint the setborder widget
591         borders->update();
592 }
593
594
595 void GuiTabular::updateContents()
596 {
597         initialiseParams(string());
598
599         Tabular::idx_type const cell = getActiveCell();
600
601         Tabular::row_type const row = tabular_.cellRow(cell);
602         Tabular::col_type const col = tabular_.cellColumn(cell);
603
604         tabularRowED->setText(QString::number(row + 1));
605         tabularColumnED->setText(QString::number(col + 1));
606
607         bool const multicol(tabular_.isMultiColumn(cell));
608
609         multicolumnCB->setChecked(multicol);
610
611         rotateCellCB->setChecked(tabular_.getRotateCell(cell));
612         rotateTabularCB->setChecked(tabular_.getRotateTabular());
613
614         longTabularCB->setChecked(tabular_.isLongTabular());
615
616         update_borders();
617
618         Length pwidth;
619         docstring special;
620
621         if (multicol) {
622                 special = tabular_.getAlignSpecial(cell, Tabular::SET_SPECIAL_MULTI);
623                 pwidth = tabular_.getMColumnPWidth(cell);
624         } else {
625                 special = tabular_.getAlignSpecial(cell, Tabular::SET_SPECIAL_COLUMN);
626                 pwidth = tabular_.getColumnPWidth(cell);
627         }
628
629         specialAlignmentED->setText(toqstr(special));
630
631         bool const isReadonly = bc().policy().isReadOnly();
632         specialAlignmentED->setEnabled(!isReadonly);
633
634         Length::UNIT default_unit =
635                 useMetricUnits() ? Length::CM : Length::IN;
636
637         borderDefaultRB->setChecked(!tabular_.useBookTabs());
638         booktabsRB->setChecked(tabular_.useBookTabs());
639
640         if (tabular_.row_info[row].top_space.empty()
641             && !tabular_.row_info[row].top_space_default) {
642                 topspaceCO->setCurrentIndex(0);
643         } else if (tabular_.row_info[row].top_space_default) {
644                 topspaceCO->setCurrentIndex(1);
645         } else {
646                 topspaceCO->setCurrentIndex(2);
647                 lengthToWidgets(topspaceED,
648                                 topspaceUnit,
649                                 tabular_.row_info[row].top_space.asString(),
650                                 default_unit);
651         }
652         topspaceED->setEnabled(!isReadonly
653                 && (topspaceCO->currentIndex() == 2));
654         topspaceUnit->setEnabled(!isReadonly
655                 && (topspaceCO->currentIndex() == 2));
656         topspaceCO->setEnabled(!isReadonly);
657
658         if (tabular_.row_info[row].bottom_space.empty()
659             && !tabular_.row_info[row].bottom_space_default) {
660                 bottomspaceCO->setCurrentIndex(0);
661         } else if (tabular_.row_info[row].bottom_space_default) {
662                 bottomspaceCO->setCurrentIndex(1);
663         } else {
664                 bottomspaceCO->setCurrentIndex(2);
665                 lengthToWidgets(bottomspaceED,
666                                 bottomspaceUnit,
667                                 tabular_.row_info[row].bottom_space.asString(),
668                                 default_unit);
669         }
670         bottomspaceED->setEnabled(!isReadonly
671                 && (bottomspaceCO->currentIndex() == 2));
672         bottomspaceUnit->setEnabled(!isReadonly
673                 && (bottomspaceCO->currentIndex() == 2));
674         bottomspaceCO->setEnabled(!isReadonly);
675
676         if (tabular_.row_info[row].interline_space.empty()
677             && !tabular_.row_info[row].interline_space_default) {
678                 interlinespaceCO->setCurrentIndex(0);
679         } else if (tabular_.row_info[row].interline_space_default) {
680                 interlinespaceCO->setCurrentIndex(1);
681         } else {
682                 interlinespaceCO->setCurrentIndex(2);
683                 lengthToWidgets(interlinespaceED,
684                                 interlinespaceUnit,
685                                 tabular_.row_info[row].interline_space.asString(),
686                                 default_unit);
687         }
688         interlinespaceED->setEnabled(!isReadonly
689                 && (interlinespaceCO->currentIndex() == 2));
690         interlinespaceUnit->setEnabled(!isReadonly
691                 && (interlinespaceCO->currentIndex() == 2));
692         interlinespaceCO->setEnabled(!isReadonly);
693
694         string colwidth;
695         if (!pwidth.zero())
696                 colwidth = pwidth.asString();
697         lengthToWidgets(widthED, widthUnit,
698                 colwidth, default_unit);
699
700         widthED->setEnabled(!isReadonly);
701         widthUnit->setEnabled(!isReadonly);
702
703         hAlignCB->clear();
704         hAlignCB->addItem(qt_("Left"));
705         hAlignCB->addItem(qt_("Center"));
706         hAlignCB->addItem(qt_("Right"));
707         if (!multicol && !pwidth.zero())
708                 hAlignCB->addItem(qt_("Justified"));
709
710         int align = 0;
711         switch (tabular_.getAlignment(cell)) {
712         case LYX_ALIGN_LEFT:
713                 align = 0;
714                 break;
715         case LYX_ALIGN_CENTER:
716                 align = 1;
717                 break;
718         case LYX_ALIGN_RIGHT:
719                 align = 2;
720                 break;
721         case LYX_ALIGN_BLOCK:
722         {
723                 if (!multicol && !pwidth.zero())
724                         align = 3;
725                 break;
726         }
727         default:
728                 align = 0;
729                 break;
730         }
731         hAlignCB->setCurrentIndex(align);
732
733         int valign = 0;
734         switch (tabular_.getVAlignment(cell)) {
735         case Tabular::LYX_VALIGN_TOP:
736                 valign = 0;
737                 break;
738         case Tabular::LYX_VALIGN_MIDDLE:
739                 valign = 1;
740                 break;
741         case Tabular::LYX_VALIGN_BOTTOM:
742                 valign = 2;
743                 break;
744         default:
745                 valign = 1;
746                 break;
747         }
748         if (pwidth.zero())
749                 valign = 1;
750         vAlignCB->setCurrentIndex(valign);
751
752         hAlignCB->setEnabled(true);
753         vAlignCB->setEnabled(!pwidth.zero());
754
755         if (!tabular_.isLongTabular()) {
756                 headerStatusCB->setChecked(false);
757                 headerBorderAboveCB->setChecked(false);
758                 headerBorderBelowCB->setChecked(false);
759                 firstheaderStatusCB->setChecked(false);
760                 firstheaderBorderAboveCB->setChecked(false);
761                 firstheaderBorderBelowCB->setChecked(false);
762                 firstheaderNoContentsCB->setChecked(false);
763                 footerStatusCB->setChecked(false);
764                 footerBorderAboveCB->setChecked(false);
765                 footerBorderBelowCB->setChecked(false);
766                 lastfooterStatusCB->setChecked(false);
767                 lastfooterBorderAboveCB->setChecked(false);
768                 lastfooterBorderBelowCB->setChecked(false);
769                 lastfooterNoContentsCB->setChecked(false);
770                 newpageCB->setChecked(false);
771                 newpageCB->setEnabled(false);
772                 return;
773         }
774
775         Tabular::ltType ltt;
776         bool use_empty;
777         bool row_set = tabular_.getRowOfLTHead(row, ltt);
778         headerStatusCB->setChecked(row_set);
779         if (ltt.set) {
780                 headerBorderAboveCB->setChecked(ltt.topDL);
781                 headerBorderBelowCB->setChecked(ltt.bottomDL);
782                 use_empty = true;
783         } else {
784                 headerBorderAboveCB->setChecked(false);
785                 headerBorderBelowCB->setChecked(false);
786                 headerBorderAboveCB->setEnabled(false);
787                 headerBorderBelowCB->setEnabled(false);
788                 firstheaderNoContentsCB->setChecked(false);
789                 firstheaderNoContentsCB->setEnabled(false);
790                 use_empty = false;
791         }
792
793         row_set = tabular_.getRowOfLTFirstHead(row, ltt);
794         firstheaderStatusCB->setChecked(row_set);
795         if (ltt.set && (!ltt.empty || !use_empty)) {
796                 firstheaderBorderAboveCB->setChecked(ltt.topDL);
797                 firstheaderBorderBelowCB->setChecked(ltt.bottomDL);
798         } else {
799                 firstheaderBorderAboveCB->setEnabled(false);
800                 firstheaderBorderBelowCB->setEnabled(false);
801                 firstheaderBorderAboveCB->setChecked(false);
802                 firstheaderBorderBelowCB->setChecked(false);
803                 if (use_empty) {
804                         firstheaderNoContentsCB->setChecked(ltt.empty);
805                         if (ltt.empty)
806                                 firstheaderStatusCB->setEnabled(false);
807                 }
808         }
809
810         row_set = tabular_.getRowOfLTFoot(row, ltt);
811         footerStatusCB->setChecked(row_set);
812         if (ltt.set) {
813                 footerBorderAboveCB->setChecked(ltt.topDL);
814                 footerBorderBelowCB->setChecked(ltt.bottomDL);
815                 use_empty = true;
816         } else {
817                 footerBorderAboveCB->setChecked(false);
818                 footerBorderBelowCB->setChecked(false);
819                 footerBorderAboveCB->setEnabled(false);
820                 footerBorderBelowCB->setEnabled(false);
821                 lastfooterNoContentsCB->setChecked(false);
822                 lastfooterNoContentsCB->setEnabled(false);
823                 use_empty = false;
824         }
825
826         row_set = tabular_.getRowOfLTLastFoot(row, ltt);
827                 lastfooterStatusCB->setChecked(row_set);
828         if (ltt.set && (!ltt.empty || !use_empty)) {
829                 lastfooterBorderAboveCB->setChecked(ltt.topDL);
830                 lastfooterBorderBelowCB->setChecked(ltt.bottomDL);
831         } else {
832                 lastfooterBorderAboveCB->setEnabled(false);
833                 lastfooterBorderBelowCB->setEnabled(false);
834                 lastfooterBorderAboveCB->setChecked(false);
835                 lastfooterBorderBelowCB->setChecked(false);
836                 if (use_empty) {
837                         lastfooterNoContentsCB->setChecked(ltt.empty);
838                         if (ltt.empty)
839                                 lastfooterStatusCB->setEnabled(false);
840                 }
841         }
842         newpageCB->setChecked(tabular_.getLTNewPage(row));
843 }
844
845
846 void GuiTabular::closeGUI()
847 {
848         // ugly hack to auto-apply the stuff that hasn't been
849         // yet. don't let this continue to exist ...
850
851         // Subtle here, we must /not/ apply any changes and
852         // then refer to tabular, as it will have been freed
853         // since the changes update the actual tabular_
854         //
855         // apply the fixed width values
856         Tabular::idx_type const cell = getActiveCell();
857         bool const multicol = tabular_.isMultiColumn(cell);
858         string width = widgetsToLength(widthED, widthUnit);
859         string width2;
860
861         Length llen = tabular_.getColumnPWidth(cell);
862         Length llenMulti = tabular_.getMColumnPWidth(cell);
863
864         if (multicol && !llenMulti.zero())
865                 width2 = llenMulti.asString();
866         else if (!multicol && !llen.zero())
867                 width2 = llen.asString();
868
869         // apply the special alignment
870         docstring const sa1 = qstring_to_ucs4(specialAlignmentED->text());
871         docstring sa2;
872
873         if (multicol)
874                 sa2 = tabular_.getAlignSpecial(cell, Tabular::SET_SPECIAL_MULTI);
875         else
876                 sa2 = tabular_.getAlignSpecial(cell, Tabular::SET_SPECIAL_COLUMN);
877
878         if (sa1 != sa2) {
879                 if (multicol)
880                         set(Tabular::SET_SPECIAL_MULTI, to_utf8(sa1));
881                 else
882                         set(Tabular::SET_SPECIAL_COLUMN, to_utf8(sa1));
883         }
884
885         if (width != width2) {
886                 if (multicol)
887                         set(Tabular::SET_MPWIDTH, width);
888                 else
889                         set(Tabular::SET_PWIDTH, width);
890         }
891
892         /* DO WE NEED THIS?
893         switch (topspaceCO->currentIndex()) {
894                 case 0:
895                         set(Tabular::SET_TOP_SPACE, "");
896                         break;
897                 case 1:
898                         set(Tabular::SET_TOP_SPACE, "default");
899                         break;
900                 case 2:
901                         set(Tabular::SET_TOP_SPACE,
902                                 widgetsToLength(topspaceED, topspaceUnit));
903                         break;
904         }
905
906         switch (bottomspaceCO->currentIndex()) {
907                 case 0:
908                         set(Tabular::SET_BOTTOM_SPACE, "");
909                         break;
910                 case 1:
911                         set(Tabular::SET_BOTTOM_SPACE, "default");
912                         break;
913                 case 2:
914                         set(Tabular::SET_BOTTOM_SPACE,
915                                 widgetsToLength(bottomspaceED, bottomspaceUnit));
916                         break;
917         }
918
919         switch (interlinespaceCO->currentIndex()) {
920                 case 0:
921                         set(Tabular::SET_INTERLINE_SPACE, "");
922                         break;
923                 case 1:
924                         set(Tabular::SET_INTERLINE_SPACE, "default");
925                         break;
926                 case 2:
927                         set(Tabular::SET_INTERLINE_SPACE,
928                                 widgetsToLength(interlinespaceED, interlinespaceUnit));
929                         break;
930         }
931 */
932 }
933
934
935 bool GuiTabular::initialiseParams(string const & data)
936 {
937         // try to get the current cell
938         BufferView const * const bv = bufferview();
939         InsetTabular const * current_inset = 0;
940         if (bv) {
941                 Cursor const & cur = bv->cursor();
942                 // get the innermost tabular inset;
943                 // assume that it is "ours"
944                 for (int i = cur.depth() - 1; i >= 0; --i)
945                         if (cur[i].inset().lyxCode() == TABULAR_CODE) {
946                                 current_inset = static_cast<InsetTabular const *>(&cur[i].inset());
947                                 active_cell_ = cur[i].idx();
948                                 break;
949                         }
950         }
951
952         if (current_inset && data.empty()) {
953                 tabular_ = Tabular(current_inset->tabular);
954                 return true;
955         }
956
957         InsetTabular tmp(buffer());
958         InsetTabularMailer::string2params(data, tmp);
959         tabular_ = Tabular(tmp.tabular);
960         return true;
961 }
962
963
964 void GuiTabular::clearParams()
965 {
966         InsetTabular tmp(buffer());
967         tabular_ = tmp.tabular;
968         active_cell_ = Tabular::npos;
969 }
970
971
972 Tabular::idx_type GuiTabular::getActiveCell() const
973 {
974         return active_cell_;
975 }
976
977
978 void GuiTabular::set(Tabular::Feature f, string const & arg)
979 {
980         string const data = featureAsString(f) + ' ' + arg;
981         dispatch(FuncRequest(getLfun(), data));
982 }
983
984
985 bool GuiTabular::useMetricUnits() const
986 {
987         return lyxrc.default_papersize > PAPER_USEXECUTIVE;
988 }
989
990
991 void GuiTabular::toggleTopLine()
992 {
993         if (tabular_.isMultiColumn(getActiveCell()))
994                 set(Tabular::M_TOGGLE_LINE_TOP);
995         else
996                 set(Tabular::TOGGLE_LINE_TOP);
997 }
998
999
1000 void GuiTabular::toggleBottomLine()
1001 {
1002         if (tabular_.isMultiColumn(getActiveCell()))
1003                 set(Tabular::M_TOGGLE_LINE_BOTTOM);
1004         else
1005                 set(Tabular::TOGGLE_LINE_BOTTOM);
1006 }
1007
1008
1009 void GuiTabular::toggleLeftLine()
1010 {
1011         if (tabular_.isMultiColumn(getActiveCell()))
1012                 set(Tabular::M_TOGGLE_LINE_LEFT);
1013         else
1014                 set(Tabular::TOGGLE_LINE_LEFT);
1015 }
1016
1017
1018 void GuiTabular::toggleRightLine()
1019 {
1020         if (tabular_.isMultiColumn(getActiveCell()))
1021                 set(Tabular::M_TOGGLE_LINE_RIGHT);
1022         else
1023                 set(Tabular::TOGGLE_LINE_RIGHT);
1024 }
1025
1026
1027 void GuiTabular::setSpecial(string const & special)
1028 {
1029         if (tabular_.isMultiColumn(getActiveCell()))
1030                 set(Tabular::SET_SPECIAL_MULTI, special);
1031         else
1032                 set(Tabular::SET_SPECIAL_COLUMN, special);
1033 }
1034
1035
1036 void GuiTabular::setWidth(string const & width)
1037 {
1038         if (tabular_.isMultiColumn(getActiveCell()))
1039                 set(Tabular::SET_MPWIDTH, width);
1040         else
1041                 set(Tabular::SET_PWIDTH, width);
1042
1043         updateView();
1044 }
1045
1046
1047 void GuiTabular::toggleMultiColumn()
1048 {
1049         set(Tabular::MULTICOLUMN);
1050         updateView();
1051 }
1052
1053
1054 void GuiTabular::rotateTabular(bool yes)
1055 {
1056         if (yes)
1057                 set(Tabular::SET_ROTATE_TABULAR);
1058         else
1059                 set(Tabular::UNSET_ROTATE_TABULAR);
1060 }
1061
1062
1063 void GuiTabular::rotateCell(bool yes)
1064 {
1065         if (yes)
1066                 set(Tabular::SET_ROTATE_CELL);
1067         else
1068                 set(Tabular::UNSET_ROTATE_CELL);
1069 }
1070
1071
1072 void GuiTabular::halign(GuiTabular::HALIGN h)
1073 {
1074         Tabular::Feature num = Tabular::ALIGN_LEFT;
1075         Tabular::Feature multi_num = Tabular::M_ALIGN_LEFT;
1076
1077         switch (h) {
1078                 case LEFT:
1079                         num = Tabular::ALIGN_LEFT;
1080                         multi_num = Tabular::M_ALIGN_LEFT;
1081                         break;
1082                 case CENTER:
1083                         num = Tabular::ALIGN_CENTER;
1084                         multi_num = Tabular::M_ALIGN_CENTER;
1085                         break;
1086                 case RIGHT:
1087                         num = Tabular::ALIGN_RIGHT;
1088                         multi_num = Tabular::M_ALIGN_RIGHT;
1089                         break;
1090                 case BLOCK:
1091                         num = Tabular::ALIGN_BLOCK;
1092                         //multi_num: no equivalent
1093                         break;
1094         }
1095
1096         if (tabular_.isMultiColumn(getActiveCell()))
1097                 set(multi_num);
1098         else
1099                 set(num);
1100 }
1101
1102
1103 void GuiTabular::valign(GuiTabular::VALIGN v)
1104 {
1105         Tabular::Feature num = Tabular::VALIGN_MIDDLE;
1106         Tabular::Feature multi_num = Tabular::M_VALIGN_MIDDLE;
1107
1108         switch (v) {
1109                 case TOP:
1110                         num = Tabular::VALIGN_TOP;
1111                         multi_num = Tabular::M_VALIGN_TOP;
1112                         break;
1113                 case MIDDLE:
1114                         num = Tabular::VALIGN_MIDDLE;
1115                         multi_num = Tabular::M_VALIGN_MIDDLE;
1116                         break;
1117                 case BOTTOM:
1118                         num = Tabular::VALIGN_BOTTOM;
1119                         multi_num = Tabular::M_VALIGN_BOTTOM;
1120                         break;
1121         }
1122
1123         if (tabular_.isMultiColumn(getActiveCell()))
1124                 set(multi_num);
1125         else
1126                 set(num);
1127 }
1128
1129
1130 void GuiTabular::booktabs(bool yes)
1131 {
1132         if (yes)
1133                 set(Tabular::SET_BOOKTABS);
1134         else
1135                 set(Tabular::UNSET_BOOKTABS);
1136 }
1137
1138
1139 void GuiTabular::longTabular(bool yes)
1140 {
1141         if (yes)
1142                 set(Tabular::SET_LONGTABULAR);
1143         else
1144                 set(Tabular::UNSET_LONGTABULAR);
1145 }
1146
1147
1148 Dialog * createGuiTabular(GuiView & lv) { return new GuiTabular(lv); }
1149
1150
1151 } // namespace frontend
1152 } // namespace lyx
1153
1154 #include "GuiTabular_moc.cpp"