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