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