3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
7 * \author Jürgen Spitzmüller
11 * Full author contact details are available in file CREDITS.
16 #include "GuiTabular.h"
18 #include "GuiApplication.h"
19 #include "GuiSetBorder.h"
21 #include "LengthCombo.h"
22 #include "qt_helpers.h"
23 #include "Validator.h"
25 #include "BufferView.h"
27 #include "FuncRequest.h"
28 #include "FuncStatus.h"
32 #include "insets/InsetTabular.h"
34 #include "support/convert.h"
35 #include "support/debug.h"
36 #include "support/lstrings.h"
39 #include <QPushButton>
40 #include <QRadioButton>
48 GuiTabular::GuiTabular(QWidget * parent)
49 : InsetParamsWidget(parent), firstheader_suppressable_(false),
50 lastfooter_suppressable_(false), orig_leftborder_(GuiSetBorder::LINE_UNDEF),
51 orig_rightborder_(GuiSetBorder::LINE_UNDEF)
56 tabularWidthED->setValidator(unsignedLengthValidator(tabularWidthED));
57 columnWidthED->setValidator(unsignedLengthValidator(columnWidthED));
58 multirowOffsetED->setValidator(new LengthValidator(multirowOffsetED));
59 topspaceED->setValidator(new LengthValidator(topspaceED));
60 bottomspaceED->setValidator(new LengthValidator(bottomspaceED));
61 interlinespaceED->setValidator(new LengthValidator(interlinespaceED));
63 tabularWidthUnitLC->setCurrentItem(Length::defaultUnit());
64 columnWidthUnitLC->setCurrentItem(Length::defaultUnit());
65 multirowOffsetUnitLC->setCurrentItem(Length::defaultUnit());
66 topspaceUnitLC->setCurrentItem(Length::defaultUnit());
67 bottomspaceUnitLC->setCurrentItem(Length::defaultUnit());
68 interlinespaceUnitLC->setCurrentItem(Length::defaultUnit());
70 connect(topspaceED, SIGNAL(textEdited(const QString &)),
71 this, SLOT(checkEnabled()));
72 connect(topspaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
73 this, SLOT(checkEnabled()));
74 connect(bottomspaceED, SIGNAL(textEdited(const QString &)),
75 this, SLOT(checkEnabled()));
76 connect(bottomspaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
77 this, SLOT(checkEnabled()));
78 connect(interlinespaceED, SIGNAL(textEdited(const QString &)),
79 this, SLOT(checkEnabled()));
80 connect(interlinespaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
81 this, SLOT(checkEnabled()));
82 connect(booktabsRB, SIGNAL(clicked(bool)),
83 this, SLOT(booktabs_toggled(bool)));
84 connect(borderDefaultRB, SIGNAL(clicked(bool)),
85 this, SLOT(nonbooktabs_toggled(bool)));
86 connect(borderSetPB, SIGNAL(clicked()),
87 this, SLOT(borderSet_clicked()));
88 connect(borderUnsetPB, SIGNAL(clicked()),
89 this, SLOT(borderUnset_clicked()));
90 connect(hAlignCO, SIGNAL(activated(int)),
91 this, SLOT(checkEnabled()));
92 connect(vAlignCO, SIGNAL(activated(int)),
93 this, SLOT(checkEnabled()));
94 connect(multicolumnCB, SIGNAL(clicked()),
95 this, SLOT(checkEnabled()));
96 connect(multirowCB, SIGNAL(clicked()),
97 this, SLOT(checkEnabled()));
98 connect(multirowOffsetED, SIGNAL(textEdited(const QString &)),
99 this, SLOT(checkEnabled()));
100 connect(multirowOffsetUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
101 this, SLOT(checkEnabled()));
102 connect(newpageCB, SIGNAL(clicked()),
103 this, SLOT(checkEnabled()));
104 connect(headerStatusCB, SIGNAL(clicked()),
105 this, SLOT(checkEnabled()));
106 connect(headerBorderAboveCB, SIGNAL(clicked()),
107 this, SLOT(checkEnabled()));
108 connect(headerBorderBelowCB, SIGNAL(clicked()),
109 this, SLOT(checkEnabled()));
110 connect(firstheaderStatusCB, SIGNAL(clicked()),
111 this, SLOT(checkEnabled()));
112 connect(firstheaderBorderAboveCB, SIGNAL(clicked()),
113 this, SLOT(checkEnabled()));
114 connect(firstheaderBorderBelowCB, SIGNAL(clicked()),
115 this, SLOT(checkEnabled()));
116 connect(firstheaderNoContentsCB, SIGNAL(clicked()),
117 this, SLOT(checkEnabled()));
118 connect(footerStatusCB, SIGNAL(clicked()),
119 this, SLOT(checkEnabled()));
120 connect(footerBorderAboveCB, SIGNAL(clicked()),
121 this, SLOT(checkEnabled()));
122 connect(footerBorderBelowCB, SIGNAL(clicked()),
123 this, SLOT(checkEnabled()));
124 connect(lastfooterStatusCB, SIGNAL(clicked()),
125 this, SLOT(checkEnabled()));
126 connect(lastfooterBorderAboveCB, SIGNAL(clicked()),
127 this, SLOT(checkEnabled()));
128 connect(lastfooterBorderBelowCB, SIGNAL(clicked()),
129 this, SLOT(checkEnabled()));
130 connect(lastfooterNoContentsCB, SIGNAL(clicked()),
131 this, SLOT(checkEnabled()));
132 connect(captionStatusCB, SIGNAL(clicked()),
133 this, SLOT(checkEnabled()));
134 connect(specialAlignmentED, SIGNAL(textEdited(const QString &)),
135 this, SLOT(checkEnabled()));
136 connect(columnWidthED, SIGNAL(textEdited(const QString &)),
137 this, SLOT(checkEnabled()));
138 connect(columnWidthUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
139 this, SLOT(checkEnabled()));
140 connect(borders, SIGNAL(topSet()),
141 this, SLOT(checkEnabled()));
142 connect(borders, SIGNAL(bottomSet()),
143 this, SLOT(checkEnabled()));
144 connect(borders, SIGNAL(rightSet()),
145 this, SLOT(checkEnabled()));
146 connect(borders, SIGNAL(leftSet()),
147 this, SLOT(checkEnabled()));
148 connect(rotateTabularCB, SIGNAL(clicked()),
149 this, SLOT(checkEnabled()));
150 connect(rotateTabularAngleSB, SIGNAL(valueChanged(int)),
151 this, SLOT(checkEnabled()));
152 connect(rotateCellCB, SIGNAL(clicked()),
153 this, SLOT(checkEnabled()));
154 connect(rotateCellAngleSB, SIGNAL(valueChanged(int)),
155 this, SLOT(checkEnabled()));
156 connect(TableAlignCO, SIGNAL(activated(int)),
157 this, SLOT(checkEnabled()));
158 connect(longTabularCB, SIGNAL(clicked()),
159 this, SLOT(checkEnabled()));
160 connect(leftRB, SIGNAL(clicked()),
161 this, SLOT(checkEnabled()));
162 connect(centerRB, SIGNAL(clicked()),
163 this, SLOT(checkEnabled()));
164 connect(rightRB, SIGNAL(clicked()),
165 this, SLOT(checkEnabled()));
166 connect(tabularWidthED, SIGNAL(textEdited(const QString &)),
167 this, SLOT(checkEnabled()));
169 decimalPointED->setInputMask("X; ");
170 decimalPointED->setMaxLength(1);
172 // initialize the length validator
173 addCheckedWidget(columnWidthED, columnWidthLA);
174 addCheckedWidget(multirowOffsetED, multirowOffsetLA);
175 addCheckedWidget(topspaceED, topspaceLA);
176 addCheckedWidget(bottomspaceED, bottomspaceLA);
177 addCheckedWidget(interlinespaceED, interlinespaceLA);
178 addCheckedWidget(tabularWidthED, tabularWidthLA);
182 void GuiTabular::on_topspaceCO_activated(int index)
184 bool const enable = (index == 2);
185 topspaceED->setEnabled(enable);
186 topspaceUnitLC->setEnabled(enable);
190 void GuiTabular::on_bottomspaceCO_activated(int index)
192 bool const enable = (index == 2);
193 bottomspaceED->setEnabled(enable);
194 bottomspaceUnitLC->setEnabled(enable);
198 void GuiTabular::on_interlinespaceCO_activated(int index)
200 bool const enable = (index == 2);
201 interlinespaceED->setEnabled(enable);
202 interlinespaceUnitLC->setEnabled(enable);
206 void GuiTabular::enableWidgets() const
208 // if there is a LaTeX argument, the width and alignment will be overwritten
209 // therefore disable them in this case
210 columnWidthED->setEnabled(specialAlignmentED->text().isEmpty());
211 columnWidthUnitLC->setEnabled(specialAlignmentED->text().isEmpty());
212 // if the column has a width, multirows are always left-aligned
213 // therefore disable hAlignCB in this case
214 hAlignCO->setEnabled(!(multirowCB->isChecked()
215 && !widgetsToLength(columnWidthED, columnWidthUnitLC).empty())
216 && specialAlignmentED->text().isEmpty());
217 // decimal alignment is only possible for non-multicol and non-multirow cells
218 if ((multicolumnCB->isChecked() || multirowCB->isChecked())
219 && hAlignCO->findData(toqstr("decimal")))
220 hAlignCO->removeItem(hAlignCO->findData(toqstr("decimal")));
221 else if (!multicolumnCB->isChecked() && !multirowCB->isChecked()
222 && hAlignCO->findData(toqstr("decimal")) == -1)
223 hAlignCO->addItem(qt_("At Decimal Separator"), toqstr("decimal"));
225 hAlignCO->itemData(hAlignCO->currentIndex()).toString() == QString("decimal");
226 decimalPointED->setEnabled(dalign);
227 decimalLA->setEnabled(dalign);
229 bool const setwidth = TableAlignCO->currentText() == qt_("Middle")
230 && !longTabularCB->isChecked();
231 tabularWidthLA->setEnabled(setwidth);
232 tabularWidthED->setEnabled(setwidth);
233 tabularWidthUnitLC->setEnabled(setwidth);
235 rotateTabularAngleSB->setEnabled(rotateTabularCB->isChecked()
236 && !longTabularCB->isChecked());
237 rotateCellAngleSB->setEnabled(rotateCellCB->isChecked());
239 bool const enable_valign =
240 !multirowCB->isChecked()
241 && !widgetsToLength(columnWidthED, columnWidthUnitLC).empty()
242 && specialAlignmentED->text().isEmpty();
243 vAlignCO->setEnabled(enable_valign);
244 vAlignLA->setEnabled(enable_valign);
246 topspaceED->setEnabled(topspaceCO->currentIndex() == 2);
247 topspaceED->setEnabled(topspaceCO->currentIndex() == 2);
248 topspaceUnitLC->setEnabled(topspaceCO->currentIndex() == 2);
249 bottomspaceED->setEnabled(bottomspaceCO->currentIndex() == 2);
250 bottomspaceUnitLC->setEnabled(bottomspaceCO->currentIndex() == 2);
251 interlinespaceED->setEnabled(interlinespaceCO->currentIndex() == 2);
252 interlinespaceUnitLC->setEnabled(interlinespaceCO->currentIndex() == 2);
254 // setting as longtable is not allowed when table is inside a float
255 bool const is_tabular_star = !tabularWidthED->text().isEmpty();
256 longTabularCB->setEnabled(!is_tabular_star && funcEnabled(Tabular::SET_LONGTABULAR));
257 bool const longtabular = longTabularCB->isChecked();
258 longtableGB->setEnabled(true);
259 newpageCB->setEnabled(longtabular);
260 alignmentGB->setEnabled(longtabular);
261 // longtables and tabular* cannot have a vertical alignment
262 TableAlignLA->setDisabled(is_tabular_star || longtabular);
263 TableAlignCO->setDisabled(is_tabular_star || longtabular);
264 // longtable cannot be rotated with rotating package, only
265 // with [pdf]lscape, which only supports 90 deg.
266 rotateTabularAngleSB->setDisabled(longtabular);
268 // FIXME: This Dialog is really horrible, disabling/enabling a checkbox
269 // depending on the cursor position is very very unintuitive...
270 // We need some edit boxes to show which rows are header/footer/etc
271 // without having to move the cursor first.
272 headerStatusCB->setEnabled(longtabular
273 && (headerStatusCB->isChecked() ?
274 funcEnabled(Tabular::UNSET_LTHEAD) :
275 funcEnabled(Tabular::SET_LTHEAD)));
276 headerBorderAboveCB->setEnabled(longtabular
277 && headerStatusCB->isChecked());
278 headerBorderBelowCB->setEnabled(longtabular
279 && headerStatusCB->isChecked());
281 // first header can only be suppressed when there is a header
282 // firstheader_suppressable_ is set in paramsToDialog
283 firstheaderNoContentsCB->setEnabled(longtabular && firstheader_suppressable_);
284 // check if setting a first header is allowed
285 // additionally check firstheaderNoContentsCB because when this is
286 // the case a first header makes no sense
287 firstheaderStatusCB->setEnabled((firstheaderStatusCB->isChecked() ?
288 funcEnabled(Tabular::UNSET_LTFIRSTHEAD) :
289 funcEnabled(Tabular::SET_LTFIRSTHEAD))
290 && longtabular && !firstheaderNoContentsCB->isChecked());
291 firstheaderBorderAboveCB->setEnabled(longtabular
292 && firstheaderStatusCB->isChecked());
293 firstheaderBorderBelowCB->setEnabled(longtabular
294 && firstheaderStatusCB->isChecked());
296 footerStatusCB->setEnabled(longtabular
297 && (footerStatusCB->isChecked() ?
298 funcEnabled(Tabular::UNSET_LTFOOT) :
299 funcEnabled(Tabular::SET_LTFOOT)));
300 footerBorderAboveCB->setEnabled(longtabular
301 && footerBorderAboveCB->isChecked());
302 footerBorderBelowCB->setEnabled(longtabular
303 && footerBorderAboveCB->isChecked());
305 // last footer can only be suppressed when there is a footer
306 // lastfooter_suppressable_ is set in paramsToDialog
307 lastfooterNoContentsCB->setEnabled(longtabular && lastfooter_suppressable_);
308 // check if setting a last footer is allowed
309 // additionally check lastfooterNoContentsCB because when this is
310 // the case a last footer makes no sense
311 lastfooterStatusCB->setEnabled((lastfooterStatusCB->isChecked() ?
312 funcEnabled(Tabular::UNSET_LTLASTFOOT) :
313 funcEnabled(Tabular::SET_LTLASTFOOT))
314 && longtabular && !lastfooterNoContentsCB->isChecked());
315 lastfooterBorderAboveCB->setEnabled(longtabular
316 && lastfooterBorderAboveCB->isChecked());
317 lastfooterBorderBelowCB->setEnabled(longtabular
318 && lastfooterBorderAboveCB->isChecked());
320 captionStatusCB->setEnabled(funcEnabled(Tabular::TOGGLE_LTCAPTION)
323 multicolumnCB->setEnabled(funcEnabled(Tabular::MULTICOLUMN)
324 && !dalign && !multirowCB->isChecked());
325 multirowCB->setEnabled(funcEnabled(Tabular::MULTIROW)
326 && !dalign && !multicolumnCB->isChecked());
327 bool const enable_mr = multirowCB->isChecked();
328 multirowOffsetLA->setEnabled(enable_mr);
329 multirowOffsetED->setEnabled(enable_mr);
330 multirowOffsetUnitLC->setEnabled(enable_mr);
332 // Vertical lines cannot be set in formal tables
333 borders->setLeftEnabled(!booktabsRB->isChecked());
334 borders->setRightEnabled(!booktabsRB->isChecked());
338 void GuiTabular::checkEnabled()
345 void GuiTabular::borderSet_clicked()
347 borders->setTop(GuiSetBorder::LINE_SET);
348 borders->setBottom(GuiSetBorder::LINE_SET);
349 borders->setLeft(GuiSetBorder::LINE_SET);
350 borders->setRight(GuiSetBorder::LINE_SET);
351 // repaint the setborder widget
357 void GuiTabular::borderUnset_clicked()
359 borders->setTop(GuiSetBorder::LINE_UNSET);
360 borders->setBottom(GuiSetBorder::LINE_UNSET);
361 borders->setLeft(GuiSetBorder::LINE_UNSET);
362 borders->setRight(GuiSetBorder::LINE_UNSET);
363 // repaint the setborder widget
369 void GuiTabular::booktabs_toggled(bool const check)
371 // when switching from formal, restore the left/right lines
373 borders->setLeft(orig_leftborder_);
374 borders->setRight(orig_rightborder_);
376 // repaint the setborder widget
382 void GuiTabular::nonbooktabs_toggled(bool const check)
384 booktabs_toggled(!check);
388 static void setParam(string & param_str, Tabular::Feature f, string const & arg = string())
391 param_str += featureAsString(f) + ' ' + arg;
395 void GuiTabular::setHAlign(string & param_str) const
397 Tabular::Feature num = Tabular::ALIGN_LEFT;
398 Tabular::Feature multi_num = Tabular::M_ALIGN_LEFT;
400 fromqstr(hAlignCO->itemData(hAlignCO->currentIndex()).toString());
401 if (align == "left") {
402 num = Tabular::ALIGN_LEFT;
403 multi_num = Tabular::M_ALIGN_LEFT;
404 } else if (align == "center") {
405 num = Tabular::ALIGN_CENTER;
406 multi_num = Tabular::M_ALIGN_CENTER;
407 } else if (align == "right") {
408 num = Tabular::ALIGN_RIGHT;
409 multi_num = Tabular::M_ALIGN_RIGHT;
410 } else if (align == "justified") {
411 num = Tabular::ALIGN_BLOCK;
412 //multi_num: no equivalent
413 } else if (align == "decimal") {
414 num = Tabular::ALIGN_DECIMAL;
415 //multi_num: no equivalent
418 if (multicolumnCB->isChecked())
419 setParam(param_str, multi_num);
421 setParam(param_str, num);
425 void GuiTabular::setVAlign(string & param_str) const
427 int const align = vAlignCO->currentIndex();
428 enum VALIGN { TOP, MIDDLE, BOTTOM };
432 case 0: v = TOP; break;
433 case 1: v = MIDDLE; break;
434 case 2: v = BOTTOM; break;
437 Tabular::Feature num = Tabular::VALIGN_MIDDLE;
438 Tabular::Feature multi_num = Tabular::M_VALIGN_MIDDLE;
442 num = Tabular::VALIGN_TOP;
443 multi_num = Tabular::M_VALIGN_TOP;
446 num = Tabular::VALIGN_MIDDLE;
447 multi_num = Tabular::M_VALIGN_MIDDLE;
450 num = Tabular::VALIGN_BOTTOM;
451 multi_num = Tabular::M_VALIGN_BOTTOM;
454 if (multicolumnCB->isChecked() || multirowCB->isChecked())
455 setParam(param_str, multi_num);
457 setParam(param_str, num);
461 void GuiTabular::setTableAlignment(string & param_str) const
463 int const align = TableAlignCO->currentIndex();
465 case 0: setParam(param_str, Tabular::TABULAR_VALIGN_TOP);
467 case 1: setParam(param_str, Tabular::TABULAR_VALIGN_MIDDLE);
469 case 2: setParam(param_str, Tabular::TABULAR_VALIGN_BOTTOM);
475 docstring GuiTabular::dialogToParams() const
477 string param_str = "tabular";
480 string tabwidth = widgetsToLength(tabularWidthED, tabularWidthUnitLC);
481 if (tabwidth.empty())
483 setParam(param_str, Tabular::SET_TABULAR_WIDTH, tabwidth);
485 // apply the fixed width values
486 // this must be done before applying the column alignment
487 // because its value influences the alignment of multirow cells
488 string width = widgetsToLength(columnWidthED, columnWidthUnitLC);
491 if (multicolumnCB->isChecked())
492 setParam(param_str, Tabular::SET_MPWIDTH, width);
494 setParam(param_str, Tabular::SET_PWIDTH, width);
496 // apply the column alignment
497 // multirows inherit the alignment from the column; if a column width
498 // is set, multirows are always left-aligned so that in this case
499 // its alignment must not be applied (see bug #8084)
500 if (!(multirowCB->isChecked() && width != "0pt"))
501 setHAlign(param_str);
503 // SET_DECIMAL_POINT must come after setHAlign() (ALIGN_DECIMAL)
504 string decimal_point = fromqstr(decimalPointED->text());
505 if (decimal_point.empty())
506 decimal_point = lyxrc.default_decimal_point;
507 setParam(param_str, Tabular::SET_DECIMAL_POINT, decimal_point);
509 setVAlign(param_str);
510 setTableAlignment(param_str);
512 if (booktabsRB->isChecked())
513 setParam(param_str, Tabular::SET_BOOKTABS);
515 setParam(param_str, Tabular::UNSET_BOOKTABS);
518 switch (topspaceCO->currentIndex()) {
520 setParam(param_str, Tabular::SET_TOP_SPACE, "none");
523 setParam(param_str, Tabular::SET_TOP_SPACE, "default");
526 if (!topspaceED->text().isEmpty())
527 setParam(param_str, Tabular::SET_TOP_SPACE,
528 widgetsToLength(topspaceED, topspaceUnitLC));
533 switch (bottomspaceCO->currentIndex()) {
535 setParam(param_str, Tabular::SET_BOTTOM_SPACE, "none");
538 setParam(param_str, Tabular::SET_BOTTOM_SPACE, "default");
541 if (!bottomspaceED->text().isEmpty())
542 setParam(param_str, Tabular::SET_BOTTOM_SPACE,
543 widgetsToLength(bottomspaceED,
549 switch (interlinespaceCO->currentIndex()) {
551 setParam(param_str, Tabular::SET_INTERLINE_SPACE, "none");
554 setParam(param_str, Tabular::SET_INTERLINE_SPACE, "default");
557 if (!interlinespaceED->text().isEmpty())
558 setParam(param_str, Tabular::SET_INTERLINE_SPACE,
559 widgetsToLength(interlinespaceED,
560 interlinespaceUnitLC));
565 if (borders->topLineSet() && borders->bottomLineSet() && borders->leftLineSet()
566 && borders->rightLineSet())
567 setParam(param_str, Tabular::SET_ALL_LINES);
568 else if (borders->topLineUnset() && borders->bottomLineUnset() && borders->leftLineUnset()
569 && borders->rightLineUnset())
570 setParam(param_str, Tabular::UNSET_ALL_LINES);
572 if (borders->getLeft() != GuiSetBorder::LINE_UNDECIDED)
573 setParam(param_str, Tabular::SET_LINE_LEFT,
574 borders->leftLineSet() ? "true" : "false");
575 if (borders->getRight() != GuiSetBorder::LINE_UNDECIDED)
576 setParam(param_str, Tabular::SET_LINE_RIGHT,
577 borders->rightLineSet() ? "true" : "false");
578 if (borders->getTop() != GuiSetBorder::LINE_UNDECIDED)
579 setParam(param_str, Tabular::SET_LINE_TOP,
580 borders->topLineSet() ? "true" : "false");
581 if (borders->getBottom() != GuiSetBorder::LINE_UNDECIDED)
582 setParam(param_str, Tabular::SET_LINE_BOTTOM,
583 borders->bottomLineSet() ? "true" : "false");
586 // apply the special alignment
587 string special = fromqstr(specialAlignmentED->text());
588 if (support::trim(special).empty())
590 if (multicolumnCB->isChecked())
591 setParam(param_str, Tabular::SET_SPECIAL_MULTICOLUMN, special);
593 setParam(param_str, Tabular::SET_SPECIAL_COLUMN, special);
596 if (multicolumnCB->isChecked())
597 setParam(param_str, Tabular::SET_MULTICOLUMN);
599 setParam(param_str, Tabular::UNSET_MULTICOLUMN);
601 // apply the multirow offset
602 string mroffset = widgetsToLength(multirowOffsetED, multirowOffsetUnitLC);
603 if (mroffset.empty())
605 if (multirowCB->isChecked())
606 setParam(param_str, Tabular::SET_MROFFSET, mroffset);
608 if (multirowCB->isChecked())
609 setParam(param_str, Tabular::SET_MULTIROW);
611 setParam(param_str, Tabular::UNSET_MULTIROW);
612 // store the table rotation angle
613 string const tabular_angle = convert<string>(rotateTabularAngleSB->value());
614 if (rotateTabularCB->isChecked())
615 setParam(param_str, Tabular::SET_ROTATE_TABULAR, tabular_angle);
617 setParam(param_str, Tabular::UNSET_ROTATE_TABULAR, tabular_angle);
618 // store the cell rotation angle
619 string const cell_angle = convert<string>(rotateCellAngleSB->value());
620 if (rotateCellCB->isChecked())
621 setParam(param_str, Tabular::SET_ROTATE_CELL, cell_angle);
623 setParam(param_str, Tabular::UNSET_ROTATE_CELL, cell_angle);
625 if (longTabularCB->isChecked())
626 setParam(param_str, Tabular::SET_LONGTABULAR);
628 setParam(param_str, Tabular::UNSET_LONGTABULAR);
630 if (newpageCB->isChecked())
631 setParam(param_str, Tabular::SET_LTNEWPAGE);
633 setParam(param_str, Tabular::UNSET_LTNEWPAGE);
635 if (captionStatusCB->isChecked())
636 setParam(param_str, Tabular::SET_LTCAPTION);
638 setParam(param_str, Tabular::UNSET_LTCAPTION);
640 if (headerStatusCB->isChecked())
641 setParam(param_str, Tabular::SET_LTHEAD, "none");
643 setParam(param_str, Tabular::UNSET_LTHEAD, "none");
645 if (headerBorderAboveCB->isChecked())
646 setParam(param_str, Tabular::SET_LTHEAD, "dl_above");
648 setParam(param_str, Tabular::UNSET_LTHEAD, "dl_above");
650 if (headerBorderBelowCB->isChecked())
651 setParam(param_str, Tabular::SET_LTHEAD, "dl_below");
653 setParam(param_str, Tabular::UNSET_LTHEAD, "dl_below");
654 if (firstheaderBorderAboveCB->isChecked())
655 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "dl_above");
657 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "dl_above");
658 if (firstheaderBorderBelowCB->isChecked())
659 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "dl_below");
661 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "dl_below");
662 if (firstheaderStatusCB->isChecked())
663 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "none");
665 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "none");
666 if (firstheaderNoContentsCB->isChecked())
667 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "empty");
669 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "empty");
670 if (footerStatusCB->isChecked())
671 setParam(param_str, Tabular::SET_LTFOOT, "none");
673 setParam(param_str, Tabular::UNSET_LTFOOT, "none");
674 if (footerBorderAboveCB->isChecked())
675 setParam(param_str, Tabular::SET_LTFOOT, "dl_above");
677 setParam(param_str, Tabular::UNSET_LTFOOT, "dl_above");
678 if (footerBorderBelowCB->isChecked())
679 setParam(param_str, Tabular::SET_LTFOOT, "dl_below");
681 setParam(param_str, Tabular::UNSET_LTFOOT, "dl_below");
682 if (lastfooterStatusCB->isChecked())
683 setParam(param_str, Tabular::SET_LTLASTFOOT, "none");
685 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "none");
686 if (lastfooterBorderAboveCB->isChecked())
687 setParam(param_str, Tabular::SET_LTLASTFOOT, "dl_above");
689 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "dl_above");
690 if (lastfooterBorderBelowCB->isChecked())
691 setParam(param_str, Tabular::SET_LTLASTFOOT, "dl_below");
693 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "dl_below");
694 if (lastfooterNoContentsCB->isChecked())
695 setParam(param_str, Tabular::SET_LTLASTFOOT, "empty");
697 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "empty");
699 if (leftRB->isChecked())
700 setParam(param_str, Tabular::LONGTABULAR_ALIGN_LEFT);
701 else if (centerRB->isChecked())
702 setParam(param_str, Tabular::LONGTABULAR_ALIGN_CENTER);
703 else if (rightRB->isChecked())
704 setParam(param_str, Tabular::LONGTABULAR_ALIGN_RIGHT);
706 return from_utf8(param_str);
710 static Length getColumnPWidth(Tabular const & t, size_t cell)
712 return t.column_info[t.cellColumn(cell)].p_width;
716 static Length getMColumnPWidth(Tabular const & t, size_t cell)
718 if (t.isMultiColumn(cell) || t.isMultiRow(cell))
719 return t.cellInfo(cell).p_width;
724 static Length getMROffset(Tabular const & t, size_t cell)
726 if (t.isMultiRow(cell))
727 return t.cellInfo(cell).mroffset;
732 static docstring getAlignSpecial(Tabular const & t, size_t cell, int what)
734 if (what == Tabular::SET_SPECIAL_MULTICOLUMN)
735 return t.cellInfo(cell).align_special;
736 return t.column_info[t.cellColumn(cell)].align_special;
740 GuiSetBorder::BorderState GuiTabular::borderState(GuiSetBorder::BorderState bs,
743 if (bs == GuiSetBorder::LINE_UNDEF)
744 bs = line ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
745 else if ((bs == GuiSetBorder::LINE_SET && !line)
746 || (bs == GuiSetBorder::LINE_UNSET && line))
747 bs = GuiSetBorder::LINE_UNDECIDED;
752 void GuiTabular::paramsToDialog(Inset const * inset)
754 InsetTabular const * itab = static_cast<InsetTabular const *>(inset);
755 // Copy Tabular of current inset.
756 Tabular const & tabular = itab->tabular;
758 BufferView const * bv = guiApp->currentView()->currentBufferView();
759 size_t const cell = bv->cursor().idx();
761 Tabular::row_type const row = tabular.cellRow(cell);
762 Tabular::col_type const col = tabular.cellColumn(cell);
764 tabularRowED->setText(QString::number(row + 1));
765 tabularColumnED->setText(QString::number(col + 1));
767 bool const multicol = tabular.isMultiColumn(cell);
768 multicolumnCB->setChecked(multicol);
770 bool const multirow = tabular.isMultiRow(cell);
771 multirowCB->setChecked(multirow);
773 rotateCellCB->setChecked(tabular.getRotateCell(cell) != 0);
774 if (rotateCellCB->isChecked()) {
775 if (tabular.getRotateCell(cell) != 0)
776 rotateCellAngleSB->setValue(tabular.getRotateCell(cell));
778 rotateCellAngleSB->setValue(90);
781 longTabularCB->setChecked(tabular.is_long_tabular);
783 rotateTabularCB->setChecked(tabular.rotate != 0);
784 if (rotateTabularCB->isChecked()) {
785 if (longTabularCB->isChecked())
786 rotateTabularAngleSB->setValue(90);
788 rotateTabularAngleSB->setValue(tabular.rotate != 0 ? tabular.rotate : 90);
791 // In what follows, we check the borders of all selected cells,
792 // and if there are diverging settings, we use the LINE_UNDEF
794 GuiSetBorder::BorderState lt = GuiSetBorder::LINE_UNDEF;
795 GuiSetBorder::BorderState lb = GuiSetBorder::LINE_UNDEF;
796 GuiSetBorder::BorderState ll = GuiSetBorder::LINE_UNDEF;
797 GuiSetBorder::BorderState lr = GuiSetBorder::LINE_UNDEF;
798 CursorSlice const & beg = bv->cursor().selBegin();
799 CursorSlice const & end = bv->cursor().selEnd();
801 Tabular::col_type cs = tabular.cellColumn(beg.idx());
802 Tabular::col_type ce = tabular.cellColumn(end.idx());
805 Tabular::row_type rs = tabular.cellRow(beg.idx());
806 Tabular::row_type re = tabular.cellRow(end.idx());
809 for (Tabular::row_type r = rs; r <= re; ++r)
810 for (Tabular::col_type c = cs; c <= ce; ++c) {
811 idx_type const cc = tabular.cellIndex(r, c);
812 lt = borderState(lt, tabular.topLine(cc));
813 lb = borderState(lb, tabular.bottomLine(cc));
814 ll = borderState(ll, tabular.leftLine(cc));
815 lr = borderState(lr, tabular.rightLine(cc));
816 // store left/right borders for the case of formal/nonformal switch
817 orig_leftborder_ = borderState(ll, tabular.leftLine(cc, true));
818 orig_rightborder_ = borderState(lr, tabular.rightLine(cc, true));
821 lt = tabular.topLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
822 lb = tabular.bottomLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
823 ll = tabular.leftLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
824 lr = tabular.rightLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
825 // store left/right borders for the case of formal/nonformal switch
826 orig_leftborder_ = tabular.leftLine(cell, true) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
827 orig_rightborder_ = tabular.rightLine(cell, true) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
830 borders->setBottom(lb);
831 borders->setLeft(ll);
832 borders->setRight(lr);
833 // repaint the setborder widget
836 Length::UNIT const default_unit = Length::defaultUnit();
838 ///////////////////////////////////
839 // Set width and alignment
841 Length const tabwidth = tabular.tabularWidth();
843 && !(tabularWidthED->hasFocus() && tabularWidthED->text() == "0"))
844 tabularWidthED->clear();
846 lengthToWidgets(tabularWidthED, tabularWidthUnitLC,
847 tabwidth.asString(), default_unit);
852 special = getAlignSpecial(tabular, cell,
853 Tabular::SET_SPECIAL_MULTICOLUMN);
854 pwidth = getMColumnPWidth(tabular, cell);
856 special = getAlignSpecial(tabular, cell,
857 Tabular::SET_SPECIAL_COLUMN);
858 pwidth = getColumnPWidth(tabular, cell);
862 && !(columnWidthED->hasFocus() && columnWidthED->text() == "0"))
863 columnWidthED->clear();
865 colwidth = pwidth.asString();
866 lengthToWidgets(columnWidthED, columnWidthUnitLC,
867 colwidth, default_unit);
871 mroffset = getMROffset(tabular, cell);
874 && !(multirowOffsetED->hasFocus() && multirowOffsetED->text() == "0"))
875 multirowOffsetED->clear();
877 offset = mroffset.asString();
878 lengthToWidgets(multirowOffsetED, multirowOffsetUnitLC,
879 offset, default_unit);
881 specialAlignmentED->setText(toqstr(special));
882 ///////////////////////////////////
885 borderDefaultRB->setChecked(!tabular.use_booktabs);
886 booktabsRB->setChecked(tabular.use_booktabs);
888 if (tabular.row_info[row].top_space.empty()
889 && !tabular.row_info[row].top_space_default) {
890 topspaceCO->setCurrentIndex(0);
891 } else if (tabular.row_info[row].top_space_default) {
892 topspaceCO->setCurrentIndex(1);
894 topspaceCO->setCurrentIndex(2);
895 lengthToWidgets(topspaceED,
897 tabular.row_info[row].top_space.asString(),
901 if (tabular.row_info[row].bottom_space.empty()
902 && !tabular.row_info[row].bottom_space_default) {
903 bottomspaceCO->setCurrentIndex(0);
904 } else if (tabular.row_info[row].bottom_space_default) {
905 bottomspaceCO->setCurrentIndex(1);
907 bottomspaceCO->setCurrentIndex(2);
908 lengthToWidgets(bottomspaceED,
910 tabular.row_info[row].bottom_space.asString(),
914 if (tabular.row_info[row].interline_space.empty()
915 && !tabular.row_info[row].interline_space_default) {
916 interlinespaceCO->setCurrentIndex(0);
917 } else if (tabular.row_info[row].interline_space_default) {
918 interlinespaceCO->setCurrentIndex(1);
920 interlinespaceCO->setCurrentIndex(2);
921 lengthToWidgets(interlinespaceED,
922 interlinespaceUnitLC,
923 tabular.row_info[row].interline_space.asString(),
928 hAlignCO->addItem(qt_("Left"), toqstr("left"));
929 hAlignCO->addItem(qt_("Center"), toqstr("center"));
930 hAlignCO->addItem(qt_("Right"), toqstr("right"));
931 if (!multicol && !pwidth.zero())
932 hAlignCO->addItem(qt_("Justified"), toqstr("justified"));
933 if (!multicol && !multirow)
934 hAlignCO->addItem(qt_("At Decimal Separator"), toqstr("decimal"));
937 switch (tabular.getAlignment(cell)) {
941 case LYX_ALIGN_CENTER:
944 case LYX_ALIGN_RIGHT:
947 case LYX_ALIGN_BLOCK:
949 if (!multicol && !pwidth.zero())
953 case LYX_ALIGN_DECIMAL:
955 if (!multicol && !multirow)
960 // we should never end up here
963 hAlignCO->setCurrentIndex(hAlignCO->findData(toqstr(align)));
966 QString decimal_point = toqstr(tabular.column_info[col].decimal_point);
967 if (decimal_point.isEmpty())
968 decimal_point = toqstr(from_utf8(lyxrc.default_decimal_point));
969 decimalPointED->setText(decimal_point);
972 switch (tabular.getVAlignment(cell)) {
973 case Tabular::LYX_VALIGN_TOP:
976 case Tabular::LYX_VALIGN_MIDDLE:
979 case Tabular::LYX_VALIGN_BOTTOM:
988 vAlignCO->setCurrentIndex(valign);
991 switch (tabular.tabular_valignment) {
992 case Tabular::LYX_VALIGN_TOP:
995 case Tabular::LYX_VALIGN_MIDDLE:
998 case Tabular::LYX_VALIGN_BOTTOM:
1005 TableAlignCO->setCurrentIndex(tableValign);
1007 if (!tabular.is_long_tabular) {
1008 headerStatusCB->setChecked(false);
1009 headerBorderAboveCB->setChecked(false);
1010 headerBorderBelowCB->setChecked(false);
1011 firstheaderStatusCB->setChecked(false);
1012 firstheaderBorderAboveCB->setChecked(false);
1013 firstheaderBorderBelowCB->setChecked(false);
1014 firstheaderNoContentsCB->setChecked(false);
1015 footerStatusCB->setChecked(false);
1016 footerBorderAboveCB->setChecked(false);
1017 footerBorderBelowCB->setChecked(false);
1018 lastfooterStatusCB->setChecked(false);
1019 lastfooterBorderAboveCB->setChecked(false);
1020 lastfooterBorderBelowCB->setChecked(false);
1021 lastfooterNoContentsCB->setChecked(false);
1022 newpageCB->setChecked(false);
1023 captionStatusCB->blockSignals(true);
1024 captionStatusCB->setChecked(false);
1025 captionStatusCB->blockSignals(false);
1029 // longtables cannot have a vertical alignment
1030 TableAlignCO->setCurrentIndex(Tabular::LYX_VALIGN_MIDDLE);
1032 switch (tabular.longtabular_alignment) {
1033 case Tabular::LYX_LONGTABULAR_ALIGN_LEFT:
1034 leftRB->setChecked(true);
1036 case Tabular::LYX_LONGTABULAR_ALIGN_CENTER:
1037 centerRB->setChecked(true);
1039 case Tabular::LYX_LONGTABULAR_ALIGN_RIGHT:
1040 rightRB->setChecked(true);
1043 centerRB->setChecked(true);
1046 captionStatusCB->blockSignals(true);
1047 captionStatusCB->setChecked(tabular.ltCaption(row));
1048 captionStatusCB->blockSignals(false);
1050 Tabular::ltType ltt;
1052 bool row_set = tabular.getRowOfLTHead(row, ltt);
1053 headerStatusCB->setChecked(row_set);
1055 headerBorderAboveCB->setChecked(ltt.topDL);
1056 headerBorderBelowCB->setChecked(ltt.bottomDL);
1059 headerBorderAboveCB->setChecked(false);
1060 headerBorderBelowCB->setChecked(false);
1061 firstheaderNoContentsCB->setChecked(false);
1065 row_set = tabular.getRowOfLTFirstHead(row, ltt);
1066 firstheaderStatusCB->setChecked(row_set);
1067 if (ltt.set && (!ltt.empty || !use_empty)) {
1068 firstheaderBorderAboveCB->setChecked(ltt.topDL);
1069 firstheaderBorderBelowCB->setChecked(ltt.bottomDL);
1071 firstheaderBorderAboveCB->setChecked(false);
1072 firstheaderBorderBelowCB->setChecked(false);
1075 row_set = tabular.getRowOfLTFoot(row, ltt);
1076 footerStatusCB->setChecked(row_set);
1078 footerBorderAboveCB->setChecked(ltt.topDL);
1079 footerBorderBelowCB->setChecked(ltt.bottomDL);
1082 footerBorderAboveCB->setChecked(false);
1083 footerBorderBelowCB->setChecked(false);
1084 lastfooterNoContentsCB->setChecked(false);
1088 row_set = tabular.getRowOfLTLastFoot(row, ltt);
1089 lastfooterStatusCB->setChecked(row_set);
1090 if (ltt.set && (!ltt.empty || !use_empty)) {
1091 lastfooterBorderAboveCB->setChecked(ltt.topDL);
1092 lastfooterBorderBelowCB->setChecked(ltt.bottomDL);
1094 lastfooterBorderAboveCB->setChecked(false);
1095 lastfooterBorderBelowCB->setChecked(false);
1097 newpageCB->setChecked(tabular.getLTNewPage(row));
1099 // first header can only be suppressed when there is a header
1100 firstheader_suppressable_ = tabular.haveLTHead()
1101 && !tabular.haveLTFirstHead();
1102 // last footer can only be suppressed when there is a footer
1103 lastfooter_suppressable_ = tabular.haveLTFoot()
1104 && !tabular.haveLTLastFoot();
1106 // after setting the features, check if they are enabled
1111 bool GuiTabular::checkWidgets(bool readonly) const
1113 tabularRowED->setReadOnly(readonly);
1114 tabularColumnED->setReadOnly(readonly);
1115 tabularWidthED->setReadOnly(readonly);
1116 specialAlignmentED->setReadOnly(readonly);
1117 columnWidthED->setReadOnly(readonly);
1118 multirowOffsetED->setReadOnly(readonly);
1119 decimalPointED->setReadOnly(readonly);
1122 multicolumnCB->setEnabled(false);
1123 multirowCB->setEnabled(false);
1124 rotateCellCB->setEnabled(false);
1125 rotateCellAngleSB->setEnabled(false);
1126 rotateTabularCB->setEnabled(false);
1127 rotateTabularAngleSB->setEnabled(false);
1128 longTabularCB->setEnabled(false);
1129 borders->setEnabled(false);
1130 tabularWidthUnitLC->setEnabled(false);
1131 columnWidthUnitLC->setEnabled(false);
1132 multirowOffsetUnitLC->setEnabled(false);
1133 setBordersGB->setEnabled(false);
1134 allBordersGB->setEnabled(false);
1135 borderStyleGB->setEnabled(false);
1136 booktabsRB->setEnabled(false);
1137 topspaceCO->setEnabled(false);
1138 topspaceUnitLC->setEnabled(false);
1139 bottomspaceCO->setEnabled(false);
1140 bottomspaceUnitLC->setEnabled(false);
1141 interlinespaceCO->setEnabled(false);
1142 interlinespaceUnitLC->setEnabled(false);
1143 hAlignCO->setEnabled(false);
1144 vAlignCO->setEnabled(false);
1145 TableAlignCO->setEnabled(false);
1146 longtableGB->setEnabled(false);
1147 alignmentGB->setEnabled(false);
1151 return InsetParamsWidget::checkWidgets();
1155 bool GuiTabular::funcEnabled(Tabular::Feature f) const
1157 FuncRequest r(LFUN_INSET_MODIFY, "tabular for-dialog" + featureAsString(f));
1158 return getStatus(r).enabled();
1162 } // namespace frontend
1165 #include "moc_GuiTabular.cpp"