]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiTabular.cpp
* fix spelling in comments to please John.
[lyx.git] / src / frontends / qt4 / GuiTabular.cpp
1 /**
2  * \file GuiTabular.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
7  * \author Jürgen Spitzmüller
8  * \author Herbert Voß
9  * \author Uwe Stöhr
10  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 #include <config.h>
15
16 #include "GuiTabular.h"
17
18 #include "GuiSetBorder.h"
19 #include "GuiView.h"
20 #include "LengthCombo.h"
21 #include "qt_helpers.h"
22 #include "Validator.h"
23
24 #include "BufferView.h"
25 #include "Cursor.h"
26 #include "FuncRequest.h"
27 #include "FuncStatus.h"
28 #include "LyXFunc.h"
29
30 #include "insets/InsetTabular.h"
31
32 #include <QCheckBox>
33 #include <QPushButton>
34 #include <QRadioButton>
35 #include <QLineEdit>
36
37 using namespace std;
38
39 namespace lyx {
40 namespace frontend {
41
42 GuiTabular::GuiTabular(GuiView & lv)
43         : GuiDialog(lv, "tabular", qt_("Table Settings")),
44         // tabular_ is initialised at dialog construction in initialiseParams()
45         tabular_(&(lv.currentBufferView()->buffer()), 0, 0),
46         applying_(false)
47 {
48         active_cell_ = Tabular::npos;
49
50         setupUi(this);
51
52         connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
53         connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
54         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
55         connect(restorePB, SIGNAL(clicked()), this, SLOT(slotRestore()));
56
57         // Manage the restore, ok, apply, restore and cancel/close buttons
58         bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
59         bc().setOK(okPB);
60         bc().setApply(applyPB);
61         bc().setCancel(closePB);
62         bc().setRestore(restorePB);
63
64         widthED->setValidator(unsignedLengthValidator(widthED));
65         topspaceED->setValidator(new LengthValidator(topspaceED));
66         bottomspaceED->setValidator(new LengthValidator(bottomspaceED));
67         interlinespaceED->setValidator(new LengthValidator(interlinespaceED));
68
69         widthUnitCB->setCurrentItem(Length::defaultUnit());
70
71         connect(topspaceED, SIGNAL(textChanged(QString)),
72                 this, SLOT(change_adaptor()));
73         connect(topspaceUnit, SIGNAL(selectionChanged(lyx::Length::UNIT)),
74                 this, SLOT(change_adaptor()));
75         connect(topspaceCO, SIGNAL(activated(int)),
76                 this, SLOT(topspace_changed()));
77         connect(bottomspaceED, SIGNAL(textChanged(QString)),
78                 this, SLOT(change_adaptor()));
79         connect(bottomspaceUnit, SIGNAL(selectionChanged(lyx::Length::UNIT)),
80                 this, SLOT(change_adaptor()));
81         connect(bottomspaceCO, SIGNAL(activated(int)),
82                 this, SLOT(bottomspace_changed()));
83         connect(interlinespaceED, SIGNAL(textChanged(QString)),
84                 this, SLOT(change_adaptor()));
85         connect(interlinespaceUnit, SIGNAL(selectionChanged(lyx::Length::UNIT)),
86                 this, SLOT(change_adaptor()));
87         connect(interlinespaceCO, SIGNAL(activated(int)),
88                 this, SLOT(interlinespace_changed()));
89         connect(booktabsRB, SIGNAL(clicked(bool)),
90                 this, SLOT(booktabsChanged(bool)));
91         connect(borderDefaultRB, SIGNAL(clicked(bool)),
92                 this, SLOT(booktabsChanged(bool)));
93         connect(borderSetPB, SIGNAL(clicked()),
94                 this, SLOT(borderSet_clicked()));
95         connect(borderUnsetPB, SIGNAL(clicked()), 
96                 this, SLOT(borderUnset_clicked()));
97         connect(longTabularCB, SIGNAL(toggled(bool)),
98                 longtableGB, SLOT(setEnabled(bool)));
99         connect(longTabularCB, SIGNAL(toggled(bool)),
100                 newpageCB, SLOT(setEnabled(bool)));
101         connect(longTabularCB, SIGNAL(toggled(bool)),
102                 alignmentGB, SLOT(setEnabled(bool)));
103         // longtables cannot have a vertical alignment
104         connect(longTabularCB, SIGNAL(toggled(bool)),
105                 TableAlignCB, SLOT(setDisabled(bool)));
106         connect(hAlignCB, SIGNAL(activated(int)),
107                 this, SLOT(change_adaptor()));
108         connect(vAlignCB, SIGNAL(activated(int)),
109                 this, SLOT(change_adaptor()));
110         connect(multicolumnCB, SIGNAL(clicked()),
111                 this, SLOT(change_adaptor()));
112         connect(newpageCB, SIGNAL(clicked()),
113                 this, SLOT(change_adaptor()));
114         connect(captionStatusCB, SIGNAL(clicked()),
115                 this, SLOT(change_adaptor()));
116         connect(headerStatusCB, SIGNAL(clicked()),
117                 this, SLOT(change_adaptor()));
118         connect(headerBorderAboveCB, SIGNAL(clicked()),
119                 this, SLOT(change_adaptor()));
120         connect(headerBorderBelowCB, SIGNAL(clicked()),
121                 this, SLOT(change_adaptor()));
122         connect(firstheaderStatusCB, SIGNAL(clicked()),
123                 this, SLOT(change_adaptor()));
124         connect(firstheaderBorderAboveCB, SIGNAL(clicked()),
125                 this, SLOT(change_adaptor()));
126         connect(firstheaderBorderBelowCB, SIGNAL(clicked()),
127                 this, SLOT(change_adaptor()));
128         connect(firstheaderNoContentsCB, SIGNAL(clicked()),
129                 this, SLOT(change_adaptor()));
130         connect(footerStatusCB, SIGNAL(clicked()),
131                 this, SLOT(change_adaptor()));
132         connect(footerBorderAboveCB, SIGNAL(clicked()),
133                 this, SLOT(change_adaptor()));
134         connect(footerBorderBelowCB, SIGNAL(clicked()),
135                 this, SLOT(change_adaptor()));
136         connect(lastfooterStatusCB, SIGNAL(clicked()),
137                 this, SLOT(change_adaptor()));
138         connect(lastfooterBorderAboveCB, SIGNAL(clicked()),
139                 this, SLOT(change_adaptor()));
140         connect(lastfooterBorderBelowCB, SIGNAL(clicked()),
141                 this, SLOT(change_adaptor()));
142         connect(lastfooterNoContentsCB, SIGNAL(clicked()),
143                 this, SLOT(change_adaptor()));
144         connect(specialAlignmentED, SIGNAL(textChanged(QString)),
145                 this, SLOT(change_adaptor()));
146         connect(widthED, SIGNAL(textChanged(QString)),
147                 this, SLOT(change_adaptor()));
148         connect(widthUnitCB, SIGNAL(selectionChanged(lyx::Length::UNIT)),
149                 this, SLOT(change_adaptor()));
150         connect(borders, SIGNAL(clicked()),
151                 this, SLOT(change_adaptor()));
152         connect(rotateTabularCB, SIGNAL(clicked()),
153                 this, SLOT(change_adaptor()));
154         connect(rotateCellCB, SIGNAL(clicked()),
155                 this, SLOT(change_adaptor()));
156         connect(TableAlignCB, SIGNAL(activated(int)),
157                 this, SLOT(change_adaptor()));
158         connect(longTabularCB, SIGNAL(clicked()),
159                 this, SLOT(change_adaptor()));
160         connect(leftRB, SIGNAL(clicked()),
161                 this, SLOT(change_adaptor()));
162         connect(centerRB, SIGNAL(clicked()),
163                 this, SLOT(change_adaptor()));
164         connect(rightRB, SIGNAL(clicked()),
165                 this, SLOT(change_adaptor()));
166
167         bc().addReadOnly(topspaceED);
168         bc().addReadOnly(topspaceUnit);
169         bc().addReadOnly(topspaceCO);
170         bc().addReadOnly(bottomspaceED);
171         bc().addReadOnly(bottomspaceUnit);
172         bc().addReadOnly(bottomspaceCO);
173         bc().addReadOnly(interlinespaceED);
174         bc().addReadOnly(interlinespaceUnit);
175         bc().addReadOnly(interlinespaceCO);
176         bc().addReadOnly(borderDefaultRB);
177         bc().addReadOnly(booktabsRB);
178
179         bc().addReadOnly(multicolumnCB);
180         bc().addReadOnly(rotateCellCB);
181         bc().addReadOnly(rotateTabularCB);
182         bc().addReadOnly(specialAlignmentED);
183         bc().addReadOnly(widthED);
184         bc().addReadOnly(widthUnitCB);
185         bc().addReadOnly(hAlignCB);
186         bc().addReadOnly(vAlignCB);
187         bc().addReadOnly(TableAlignCB);
188         bc().addReadOnly(borderSetPB);
189         bc().addReadOnly(borderUnsetPB);
190         bc().addReadOnly(borders);
191         bc().addReadOnly(longTabularCB);
192         bc().addReadOnly(headerStatusCB);
193         bc().addReadOnly(headerBorderAboveCB);
194         bc().addReadOnly(headerBorderBelowCB);
195         bc().addReadOnly(firstheaderStatusCB);
196         bc().addReadOnly(firstheaderBorderAboveCB);
197         bc().addReadOnly(firstheaderBorderBelowCB);
198         bc().addReadOnly(firstheaderNoContentsCB);
199         bc().addReadOnly(footerStatusCB);
200         bc().addReadOnly(footerBorderAboveCB);
201         bc().addReadOnly(footerBorderBelowCB);
202         bc().addReadOnly(lastfooterStatusCB);
203         bc().addReadOnly(lastfooterBorderAboveCB);
204         bc().addReadOnly(lastfooterBorderBelowCB);
205         bc().addReadOnly(lastfooterNoContentsCB);
206         bc().addReadOnly(newpageCB);
207         bc().addReadOnly(leftRB);
208         bc().addReadOnly(centerRB);
209         bc().addReadOnly(rightRB);
210         
211         // initialize the length validator
212         bc().addCheckedLineEdit(widthED, fixedWidthColLA);
213         bc().addCheckedLineEdit(topspaceED, topspaceLA);
214         bc().addCheckedLineEdit(bottomspaceED, bottomspaceLA);
215         bc().addCheckedLineEdit(interlinespaceED, interlinespaceLA);
216 }
217
218
219 GuiTabular::~GuiTabular()
220 {
221 }
222
223
224 void GuiTabular::change_adaptor()
225 {
226         changed();
227 }
228
229
230 void GuiTabular::topspace_changed()
231 {
232         switch (topspaceCO->currentIndex()) {
233                 case 0: {
234                         topspaceED->setEnabled(false);
235                         topspaceUnit->setEnabled(false);
236                         break;
237                 }
238                 case 1: {
239                         topspaceED->setEnabled(false);
240                         topspaceUnit->setEnabled(false);
241                         break;
242                 }
243                 case 2: {
244                         if (!bc().policy().isReadOnly()) {
245                                 topspaceED->setEnabled(true);
246                                 topspaceUnit->setEnabled(true);
247                         }
248                         break;
249                 }
250         }
251         changed();
252 }
253
254
255 void GuiTabular::bottomspace_changed()
256 {
257         switch (bottomspaceCO->currentIndex()) {
258                 case 0: {
259                         bottomspaceED->setEnabled(false);
260                         bottomspaceUnit->setEnabled(false);
261                         break;
262                 }
263                 case 1: {
264                         bottomspaceED->setEnabled(false);
265                         bottomspaceUnit->setEnabled(false);
266                         break;
267                 }
268                 case 2: {
269                         if (!bc().policy().isReadOnly()) {
270                                 bottomspaceED->setEnabled(true);
271                                 bottomspaceUnit->setEnabled(true);
272                         }
273                         break;
274                 }
275         }
276         changed();
277 }
278
279
280 void GuiTabular::interlinespace_changed()
281 {
282         switch (interlinespaceCO->currentIndex()) {
283                 case 0: {
284                         interlinespaceED->setEnabled(false);
285                         interlinespaceUnit->setEnabled(false);
286                         break;
287                 }
288                 case 1: {
289                         interlinespaceED->setEnabled(false);
290                         interlinespaceUnit->setEnabled(false);
291                         break;
292                 }
293                 case 2: {
294                         if (!bc().policy().isReadOnly()) {
295                                 interlinespaceED->setEnabled(true);
296                                 interlinespaceUnit->setEnabled(true);
297                         }
298                         break;
299                 }
300         }
301         changed();
302 }
303
304
305 void GuiTabular::booktabsChanged(bool)
306 {
307         if (booktabsRB->isChecked()) {
308                 borders->setLeft(false);
309                 borders->setRight(false);
310                 borders->setLeftEnabled(false);
311                 borders->setRightEnabled(false);
312         } else {
313                 borders->setLeftEnabled(true);
314                 borders->setRightEnabled(true); 
315         }
316         // repaint the setborder widget
317         borders->update();
318         changed();
319 }
320
321
322 void GuiTabular::borderSet_clicked()
323 {
324         borders->setTop(true);
325         borders->setBottom(true);
326         borders->setLeft(true);
327         borders->setRight(true);
328         // repaint the setborder widget
329         borders->update();
330         changed();
331 }
332
333
334 void GuiTabular::borderUnset_clicked()
335 {
336         borders->setTop(false);
337         borders->setBottom(false);
338         borders->setLeft(false);
339         borders->setRight(false);
340         // repaint the setborder widget
341         borders->update();
342         changed();
343 }
344
345
346 void GuiTabular::update_borders()
347 {
348         Tabular::idx_type const cell = getActiveCell();
349         borders->setTop(tabular_.topLine(cell));
350         borders->setBottom(tabular_.bottomLine(cell));
351         borders->setLeft(tabular_.leftLine(cell));
352         borders->setRight(tabular_.rightLine(cell));
353         borders->setLeftEnabled(!booktabsRB->isChecked());
354         borders->setRightEnabled(!booktabsRB->isChecked());
355         // repaint the setborder widget
356         borders->update();
357 }
358
359
360 namespace {
361
362 Length getColumnPWidth(Tabular const & t, size_t cell)
363 {
364         return t.column_info[t.cellColumn(cell)].p_width;
365 }
366
367
368 Length getMColumnPWidth(Tabular const & t, size_t cell)
369 {
370         if (t.isMultiColumn(cell))
371                 return t.cellInfo(cell).p_width;
372         return Length();
373 }
374
375
376 docstring getAlignSpecial(Tabular const & t, size_t cell, int what)
377 {
378         if (what == Tabular::SET_SPECIAL_MULTI)
379                 return t.cellInfo(cell).align_special;
380         return t.column_info[t.cellColumn(cell)].align_special;
381 }
382
383 }
384
385
386 void GuiTabular::applyView()
387 {
388         applying_ = true;
389
390         Tabular::idx_type const cell = getActiveCell();
391         Tabular::row_type const row = tabular_.cellRow(cell);
392         bool const multicol = tabular_.isMultiColumn(cell);
393
394         Tabular::Feature num = Tabular::ALIGN_LEFT;
395         Tabular::Feature multi_num = Tabular::M_ALIGN_LEFT;
396
397         switch (hAlignCB->currentIndex()) {
398                 case 0:
399                         num = Tabular::ALIGN_LEFT;
400                         multi_num = Tabular::M_ALIGN_LEFT;
401                         break;
402                 case 1:
403                         num = Tabular::ALIGN_CENTER;
404                         multi_num = Tabular::M_ALIGN_CENTER;
405                         break;
406                 case 2:
407                         num = Tabular::ALIGN_RIGHT;
408                         multi_num = Tabular::M_ALIGN_RIGHT;
409                         break;
410                 case 3:
411                         num = Tabular::ALIGN_BLOCK;
412                         //multi_num: no equivalent
413                         break;
414         }
415         if (multicol)
416                 set(multi_num);
417         else
418                 set(num);
419
420         num = Tabular::VALIGN_MIDDLE;
421         multi_num = Tabular::M_VALIGN_MIDDLE;
422
423         switch (vAlignCB->currentIndex()) {
424                 case 0:
425                         num = Tabular::VALIGN_TOP;
426                         multi_num = Tabular::M_VALIGN_TOP;
427                         break;
428                 case 1:
429                         num = Tabular::VALIGN_MIDDLE;
430                         multi_num = Tabular::M_VALIGN_MIDDLE;
431                         break;
432                 case 2:
433                         num = Tabular::VALIGN_BOTTOM;
434                         multi_num = Tabular::M_VALIGN_BOTTOM;
435                         break;
436         }
437         if (multicol)
438                 set(multi_num);
439         else
440                 set(num);
441
442         switch (TableAlignCB->currentIndex()) {
443                 case 0:
444                         set(Tabular::TABULAR_VALIGN_TOP);
445                         break;
446                 case 1:
447                         set(Tabular::TABULAR_VALIGN_MIDDLE);
448                         break;
449                 case 2:
450                         set(Tabular::TABULAR_VALIGN_BOTTOM);
451                         break;
452         }
453
454         string value;
455
456         value = fromqstr(specialAlignmentED->text());
457         if (multicol)
458                 set(Tabular::SET_SPECIAL_MULTI, value);
459         else
460                 set(Tabular::SET_SPECIAL_COLUMN, value);
461
462         value = widgetsToLength(widthED, widthUnitCB);
463         if (multicol)
464                 set(Tabular::SET_MPWIDTH, value);
465         else
466                 set(Tabular::SET_PWIDTH, value);
467
468         if (multicolumnCB->isChecked() != multicol)
469                 set(Tabular::MULTICOLUMN);;
470
471         if (rotateTabularCB->isChecked())
472                 set(Tabular::SET_ROTATE_TABULAR);
473         else
474                 set(Tabular::UNSET_ROTATE_TABULAR);
475
476         if (rotateCellCB->isChecked())
477                 set(Tabular::SET_ROTATE_CELL);
478         else
479                 set(Tabular::UNSET_ROTATE_CELL);
480
481         // Borders
482         if (borders->getLeft() != tabular_.leftLine(cell))
483                 set(Tabular::TOGGLE_LINE_LEFT);
484         if (borders->getRight() != tabular_.rightLine(cell))
485                 set(Tabular::TOGGLE_LINE_RIGHT);
486         if (borders->getTop() != tabular_.topLine(cell))
487                 set(Tabular::TOGGLE_LINE_TOP);
488         if (borders->getBottom() != tabular_.bottomLine(cell))
489                 set(Tabular::TOGGLE_LINE_BOTTOM);
490
491         if (booktabsRB->isChecked())
492                 set(Tabular::SET_BOOKTABS);
493         else
494                 set(Tabular::UNSET_BOOKTABS);
495         
496         switch (topspaceCO->currentIndex()) {
497                 case 0:
498                         set(Tabular::SET_TOP_SPACE, "");
499                         break;
500                 case 1:
501                         set(Tabular::SET_TOP_SPACE, "default");
502                         break;
503                 case 2:
504                         set(Tabular::SET_TOP_SPACE,
505                                 widgetsToLength(topspaceED,
506                                                 topspaceUnit));
507                         break;
508         }
509         
510         switch (bottomspaceCO->currentIndex()) {
511                 case 0:
512                         set(Tabular::SET_BOTTOM_SPACE, "");
513                         break;
514                 case 1:
515                         set(Tabular::SET_BOTTOM_SPACE, "default");
516                         break;
517                 case 2:
518                         set(Tabular::SET_BOTTOM_SPACE,
519                                 widgetsToLength(bottomspaceED,
520                                                 bottomspaceUnit));
521                         break;
522         }
523
524         switch (interlinespaceCO->currentIndex()) {
525                 case 0:
526                         set(Tabular::SET_INTERLINE_SPACE, "");
527                         break;
528                 case 1:
529                         set(Tabular::SET_INTERLINE_SPACE, "default");
530                         break;
531                 case 2:
532                         set(Tabular::SET_INTERLINE_SPACE,
533                                 widgetsToLength(interlinespaceED,
534                                                 interlinespaceUnit));
535                         break;
536         }
537
538         // Longtabular
539         if (longTabularCB->isChecked())
540                 set(Tabular::SET_LONGTABULAR);
541         else
542                 set(Tabular::UNSET_LONGTABULAR);
543
544         if (headerStatusCB->isChecked())
545                 set(Tabular::SET_LTHEAD, "");
546         else
547                 set(Tabular::UNSET_LTHEAD, "");
548         
549         if (headerBorderAboveCB->isChecked())
550                 set(Tabular::SET_LTHEAD, "dl_above");
551         else
552                 set(Tabular::UNSET_LTHEAD, "dl_above");
553
554         if (headerBorderAboveCB->isChecked())
555                 set(Tabular::SET_LTHEAD, "dl_above");
556         else
557                 set(Tabular::UNSET_LTHEAD, "dl_above");
558
559         if (headerBorderBelowCB->isChecked())
560                 set(Tabular::SET_LTHEAD, "dl_below");
561         else
562                 set(Tabular::UNSET_LTHEAD, "dl_below");
563
564         if (firstheaderBorderAboveCB->isChecked())
565                 set(Tabular::SET_LTFIRSTHEAD, "dl_above");
566         else
567                 set(Tabular::UNSET_LTFIRSTHEAD, "dl_above");
568
569         if (firstheaderBorderBelowCB->isChecked())
570                 set(Tabular::SET_LTFIRSTHEAD, "dl_below");
571         else
572                 set(Tabular::UNSET_LTFIRSTHEAD, "dl_below");
573
574         if (firstheaderStatusCB->isChecked())
575                 set(Tabular::SET_LTFIRSTHEAD, "");
576         else
577                 set(Tabular::UNSET_LTFIRSTHEAD, "");
578
579         if (firstheaderNoContentsCB->isChecked())
580                 set(Tabular::SET_LTFIRSTHEAD, "empty");
581         else
582                 set(Tabular::UNSET_LTFIRSTHEAD, "empty");
583
584         if (footerStatusCB->isChecked())
585                 set(Tabular::SET_LTFOOT, "");
586         else
587                 set(Tabular::UNSET_LTFOOT, "");
588
589         if (footerBorderAboveCB->isChecked())
590                 set(Tabular::SET_LTFOOT, "dl_above");
591         else
592                 set(Tabular::UNSET_LTFOOT, "dl_above");
593
594         if (footerBorderBelowCB->isChecked())
595                 set(Tabular::SET_LTFOOT, "dl_below");
596         else
597                 set(Tabular::UNSET_LTFOOT, "dl_below");
598
599         if (lastfooterStatusCB->isChecked())
600                 set(Tabular::SET_LTLASTFOOT, "");
601         else
602                 set(Tabular::UNSET_LTLASTFOOT, "");
603
604         if (lastfooterBorderAboveCB->isChecked())
605                 set(Tabular::SET_LTLASTFOOT, "dl_above");
606         else
607                 set(Tabular::UNSET_LTLASTFOOT, "dl_above");
608
609         if (lastfooterBorderBelowCB->isChecked())
610                 set(Tabular::SET_LTLASTFOOT, "dl_below");
611         else
612                 set(Tabular::UNSET_LTLASTFOOT, "dl_below");
613
614         if (lastfooterNoContentsCB->isChecked())
615                 set(Tabular::SET_LTLASTFOOT, "empty");
616         else
617                 set(Tabular::UNSET_LTLASTFOOT, "empty");
618
619         if (newpageCB->isChecked() != tabular_.getLTNewPage(row))
620                 set(Tabular::SET_LTNEWPAGE);
621
622         if (captionStatusCB->isChecked() != tabular_.ltCaption(row))
623                 set(Tabular::TOGGLE_LTCAPTION);
624
625         if (leftRB->isChecked())
626                 set(Tabular::LONGTABULAR_ALIGN_LEFT);
627         else if (centerRB->isChecked())
628                 set(Tabular::LONGTABULAR_ALIGN_CENTER);
629         else if (rightRB->isChecked())
630                 set(Tabular::LONGTABULAR_ALIGN_RIGHT);
631
632         applying_ = false;
633 }
634
635
636 void GuiTabular::updateContents()
637 {
638         if (applying_)
639                 return;
640
641         initialiseParams(string());
642
643         Tabular::idx_type const cell = getActiveCell();
644
645         Tabular::row_type const row = tabular_.cellRow(cell);
646         Tabular::col_type const col = tabular_.cellColumn(cell);
647
648         tabularRowED->setText(QString::number(row + 1));
649         tabularColumnED->setText(QString::number(col + 1));
650
651         bool const multicol(tabular_.isMultiColumn(cell));
652
653         multicolumnCB->setChecked(multicol);
654
655         rotateCellCB->setChecked(tabular_.getRotateCell(cell));
656         rotateTabularCB->setChecked(tabular_.rotate);
657
658         longTabularCB->setChecked(tabular_.is_long_tabular);
659
660         update_borders();
661
662         Length pwidth;
663         docstring special;
664
665         if (multicol) {
666                 special = getAlignSpecial(tabular_, cell,
667                         Tabular::SET_SPECIAL_MULTI);
668                 pwidth = getMColumnPWidth(tabular_, cell);
669         } else {
670                 special = getAlignSpecial(tabular_, cell,
671                         Tabular::SET_SPECIAL_COLUMN);
672                 pwidth = getColumnPWidth(tabular_, cell);
673         }
674
675         specialAlignmentED->setText(toqstr(special));
676
677         bool const isReadonly = bc().policy().isReadOnly();
678         specialAlignmentED->setEnabled(!isReadonly);
679
680         Length::UNIT const default_unit = Length::defaultUnit();
681
682         borderDefaultRB->setChecked(!tabular_.use_booktabs);
683         booktabsRB->setChecked(tabular_.use_booktabs);
684
685         if (tabular_.row_info[row].top_space.empty()
686             && !tabular_.row_info[row].top_space_default) {
687                 topspaceCO->setCurrentIndex(0);
688         } else if (tabular_.row_info[row].top_space_default) {
689                 topspaceCO->setCurrentIndex(1);
690         } else {
691                 topspaceCO->setCurrentIndex(2);
692                 lengthToWidgets(topspaceED,
693                                 topspaceUnit,
694                                 tabular_.row_info[row].top_space.asString(),
695                                 default_unit);
696         }
697         topspaceED->setEnabled(!isReadonly
698                 && (topspaceCO->currentIndex() == 2));
699         topspaceUnit->setEnabled(!isReadonly
700                 && (topspaceCO->currentIndex() == 2));
701         topspaceCO->setEnabled(!isReadonly);
702
703         if (tabular_.row_info[row].bottom_space.empty()
704             && !tabular_.row_info[row].bottom_space_default) {
705                 bottomspaceCO->setCurrentIndex(0);
706         } else if (tabular_.row_info[row].bottom_space_default) {
707                 bottomspaceCO->setCurrentIndex(1);
708         } else {
709                 bottomspaceCO->setCurrentIndex(2);
710                 lengthToWidgets(bottomspaceED,
711                                 bottomspaceUnit,
712                                 tabular_.row_info[row].bottom_space.asString(),
713                                 default_unit);
714         }
715         bottomspaceED->setEnabled(!isReadonly
716                 && (bottomspaceCO->currentIndex() == 2));
717         bottomspaceUnit->setEnabled(!isReadonly
718                 && (bottomspaceCO->currentIndex() == 2));
719         bottomspaceCO->setEnabled(!isReadonly);
720
721         if (tabular_.row_info[row].interline_space.empty()
722             && !tabular_.row_info[row].interline_space_default) {
723                 interlinespaceCO->setCurrentIndex(0);
724         } else if (tabular_.row_info[row].interline_space_default) {
725                 interlinespaceCO->setCurrentIndex(1);
726         } else {
727                 interlinespaceCO->setCurrentIndex(2);
728                 lengthToWidgets(interlinespaceED,
729                                 interlinespaceUnit,
730                                 tabular_.row_info[row].interline_space.asString(),
731                                 default_unit);
732         }
733         interlinespaceED->setEnabled(!isReadonly
734                 && (interlinespaceCO->currentIndex() == 2));
735         interlinespaceUnit->setEnabled(!isReadonly
736                 && (interlinespaceCO->currentIndex() == 2));
737         interlinespaceCO->setEnabled(!isReadonly);
738
739         string colwidth;
740         if (!pwidth.zero()) {
741                 colwidth = pwidth.asString();
742
743                 lengthToWidgets(widthED, widthUnitCB,
744                         colwidth, default_unit);
745         }
746
747         widthED->setEnabled(!isReadonly);
748         widthUnitCB->setEnabled(!isReadonly);
749
750         hAlignCB->clear();
751         hAlignCB->addItem(qt_("Left"));
752         hAlignCB->addItem(qt_("Center"));
753         hAlignCB->addItem(qt_("Right"));
754         if (!multicol && !pwidth.zero())
755                 hAlignCB->addItem(qt_("Justified"));
756
757         int align = 0;
758         switch (tabular_.getAlignment(cell)) {
759         case LYX_ALIGN_LEFT:
760                 align = 0;
761                 break;
762         case LYX_ALIGN_CENTER:
763                 align = 1;
764                 break;
765         case LYX_ALIGN_RIGHT:
766                 align = 2;
767                 break;
768         case LYX_ALIGN_BLOCK:
769         {
770                 if (!multicol && !pwidth.zero())
771                         align = 3;
772                 break;
773         }
774         default:
775                 align = 0;
776                 break;
777         }
778         hAlignCB->setCurrentIndex(align);
779
780         int valign = 0;
781         switch (tabular_.getVAlignment(cell)) {
782         case Tabular::LYX_VALIGN_TOP:
783                 valign = 0;
784                 break;
785         case Tabular::LYX_VALIGN_MIDDLE:
786                 valign = 1;
787                 break;
788         case Tabular::LYX_VALIGN_BOTTOM:
789                 valign = 2;
790                 break;
791         default:
792                 valign = 0;
793                 break;
794         }
795         if (pwidth.zero())
796                 valign = 0;
797         vAlignCB->setCurrentIndex(valign);
798
799         hAlignCB->setEnabled(true);
800         vAlignCB->setEnabled(!pwidth.zero());
801
802         int tableValign = 1;
803         switch (tabular_.tabular_valignment) {
804         case Tabular::LYX_VALIGN_TOP:
805                 tableValign = 0;
806                 break;
807         case Tabular::LYX_VALIGN_MIDDLE:
808                 tableValign = 1;
809                 break;
810         case Tabular::LYX_VALIGN_BOTTOM:
811                 tableValign = 2;
812                 break;
813         default:
814                 tableValign = 0;
815                 break;
816         }
817         TableAlignCB->setCurrentIndex(tableValign);
818
819         if (!tabular_.is_long_tabular) {
820                 headerStatusCB->setChecked(false);
821                 headerBorderAboveCB->setChecked(false);
822                 headerBorderBelowCB->setChecked(false);
823                 firstheaderStatusCB->setChecked(false);
824                 firstheaderBorderAboveCB->setChecked(false);
825                 firstheaderBorderBelowCB->setChecked(false);
826                 firstheaderNoContentsCB->setChecked(false);
827                 footerStatusCB->setChecked(false);
828                 footerBorderAboveCB->setChecked(false);
829                 footerBorderBelowCB->setChecked(false);
830                 lastfooterStatusCB->setChecked(false);
831                 lastfooterBorderAboveCB->setChecked(false);
832                 lastfooterBorderBelowCB->setChecked(false);
833                 lastfooterNoContentsCB->setChecked(false);
834                 newpageCB->setChecked(false);
835                 newpageCB->setEnabled(false);
836                 captionStatusCB->blockSignals(true);
837                 captionStatusCB->setChecked(false);
838                 captionStatusCB->blockSignals(false);
839                 return;
840         } else
841                 // longtables cannot have a vertical alignment
842                 TableAlignCB->setCurrentIndex(Tabular::LYX_VALIGN_MIDDLE);
843
844         switch (tabular_.longtabular_alignment) {
845         case Tabular::LYX_LONGTABULAR_ALIGN_LEFT:
846                 leftRB->setChecked(true);
847                 break;
848         case Tabular::LYX_LONGTABULAR_ALIGN_CENTER:
849                 centerRB->setChecked(true);
850                 break;
851         case Tabular::LYX_LONGTABULAR_ALIGN_RIGHT:
852                 rightRB->setChecked(true);
853                 break;
854         default:
855                 centerRB->setChecked(true);
856                 break;
857         }
858         captionStatusCB->blockSignals(true);
859         captionStatusCB->setChecked(tabular_.ltCaption(row));
860         captionStatusCB->blockSignals(false);
861
862         // FIXME: shouldn't this be handled by GuiDialog?
863         // FIXME: Some of them should be handled directly in TabularUI.ui
864         firstheaderBorderAboveCB->setEnabled(
865                 funcEnabled(Tabular::SET_LTFIRSTHEAD));
866         firstheaderBorderBelowCB->setEnabled(
867                 funcEnabled(Tabular::SET_LTFIRSTHEAD));
868         // first header can only be suppressed when there is a header
869         firstheaderNoContentsCB->setEnabled(tabular_.haveLTHead()
870                 && !tabular_.haveLTFirstHead());
871
872         //firstheaderStatusCB->setEnabled(
873         //      !firstheaderNoContentsCB->isChecked());
874         headerBorderAboveCB->setEnabled(funcEnabled(Tabular::SET_LTHEAD));
875         headerBorderBelowCB->setEnabled(funcEnabled(Tabular::SET_LTHEAD));
876         headerStatusCB->setEnabled(funcEnabled(Tabular::SET_LTHEAD));
877
878         footerBorderAboveCB->setEnabled(funcEnabled(Tabular::SET_LTFOOT));
879         footerBorderBelowCB->setEnabled(funcEnabled(Tabular::SET_LTFOOT));
880         footerStatusCB->setEnabled(funcEnabled(Tabular::SET_LTFOOT));
881
882         lastfooterBorderAboveCB->setEnabled(
883                 funcEnabled(Tabular::SET_LTLASTFOOT));
884         lastfooterBorderBelowCB->setEnabled(
885                 funcEnabled(Tabular::SET_LTLASTFOOT));
886         // last footer can only be suppressed when there is a footer
887         lastfooterNoContentsCB->setEnabled(tabular_.haveLTFoot()
888                 && !tabular_.haveLTLastFoot());
889
890         captionStatusCB->setEnabled(
891                 funcEnabled(Tabular::TOGGLE_LTCAPTION));
892         // When a row is set as longtable caption, it must not be allowed
893         // to unset that this row is a multicolumn.
894         multicolumnCB->setEnabled(funcEnabled(Tabular::MULTICOLUMN));
895
896         Tabular::ltType ltt;
897         bool use_empty;
898         bool row_set = tabular_.getRowOfLTHead(row, ltt);
899         headerStatusCB->setChecked(row_set);
900         if (ltt.set) {
901                 headerBorderAboveCB->setChecked(ltt.topDL);
902                 headerBorderBelowCB->setChecked(ltt.bottomDL);
903                 use_empty = true;
904         } else {
905                 headerBorderAboveCB->setChecked(false);
906                 headerBorderBelowCB->setChecked(false);
907                 headerBorderAboveCB->setEnabled(false);
908                 headerBorderBelowCB->setEnabled(false);
909                 firstheaderNoContentsCB->setChecked(false);
910                 firstheaderNoContentsCB->setEnabled(false);
911                 use_empty = false;
912         }
913
914         row_set = tabular_.getRowOfLTFirstHead(row, ltt);
915         // check if setting a first header is allowed
916         // additionally check firstheaderNoContentsCB because when this is
917         // the case a first header makes no sense
918         firstheaderStatusCB->setEnabled(
919                 funcEnabled(Tabular::SET_LTFIRSTHEAD)
920                 && !firstheaderNoContentsCB->isChecked());
921         firstheaderStatusCB->setChecked(row_set);
922         if (ltt.set && (!ltt.empty || !use_empty)) {
923                 firstheaderBorderAboveCB->setChecked(ltt.topDL);
924                 firstheaderBorderBelowCB->setChecked(ltt.bottomDL);
925         } else {
926                 firstheaderBorderAboveCB->setEnabled(false);
927                 firstheaderBorderBelowCB->setEnabled(false);
928                 firstheaderBorderAboveCB->setChecked(false);
929                 firstheaderBorderBelowCB->setChecked(false);
930                 if (use_empty) {
931                         if (ltt.empty)
932                                 firstheaderStatusCB->setEnabled(false);
933                 }
934         }
935
936         row_set = tabular_.getRowOfLTFoot(row, ltt);
937         footerStatusCB->setChecked(row_set);
938         if (ltt.set) {
939                 footerBorderAboveCB->setChecked(ltt.topDL);
940                 footerBorderBelowCB->setChecked(ltt.bottomDL);
941                 use_empty = true;
942         } else {
943                 footerBorderAboveCB->setChecked(false);
944                 footerBorderBelowCB->setChecked(false);
945                 footerBorderAboveCB->setEnabled(false);
946                 footerBorderBelowCB->setEnabled(false);
947                 lastfooterNoContentsCB->setChecked(false);
948                 lastfooterNoContentsCB->setEnabled(false);
949                 use_empty = false;
950         }
951
952         row_set = tabular_.getRowOfLTLastFoot(row, ltt);
953         // check if setting a last footer is allowed
954         // additionally check lastfooterNoContentsCB because when this is
955         // the case a last footer makes no sense
956         lastfooterStatusCB->setEnabled(
957                 funcEnabled(Tabular::SET_LTLASTFOOT)
958                 && !lastfooterNoContentsCB->isChecked());
959         lastfooterStatusCB->setChecked(row_set);
960         if (ltt.set && (!ltt.empty || !use_empty)) {
961                 lastfooterBorderAboveCB->setChecked(ltt.topDL);
962                 lastfooterBorderBelowCB->setChecked(ltt.bottomDL);
963         } else {
964                 lastfooterBorderAboveCB->setEnabled(false);
965                 lastfooterBorderBelowCB->setEnabled(false);
966                 lastfooterBorderAboveCB->setChecked(false);
967                 lastfooterBorderBelowCB->setChecked(false);
968                 if (use_empty) {
969                         if (ltt.empty)
970                                 lastfooterStatusCB->setEnabled(false);
971                 }
972         }
973         newpageCB->setChecked(tabular_.getLTNewPage(row));
974 }
975
976
977 bool GuiTabular::initialiseParams(string const & data)
978 {
979         // try to get the current cell
980         BufferView const * const bv = bufferview();
981         InsetTabular const * current_inset = 0;
982         if (bv) {
983                 Cursor const & cur = bv->cursor();
984                 // get the innermost tabular inset;
985                 // assume that it is "ours"
986                 for (int i = cur.depth() - 1; i >= 0; --i)
987                         if (cur[i].inset().lyxCode() == TABULAR_CODE) {
988                                 current_inset =
989                                         static_cast<InsetTabular const *>(&cur[i].inset());
990                                 active_cell_ = cur[i].idx();
991                                 break;
992                         }
993         }
994
995         if (current_inset && data.empty()) {
996                 tabular_ = Tabular(current_inset->tabular);
997                 return true;
998         }
999
1000         InsetTabular tmp(const_cast<Buffer *>(&buffer()));
1001         InsetTabular::string2params(data, tmp);
1002         tabular_ = Tabular(tmp.tabular);
1003         return true;
1004 }
1005
1006
1007 void GuiTabular::clearParams()
1008 {
1009         // This function is also called when LyX is closing and the dialog
1010         // is still open. At that time, the buffer might not be available
1011         // anymore.
1012         if (isBufferAvailable()) {
1013                 InsetTabular tmp(const_cast<Buffer *>(&buffer()));
1014                 tabular_ = tmp.tabular;
1015         }
1016         active_cell_ = Tabular::npos;
1017 }
1018
1019
1020 Tabular::idx_type GuiTabular::getActiveCell() const
1021 {
1022         return active_cell_;
1023 }
1024
1025
1026 void GuiTabular::set(Tabular::Feature f, string const & arg)
1027 {
1028         string const data = featureAsString(f) + ' ' + arg;
1029         dispatch(FuncRequest(getLfun(), data));
1030 }
1031
1032
1033 // to get the status of the longtable row settings
1034 bool GuiTabular::funcEnabled(Tabular::Feature f) const
1035 {
1036         return getStatus(
1037                 FuncRequest(getLfun(), featureAsString(f))).enabled();
1038 }
1039
1040
1041 Dialog * createGuiTabular(GuiView & lv) { return new GuiTabular(lv); }
1042
1043
1044 } // namespace frontend
1045 } // namespace lyx
1046
1047 #include "moc_GuiTabular.cpp"