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