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