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