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