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