]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiTabular.cpp
76c4f95da7307e97d871954f068f2949bb968e65
[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                 this, 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         changed();
452 }
453
454
455 void GuiTabular::ltHeaderBorderAbove_clicked()
456 {
457         if (headerBorderAboveCB->isChecked())
458                 set(Tabular::SET_LTHEAD, "dl_above");
459         else
460                 set(Tabular::UNSET_LTHEAD, "dl_above");
461         changed();
462 }
463
464
465 void GuiTabular::ltHeaderBorderBelow_clicked()
466 {
467         if (headerBorderBelowCB->isChecked())
468                 set(Tabular::SET_LTHEAD, "dl_below");
469         else
470                 set(Tabular::UNSET_LTHEAD, "dl_below");
471         changed();
472 }
473
474
475 void GuiTabular::ltFirstHeaderBorderAbove_clicked()
476 {
477         if (firstheaderBorderAboveCB->isChecked())
478                 set(Tabular::SET_LTFIRSTHEAD, "dl_above");
479         else
480                 set(Tabular::UNSET_LTFIRSTHEAD, "dl_above");
481         changed();
482 }
483
484
485 void GuiTabular::ltFirstHeaderBorderBelow_clicked()
486 {
487         if (firstheaderBorderBelowCB->isChecked())
488                 set(Tabular::SET_LTFIRSTHEAD, "dl_below");
489         else
490                 set(Tabular::UNSET_LTFIRSTHEAD, "dl_below");
491         changed();
492 }
493
494
495 void GuiTabular::ltFirstHeaderStatus_clicked()
496 {
497         bool enable = firstheaderStatusCB->isChecked();
498         if (enable)
499                 set(Tabular::SET_LTFIRSTHEAD, "");
500         else
501                 set(Tabular::UNSET_LTFIRSTHEAD, "");
502         changed();
503 }
504
505
506 void GuiTabular::ltFirstHeaderEmpty_clicked()
507 {
508         bool enable = firstheaderNoContentsCB->isChecked();
509         if (enable)
510                 set(Tabular::SET_LTFIRSTHEAD, "empty");
511         else
512                 set(Tabular::UNSET_LTFIRSTHEAD, "empty");
513         changed();
514 }
515
516
517 void GuiTabular::ltFooterStatus_clicked()
518 {
519         bool enable = footerStatusCB->isChecked();
520         if (enable)
521                 set(Tabular::SET_LTFOOT, "");
522         else
523                 set(Tabular::UNSET_LTFOOT, "");
524         changed();
525 }
526
527
528 void GuiTabular::ltFooterBorderAbove_clicked()
529 {
530         if (footerBorderAboveCB->isChecked())
531                 set(Tabular::SET_LTFOOT, "dl_above");
532         else
533                 set(Tabular::UNSET_LTFOOT, "dl_above");
534         changed();
535 }
536
537
538 void GuiTabular::ltFooterBorderBelow_clicked()
539 {
540         if (footerBorderBelowCB->isChecked())
541                 set(Tabular::SET_LTFOOT, "dl_below");
542         else
543                 set(Tabular::UNSET_LTFOOT, "dl_below");
544         changed();
545 }
546
547
548 void GuiTabular::ltLastFooterStatus_clicked()
549 {
550         bool enable = lastfooterStatusCB->isChecked();
551         if (enable)
552                 set(Tabular::SET_LTLASTFOOT, "");
553         else
554                 set(Tabular::UNSET_LTLASTFOOT, "");
555         changed();
556 }
557
558
559 void GuiTabular::ltLastFooterBorderAbove_clicked()
560 {
561         if (lastfooterBorderAboveCB->isChecked())
562                 set(Tabular::SET_LTLASTFOOT, "dl_above");
563         else
564                 set(Tabular::UNSET_LTLASTFOOT, "dl_above");
565         changed();
566 }
567
568
569 void GuiTabular::ltLastFooterBorderBelow_clicked()
570 {
571         if (lastfooterBorderBelowCB->isChecked())
572                 set(Tabular::SET_LTLASTFOOT, "dl_below");
573         else
574                 set(Tabular::UNSET_LTLASTFOOT, "dl_below");
575         changed();
576 }
577
578
579 void GuiTabular::ltLastFooterEmpty_clicked()
580 {
581         bool enable = lastfooterNoContentsCB->isChecked();
582         if (enable)
583                 set(Tabular::SET_LTLASTFOOT, "empty");
584         else
585                 set(Tabular::UNSET_LTLASTFOOT, "empty");
586         changed();
587 }
588
589
590 void GuiTabular::update_borders()
591 {
592         Tabular::idx_type const cell = getActiveCell();
593         borders->setTop(tabular_.topLine(cell));
594         borders->setBottom(tabular_.bottomLine(cell));
595         borders->setLeft(tabular_.leftLine(cell));
596         borders->setRight(tabular_.rightLine(cell));
597         // repaint the setborder widget
598         borders->update();
599 }
600
601
602 namespace {
603
604 Length getColumnPWidth(Tabular const & t, size_t cell)
605 {
606         return t.column_info[t.cellColumn(cell)].p_width;
607 }
608
609
610 Length getMColumnPWidth(Tabular const & t, size_t cell)
611 {
612         if (t.isMultiColumn(cell))
613                 return t.cellInfo(cell).p_width;
614         return Length();
615 }
616
617
618 docstring getAlignSpecial(Tabular const & t, size_t cell, int what)
619 {
620         if (what == Tabular::SET_SPECIAL_MULTI)
621                 return t.cellInfo(cell).align_special;
622         return t.column_info[t.cellColumn(cell)].align_special;
623 }
624
625 }
626
627
628
629 void GuiTabular::updateContents()
630 {
631         initialiseParams(string());
632
633         size_t const cell = getActiveCell();
634
635         Tabular::row_type const row = tabular_.cellRow(cell);
636         Tabular::col_type const col = tabular_.cellColumn(cell);
637
638         tabularRowED->setText(QString::number(row + 1));
639         tabularColumnED->setText(QString::number(col + 1));
640
641         bool const multicol(tabular_.isMultiColumn(cell));
642
643         multicolumnCB->setChecked(multicol);
644
645         rotateCellCB->setChecked(tabular_.getRotateCell(cell));
646         rotateTabularCB->setChecked(tabular_.rotate);
647
648         longTabularCB->setChecked(tabular_.is_long_tabular);
649
650         update_borders();
651
652         Length pwidth;
653         docstring special;
654
655         if (multicol) {
656                 special = getAlignSpecial(tabular_, cell,
657                         Tabular::SET_SPECIAL_MULTI);
658                 pwidth = getMColumnPWidth(tabular_, cell);
659         } else {
660                 special = getAlignSpecial(tabular_, cell,
661                         Tabular::SET_SPECIAL_COLUMN);
662                 pwidth = getColumnPWidth(tabular_, cell);
663         }
664
665         specialAlignmentED->setText(toqstr(special));
666
667         bool const isReadonly = bc().policy().isReadOnly();
668         specialAlignmentED->setEnabled(!isReadonly);
669
670         Length::UNIT const default_unit = Length::defaultUnit();
671
672         borderDefaultRB->setChecked(!tabular_.use_booktabs);
673         booktabsRB->setChecked(tabular_.use_booktabs);
674
675         if (tabular_.row_info[row].top_space.empty()
676             && !tabular_.row_info[row].top_space_default) {
677                 topspaceCO->setCurrentIndex(0);
678         } else if (tabular_.row_info[row].top_space_default) {
679                 topspaceCO->setCurrentIndex(1);
680         } else {
681                 topspaceCO->setCurrentIndex(2);
682                 lengthToWidgets(topspaceED,
683                                 topspaceUnit,
684                                 tabular_.row_info[row].top_space.asString(),
685                                 default_unit);
686         }
687         topspaceED->setEnabled(!isReadonly
688                 && (topspaceCO->currentIndex() == 2));
689         topspaceUnit->setEnabled(!isReadonly
690                 && (topspaceCO->currentIndex() == 2));
691         topspaceCO->setEnabled(!isReadonly);
692
693         if (tabular_.row_info[row].bottom_space.empty()
694             && !tabular_.row_info[row].bottom_space_default) {
695                 bottomspaceCO->setCurrentIndex(0);
696         } else if (tabular_.row_info[row].bottom_space_default) {
697                 bottomspaceCO->setCurrentIndex(1);
698         } else {
699                 bottomspaceCO->setCurrentIndex(2);
700                 lengthToWidgets(bottomspaceED,
701                                 bottomspaceUnit,
702                                 tabular_.row_info[row].bottom_space.asString(),
703                                 default_unit);
704         }
705         bottomspaceED->setEnabled(!isReadonly
706                 && (bottomspaceCO->currentIndex() == 2));
707         bottomspaceUnit->setEnabled(!isReadonly
708                 && (bottomspaceCO->currentIndex() == 2));
709         bottomspaceCO->setEnabled(!isReadonly);
710
711         if (tabular_.row_info[row].interline_space.empty()
712             && !tabular_.row_info[row].interline_space_default) {
713                 interlinespaceCO->setCurrentIndex(0);
714         } else if (tabular_.row_info[row].interline_space_default) {
715                 interlinespaceCO->setCurrentIndex(1);
716         } else {
717                 interlinespaceCO->setCurrentIndex(2);
718                 lengthToWidgets(interlinespaceED,
719                                 interlinespaceUnit,
720                                 tabular_.row_info[row].interline_space.asString(),
721                                 default_unit);
722         }
723         interlinespaceED->setEnabled(!isReadonly
724                 && (interlinespaceCO->currentIndex() == 2));
725         interlinespaceUnit->setEnabled(!isReadonly
726                 && (interlinespaceCO->currentIndex() == 2));
727         interlinespaceCO->setEnabled(!isReadonly);
728
729         string colwidth;
730         if (!pwidth.zero())
731                 colwidth = pwidth.asString();
732         lengthToWidgets(widthED, widthUnit,
733                 colwidth, default_unit);
734
735         widthED->setEnabled(!isReadonly);
736         widthUnit->setEnabled(!isReadonly);
737
738         hAlignCB->clear();
739         hAlignCB->addItem(qt_("Left"));
740         hAlignCB->addItem(qt_("Center"));
741         hAlignCB->addItem(qt_("Right"));
742         if (!multicol && !pwidth.zero())
743                 hAlignCB->addItem(qt_("Justified"));
744
745         int align = 0;
746         switch (tabular_.getAlignment(cell)) {
747         case LYX_ALIGN_LEFT:
748                 align = 0;
749                 break;
750         case LYX_ALIGN_CENTER:
751                 align = 1;
752                 break;
753         case LYX_ALIGN_RIGHT:
754                 align = 2;
755                 break;
756         case LYX_ALIGN_BLOCK:
757         {
758                 if (!multicol && !pwidth.zero())
759                         align = 3;
760                 break;
761         }
762         default:
763                 align = 0;
764                 break;
765         }
766         hAlignCB->setCurrentIndex(align);
767
768         int valign = 0;
769         switch (tabular_.getVAlignment(cell)) {
770         case Tabular::LYX_VALIGN_TOP:
771                 valign = 0;
772                 break;
773         case Tabular::LYX_VALIGN_MIDDLE:
774                 valign = 1;
775                 break;
776         case Tabular::LYX_VALIGN_BOTTOM:
777                 valign = 2;
778                 break;
779         default:
780                 valign = 0;
781                 break;
782         }
783         if (pwidth.zero())
784                 valign = 0;
785         vAlignCB->setCurrentIndex(valign);
786
787         hAlignCB->setEnabled(true);
788         vAlignCB->setEnabled(!pwidth.zero());
789
790         if (!tabular_.is_long_tabular) {
791                 headerStatusCB->setChecked(false);
792                 headerBorderAboveCB->setChecked(false);
793                 headerBorderBelowCB->setChecked(false);
794                 firstheaderStatusCB->setChecked(false);
795                 firstheaderBorderAboveCB->setChecked(false);
796                 firstheaderBorderBelowCB->setChecked(false);
797                 firstheaderNoContentsCB->setChecked(false);
798                 footerStatusCB->setChecked(false);
799                 footerBorderAboveCB->setChecked(false);
800                 footerBorderBelowCB->setChecked(false);
801                 lastfooterStatusCB->setChecked(false);
802                 lastfooterBorderAboveCB->setChecked(false);
803                 lastfooterBorderBelowCB->setChecked(false);
804                 lastfooterNoContentsCB->setChecked(false);
805                 newpageCB->setChecked(false);
806                 newpageCB->setEnabled(false);
807                 captionStatusCB->blockSignals(true);
808                 captionStatusCB->setChecked(false);
809                 captionStatusCB->blockSignals(false);
810                 return;
811         }
812         captionStatusCB->blockSignals(true);
813         captionStatusCB->setChecked(tabular_.ltCaption(row));
814         captionStatusCB->blockSignals(false);
815
816         // FIXME: shouldn't this be handled by GuiDialog?
817         // FIXME: Some of them should be handled directly in TabularUI.ui
818         firstheaderBorderAboveCB->setEnabled(
819                 funcEnabled(Tabular::SET_LTFIRSTHEAD));
820         firstheaderBorderBelowCB->setEnabled(
821                 funcEnabled(Tabular::SET_LTFIRSTHEAD));
822         // first header can only be suppressed when there is a header
823         firstheaderNoContentsCB->setEnabled(tabular_.haveLTHead()
824                 && !tabular_.haveLTFirstHead());
825
826         //firstheaderStatusCB->setEnabled(
827         //      !firstheaderNoContentsCB->isChecked());
828         headerBorderAboveCB->setEnabled(funcEnabled(Tabular::SET_LTHEAD));
829         headerBorderBelowCB->setEnabled(funcEnabled(Tabular::SET_LTHEAD));
830         headerStatusCB->setEnabled(funcEnabled(Tabular::SET_LTHEAD));
831
832         footerBorderAboveCB->setEnabled(funcEnabled(Tabular::SET_LTFOOT));
833         footerBorderBelowCB->setEnabled(funcEnabled(Tabular::SET_LTFOOT));
834         footerStatusCB->setEnabled(funcEnabled(Tabular::SET_LTFOOT));
835
836         lastfooterBorderAboveCB->setEnabled(
837                 funcEnabled(Tabular::SET_LTLASTFOOT));
838         lastfooterBorderBelowCB->setEnabled(
839                 funcEnabled(Tabular::SET_LTLASTFOOT));
840         // last footer can only be suppressed when there is a footer
841         lastfooterNoContentsCB->setEnabled(tabular_.haveLTFoot()
842                 && !tabular_.haveLTLastFoot());
843
844         captionStatusCB->setEnabled(
845                 funcEnabled(Tabular::TOGGLE_LTCAPTION));
846         // When a row is set as longtable caption, it must not be allowed
847         // to unset that this row is a multicolumn.
848         multicolumnCB->setEnabled(funcEnabled(Tabular::MULTICOLUMN));
849
850         Tabular::ltType ltt;
851         bool use_empty;
852         bool row_set = tabular_.getRowOfLTHead(row, ltt);
853         headerStatusCB->setChecked(row_set);
854         if (ltt.set) {
855                 headerBorderAboveCB->setChecked(ltt.topDL);
856                 headerBorderBelowCB->setChecked(ltt.bottomDL);
857                 use_empty = true;
858         } else {
859                 headerBorderAboveCB->setChecked(false);
860                 headerBorderBelowCB->setChecked(false);
861                 headerBorderAboveCB->setEnabled(false);
862                 headerBorderBelowCB->setEnabled(false);
863                 firstheaderNoContentsCB->setChecked(false);
864                 firstheaderNoContentsCB->setEnabled(false);
865                 use_empty = false;
866         }
867
868         row_set = tabular_.getRowOfLTFirstHead(row, ltt);
869         // check if setting a first header is allowed
870         // additionally check firstheaderNoContentsCB because when this is
871         // the case a first header makes no sense
872         firstheaderStatusCB->setEnabled(
873                 funcEnabled(Tabular::SET_LTFIRSTHEAD)
874                 && !firstheaderNoContentsCB->isChecked());
875         firstheaderStatusCB->setChecked(row_set);
876         if (ltt.set && (!ltt.empty || !use_empty)) {
877                 firstheaderBorderAboveCB->setChecked(ltt.topDL);
878                 firstheaderBorderBelowCB->setChecked(ltt.bottomDL);
879         } else {
880                 firstheaderBorderAboveCB->setEnabled(false);
881                 firstheaderBorderBelowCB->setEnabled(false);
882                 firstheaderBorderAboveCB->setChecked(false);
883                 firstheaderBorderBelowCB->setChecked(false);
884                 if (use_empty) {
885                         if (ltt.empty)
886                                 firstheaderStatusCB->setEnabled(false);
887                 }
888         }
889
890         row_set = tabular_.getRowOfLTFoot(row, ltt);
891         footerStatusCB->setChecked(row_set);
892         if (ltt.set) {
893                 footerBorderAboveCB->setChecked(ltt.topDL);
894                 footerBorderBelowCB->setChecked(ltt.bottomDL);
895                 use_empty = true;
896         } else {
897                 footerBorderAboveCB->setChecked(false);
898                 footerBorderBelowCB->setChecked(false);
899                 footerBorderAboveCB->setEnabled(false);
900                 footerBorderBelowCB->setEnabled(false);
901                 lastfooterNoContentsCB->setChecked(false);
902                 lastfooterNoContentsCB->setEnabled(false);
903                 use_empty = false;
904         }
905
906         row_set = tabular_.getRowOfLTLastFoot(row, ltt);
907         // check if setting a last footer is allowed
908         // additionally check lastfooterNoContentsCB because when this is
909         // the case a last footer makes no sense
910         lastfooterStatusCB->setEnabled(
911                 funcEnabled(Tabular::SET_LTLASTFOOT)
912                 && !lastfooterNoContentsCB->isChecked());
913         lastfooterStatusCB->setChecked(row_set);
914         if (ltt.set && (!ltt.empty || !use_empty)) {
915                 lastfooterBorderAboveCB->setChecked(ltt.topDL);
916                 lastfooterBorderBelowCB->setChecked(ltt.bottomDL);
917         } else {
918                 lastfooterBorderAboveCB->setEnabled(false);
919                 lastfooterBorderBelowCB->setEnabled(false);
920                 lastfooterBorderAboveCB->setChecked(false);
921                 lastfooterBorderBelowCB->setChecked(false);
922                 if (use_empty) {
923                         if (ltt.empty)
924                                 lastfooterStatusCB->setEnabled(false);
925                 }
926         }
927         newpageCB->setChecked(tabular_.getLTNewPage(row));
928 }
929
930
931 void GuiTabular::closeGUI()
932 {
933         // ugly hack to auto-apply the stuff that hasn't been
934         // yet. don't let this continue to exist ...
935
936         // Subtle here, we must /not/ apply any changes and
937         // then refer to tabular, as it will have been freed
938         // since the changes update the actual tabular_
939         //
940         // apply the fixed width values
941         size_t const cell = getActiveCell();
942         bool const multicol = tabular_.isMultiColumn(cell);
943         string width = widgetsToLength(widthED, widthUnit);
944         string width2;
945
946         Length llen = getColumnPWidth(tabular_, cell);
947         Length llenMulti = getMColumnPWidth(tabular_, cell);
948
949         if (multicol && !llenMulti.zero())
950                 width2 = llenMulti.asString();
951         else if (!multicol && !llen.zero())
952                 width2 = llen.asString();
953
954         // apply the special alignment
955         docstring const sa1 = qstring_to_ucs4(specialAlignmentED->text());
956         docstring sa2;
957
958         if (multicol)
959                 sa2 = getAlignSpecial(tabular_, cell,
960                         Tabular::SET_SPECIAL_MULTI);
961         else
962                 sa2 = getAlignSpecial(tabular_, cell,
963                         Tabular::SET_SPECIAL_COLUMN);
964
965         if (sa1 != sa2) {
966                 if (multicol)
967                         set(Tabular::SET_SPECIAL_MULTI, to_utf8(sa1));
968                 else
969                         set(Tabular::SET_SPECIAL_COLUMN, to_utf8(sa1));
970         }
971
972         if (width != width2) {
973                 if (multicol)
974                         set(Tabular::SET_MPWIDTH, width);
975                 else
976                         set(Tabular::SET_PWIDTH, width);
977         }
978
979         /* DO WE NEED THIS?
980         switch (topspaceCO->currentIndex()) {
981                 case 0:
982                         set(Tabular::SET_TOP_SPACE, "");
983                         break;
984                 case 1:
985                         set(Tabular::SET_TOP_SPACE, "default");
986                         break;
987                 case 2:
988                         set(Tabular::SET_TOP_SPACE,
989                                 widgetsToLength(topspaceED,
990                                         topspaceUnit));
991                         break;
992         }
993
994         switch (bottomspaceCO->currentIndex()) {
995                 case 0:
996                         set(Tabular::SET_BOTTOM_SPACE, "");
997                         break;
998                 case 1:
999                         set(Tabular::SET_BOTTOM_SPACE, "default");
1000                         break;
1001                 case 2:
1002                         set(Tabular::SET_BOTTOM_SPACE,
1003                                 widgetsToLength(bottomspaceED,
1004                                         bottomspaceUnit));
1005                         break;
1006         }
1007
1008         switch (interlinespaceCO->currentIndex()) {
1009                 case 0:
1010                         set(Tabular::SET_INTERLINE_SPACE, "");
1011                         break;
1012                 case 1:
1013                         set(Tabular::SET_INTERLINE_SPACE, "default");
1014                         break;
1015                 case 2:
1016                         set(Tabular::SET_INTERLINE_SPACE,
1017                                 widgetsToLength(interlinespaceED,
1018                                         interlinespaceUnit));
1019                         break;
1020         }
1021 */
1022 }
1023
1024
1025 bool GuiTabular::initialiseParams(string const & data)
1026 {
1027         // try to get the current cell
1028         BufferView const * const bv = bufferview();
1029         InsetTabular const * current_inset = 0;
1030         if (bv) {
1031                 Cursor const & cur = bv->cursor();
1032                 // get the innermost tabular inset;
1033                 // assume that it is "ours"
1034                 for (int i = cur.depth() - 1; i >= 0; --i)
1035                         if (cur[i].inset().lyxCode() == TABULAR_CODE) {
1036                                 current_inset =
1037                                         static_cast<InsetTabular const *>(&cur[i].inset());
1038                                 active_cell_ = cur[i].idx();
1039                                 break;
1040                         }
1041         }
1042
1043         if (current_inset && data.empty()) {
1044                 tabular_ = Tabular(current_inset->tabular);
1045                 return true;
1046         }
1047
1048         InsetTabular tmp(const_cast<Buffer &>(buffer()));
1049         InsetTabular::string2params(data, tmp);
1050         tabular_ = Tabular(tmp.tabular);
1051         return true;
1052 }
1053
1054
1055 void GuiTabular::clearParams()
1056 {
1057         // This function is also called when LyX is closing and the dialog
1058         // is still open. At that time, the buffer might not be available
1059         // anymore.
1060         if (isBufferAvailable()) {
1061                 InsetTabular tmp(const_cast<Buffer &>(buffer()));
1062                 tabular_ = tmp.tabular;
1063         }
1064         active_cell_ = Tabular::npos;
1065 }
1066
1067
1068 Tabular::idx_type GuiTabular::getActiveCell() const
1069 {
1070         return active_cell_;
1071 }
1072
1073
1074 void GuiTabular::set(Tabular::Feature f, string const & arg)
1075 {
1076         string const data = featureAsString(f) + ' ' + arg;
1077         dispatch(FuncRequest(getLfun(), data));
1078 }
1079
1080
1081 void GuiTabular::setSpecial(string const & special)
1082 {
1083         if (tabular_.isMultiColumn(getActiveCell()))
1084                 set(Tabular::SET_SPECIAL_MULTI, special);
1085         else
1086                 set(Tabular::SET_SPECIAL_COLUMN, special);
1087 }
1088
1089
1090 void GuiTabular::setWidth(string const & width)
1091 {
1092         if (tabular_.isMultiColumn(getActiveCell()))
1093                 set(Tabular::SET_MPWIDTH, width);
1094         else
1095                 set(Tabular::SET_PWIDTH, width);
1096
1097         updateView();
1098 }
1099
1100
1101 void GuiTabular::toggleMultiColumn()
1102 {
1103         set(Tabular::MULTICOLUMN);
1104         updateView();
1105 }
1106
1107
1108 void GuiTabular::rotateTabular(bool yes)
1109 {
1110         if (yes)
1111                 set(Tabular::SET_ROTATE_TABULAR);
1112         else
1113                 set(Tabular::UNSET_ROTATE_TABULAR);
1114 }
1115
1116
1117 void GuiTabular::rotateCell(bool yes)
1118 {
1119         if (yes)
1120                 set(Tabular::SET_ROTATE_CELL);
1121         else
1122                 set(Tabular::UNSET_ROTATE_CELL);
1123 }
1124
1125
1126 void GuiTabular::halign(GuiTabular::HALIGN h)
1127 {
1128         Tabular::Feature num = Tabular::ALIGN_LEFT;
1129         Tabular::Feature multi_num = Tabular::M_ALIGN_LEFT;
1130
1131         switch (h) {
1132                 case LEFT:
1133                         num = Tabular::ALIGN_LEFT;
1134                         multi_num = Tabular::M_ALIGN_LEFT;
1135                         break;
1136                 case CENTER:
1137                         num = Tabular::ALIGN_CENTER;
1138                         multi_num = Tabular::M_ALIGN_CENTER;
1139                         break;
1140                 case RIGHT:
1141                         num = Tabular::ALIGN_RIGHT;
1142                         multi_num = Tabular::M_ALIGN_RIGHT;
1143                         break;
1144                 case BLOCK:
1145                         num = Tabular::ALIGN_BLOCK;
1146                         //multi_num: no equivalent
1147                         break;
1148         }
1149
1150         if (tabular_.isMultiColumn(getActiveCell()))
1151                 set(multi_num);
1152         else
1153                 set(num);
1154 }
1155
1156
1157 void GuiTabular::valign(GuiTabular::VALIGN v)
1158 {
1159         Tabular::Feature num = Tabular::VALIGN_MIDDLE;
1160         Tabular::Feature multi_num = Tabular::M_VALIGN_MIDDLE;
1161
1162         switch (v) {
1163                 case TOP:
1164                         num = Tabular::VALIGN_TOP;
1165                         multi_num = Tabular::M_VALIGN_TOP;
1166                         break;
1167                 case MIDDLE:
1168                         num = Tabular::VALIGN_MIDDLE;
1169                         multi_num = Tabular::M_VALIGN_MIDDLE;
1170                         break;
1171                 case BOTTOM:
1172                         num = Tabular::VALIGN_BOTTOM;
1173                         multi_num = Tabular::M_VALIGN_BOTTOM;
1174                         break;
1175         }
1176
1177         if (tabular_.isMultiColumn(getActiveCell()))
1178                 set(multi_num);
1179         else
1180                 set(num);
1181 }
1182
1183
1184 void GuiTabular::booktabs(bool yes)
1185 {
1186         if (yes)
1187                 set(Tabular::SET_BOOKTABS);
1188         else
1189                 set(Tabular::UNSET_BOOKTABS);
1190 }
1191
1192
1193 void GuiTabular::longTabular(bool yes)
1194 {
1195         if (yes)
1196                 set(Tabular::SET_LONGTABULAR);
1197         else
1198                 set(Tabular::UNSET_LONGTABULAR);
1199 }
1200
1201
1202 // to get the status of the longtable row settings
1203 bool GuiTabular::funcEnabled(Tabular::Feature f) const
1204 {
1205         return getStatus(
1206                 FuncRequest(getLfun(), featureAsString(f))).enabled();
1207 }
1208
1209
1210 Dialog * createGuiTabular(GuiView & lv) { return new GuiTabular(lv); }
1211
1212
1213 } // namespace frontend
1214 } // namespace lyx
1215
1216 #include "moc_GuiTabular.cpp"