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)
55 tabularWidthED->setValidator(unsignedLengthValidator(tabularWidthED));
56 columnWidthED->setValidator(unsignedLengthValidator(columnWidthED));
57 multirowOffsetED->setValidator(new LengthValidator(multirowOffsetED));
58 topspaceED->setValidator(new LengthValidator(topspaceED));
59 bottomspaceED->setValidator(new LengthValidator(bottomspaceED));
60 interlinespaceED->setValidator(new LengthValidator(interlinespaceED));
62 tabularWidthUnitLC->setCurrentItem(Length::defaultUnit());
63 columnWidthUnitLC->setCurrentItem(Length::defaultUnit());
64 multirowOffsetUnitLC->setCurrentItem(Length::defaultUnit());
65 topspaceUnitLC->setCurrentItem(Length::defaultUnit());
66 bottomspaceUnitLC->setCurrentItem(Length::defaultUnit());
67 interlinespaceUnitLC->setCurrentItem(Length::defaultUnit());
69 connect(topspaceED, SIGNAL(textEdited(const QString &)),
70 this, SLOT(checkEnabled()));
71 connect(topspaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
72 this, SLOT(checkEnabled()));
73 connect(bottomspaceED, SIGNAL(textEdited(const QString &)),
74 this, SLOT(checkEnabled()));
75 connect(bottomspaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
76 this, SLOT(checkEnabled()));
77 connect(interlinespaceED, SIGNAL(textEdited(const QString &)),
78 this, SLOT(checkEnabled()));
79 connect(interlinespaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
80 this, SLOT(checkEnabled()));
81 connect(booktabsRB, SIGNAL(clicked(bool)),
82 this, SLOT(checkEnabled()));
83 connect(borderDefaultRB, SIGNAL(clicked(bool)),
84 this, SLOT(checkEnabled()));
85 connect(borderSetPB, SIGNAL(clicked()),
86 this, SLOT(borderSet_clicked()));
87 connect(borderUnsetPB, SIGNAL(clicked()),
88 this, SLOT(borderUnset_clicked()));
89 connect(hAlignCO, SIGNAL(activated(int)),
90 this, SLOT(checkEnabled()));
91 connect(vAlignCO, SIGNAL(activated(int)),
92 this, SLOT(checkEnabled()));
93 connect(multicolumnCB, SIGNAL(clicked()),
94 this, SLOT(checkEnabled()));
95 connect(multirowCB, SIGNAL(clicked()),
96 this, SLOT(checkEnabled()));
97 connect(multirowOffsetED, SIGNAL(textEdited(const QString &)),
98 this, SLOT(checkEnabled()));
99 connect(multirowOffsetUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
100 this, SLOT(checkEnabled()));
101 connect(newpageCB, SIGNAL(clicked()),
102 this, SLOT(checkEnabled()));
103 connect(headerStatusCB, SIGNAL(clicked()),
104 this, SLOT(checkEnabled()));
105 connect(headerBorderAboveCB, SIGNAL(clicked()),
106 this, SLOT(checkEnabled()));
107 connect(headerBorderBelowCB, SIGNAL(clicked()),
108 this, SLOT(checkEnabled()));
109 connect(firstheaderStatusCB, SIGNAL(clicked()),
110 this, SLOT(checkEnabled()));
111 connect(firstheaderBorderAboveCB, SIGNAL(clicked()),
112 this, SLOT(checkEnabled()));
113 connect(firstheaderBorderBelowCB, SIGNAL(clicked()),
114 this, SLOT(checkEnabled()));
115 connect(firstheaderNoContentsCB, SIGNAL(clicked()),
116 this, SLOT(checkEnabled()));
117 connect(footerStatusCB, SIGNAL(clicked()),
118 this, SLOT(checkEnabled()));
119 connect(footerBorderAboveCB, SIGNAL(clicked()),
120 this, SLOT(checkEnabled()));
121 connect(footerBorderBelowCB, SIGNAL(clicked()),
122 this, SLOT(checkEnabled()));
123 connect(lastfooterStatusCB, SIGNAL(clicked()),
124 this, SLOT(checkEnabled()));
125 connect(lastfooterBorderAboveCB, SIGNAL(clicked()),
126 this, SLOT(checkEnabled()));
127 connect(lastfooterBorderBelowCB, SIGNAL(clicked()),
128 this, SLOT(checkEnabled()));
129 connect(lastfooterNoContentsCB, SIGNAL(clicked()),
130 this, SLOT(checkEnabled()));
131 connect(captionStatusCB, SIGNAL(clicked()),
132 this, SLOT(checkEnabled()));
133 connect(specialAlignmentED, SIGNAL(textEdited(const QString &)),
134 this, SLOT(checkEnabled()));
135 connect(columnWidthED, SIGNAL(textEdited(const QString &)),
136 this, SLOT(checkEnabled()));
137 connect(columnWidthUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)),
138 this, SLOT(checkEnabled()));
139 connect(borders, SIGNAL(topSet()),
140 this, SLOT(checkEnabled()));
141 connect(borders, SIGNAL(bottomSet()),
142 this, SLOT(checkEnabled()));
143 connect(borders, SIGNAL(rightSet()),
144 this, SLOT(checkEnabled()));
145 connect(borders, SIGNAL(leftSet()),
146 this, SLOT(checkEnabled()));
147 connect(rotateTabularCB, SIGNAL(clicked()),
148 this, SLOT(checkEnabled()));
149 connect(rotateTabularAngleSB, SIGNAL(valueChanged(int)),
150 this, SLOT(checkEnabled()));
151 connect(rotateCellCB, SIGNAL(clicked()),
152 this, SLOT(checkEnabled()));
153 connect(rotateCellAngleSB, SIGNAL(valueChanged(int)),
154 this, SLOT(checkEnabled()));
155 connect(TableAlignCO, SIGNAL(activated(int)),
156 this, SLOT(checkEnabled()));
157 connect(longTabularCB, SIGNAL(clicked()),
158 this, SLOT(checkEnabled()));
159 connect(leftRB, SIGNAL(clicked()),
160 this, SLOT(checkEnabled()));
161 connect(centerRB, SIGNAL(clicked()),
162 this, SLOT(checkEnabled()));
163 connect(rightRB, SIGNAL(clicked()),
164 this, SLOT(checkEnabled()));
165 connect(tabularWidthED, SIGNAL(textEdited(const QString &)),
166 this, SLOT(checkEnabled()));
168 decimalPointED->setInputMask("X; ");
169 decimalPointED->setMaxLength(1);
171 // initialize the length validator
172 addCheckedWidget(columnWidthED, columnWidthLA);
173 addCheckedWidget(multirowOffsetED, multirowOffsetLA);
174 addCheckedWidget(topspaceED, topspaceLA);
175 addCheckedWidget(bottomspaceED, bottomspaceLA);
176 addCheckedWidget(interlinespaceED, interlinespaceLA);
177 addCheckedWidget(tabularWidthED, tabularWidthLA);
181 void GuiTabular::on_topspaceCO_activated(int index)
183 bool const enable = (index == 2);
184 topspaceED->setEnabled(enable);
185 topspaceUnitLC->setEnabled(enable);
189 void GuiTabular::on_bottomspaceCO_activated(int index)
191 bool const enable = (index == 2);
192 bottomspaceED->setEnabled(enable);
193 bottomspaceUnitLC->setEnabled(enable);
197 void GuiTabular::on_interlinespaceCO_activated(int index)
199 bool const enable = (index == 2);
200 interlinespaceED->setEnabled(enable);
201 interlinespaceUnitLC->setEnabled(enable);
205 void GuiTabular::enableWidgets() const
207 // if there is a LaTeX argument, the width and alignment will be overwritten
208 // therefore disable them in this case
209 columnWidthED->setEnabled(specialAlignmentED->text().isEmpty());
210 columnWidthUnitLC->setEnabled(specialAlignmentED->text().isEmpty());
211 // if the column has a width, multirows are always left-aligned
212 // therefore disable hAlignCB in this case
213 hAlignCO->setEnabled(!(multirowCB->isChecked()
214 && !widgetsToLength(columnWidthED, columnWidthUnitLC).empty())
215 && specialAlignmentED->text().isEmpty());
216 // decimal alignment is only possible for non-multicol and non-multirow cells
217 if ((multicolumnCB->isChecked() || multirowCB->isChecked())
218 && hAlignCO->findData(toqstr("decimal")))
219 hAlignCO->removeItem(hAlignCO->findData(toqstr("decimal")));
220 else if (!multicolumnCB->isChecked() && !multirowCB->isChecked()
221 && hAlignCO->findData(toqstr("decimal")) == -1)
222 hAlignCO->addItem(qt_("At Decimal Separator"), toqstr("decimal"));
224 hAlignCO->itemData(hAlignCO->currentIndex()).toString() == QString("decimal");
225 decimalPointED->setEnabled(dalign);
226 decimalLA->setEnabled(dalign);
228 bool const setwidth = TableAlignCO->currentText() == qt_("Middle")
229 && !longTabularCB->isChecked();
230 tabularWidthLA->setEnabled(setwidth);
231 tabularWidthED->setEnabled(setwidth);
232 tabularWidthUnitLC->setEnabled(setwidth);
234 rotateTabularAngleSB->setEnabled(rotateTabularCB->isChecked()
235 && !longTabularCB->isChecked());
236 rotateCellAngleSB->setEnabled(rotateCellCB->isChecked());
238 bool const enable_valign =
239 !multirowCB->isChecked()
240 && !widgetsToLength(columnWidthED, columnWidthUnitLC).empty()
241 && specialAlignmentED->text().isEmpty();
242 vAlignCO->setEnabled(enable_valign);
243 vAlignLA->setEnabled(enable_valign);
245 topspaceED->setEnabled(topspaceCO->currentIndex() == 2);
246 topspaceED->setEnabled(topspaceCO->currentIndex() == 2);
247 topspaceUnitLC->setEnabled(topspaceCO->currentIndex() == 2);
248 bottomspaceED->setEnabled(bottomspaceCO->currentIndex() == 2);
249 bottomspaceUnitLC->setEnabled(bottomspaceCO->currentIndex() == 2);
250 interlinespaceED->setEnabled(interlinespaceCO->currentIndex() == 2);
251 interlinespaceUnitLC->setEnabled(interlinespaceCO->currentIndex() == 2);
253 // setting as longtable is not allowed when table is inside a float
254 bool const is_tabular_star = !tabularWidthED->text().isEmpty();
255 longTabularCB->setEnabled(!is_tabular_star && funcEnabled(Tabular::SET_LONGTABULAR));
256 bool const longtabular = longTabularCB->isChecked();
257 longtableGB->setEnabled(true);
258 newpageCB->setEnabled(longtabular);
259 alignmentGB->setEnabled(longtabular);
260 // longtables and tabular* cannot have a vertical alignment
261 TableAlignLA->setDisabled(is_tabular_star || longtabular);
262 TableAlignCO->setDisabled(is_tabular_star || longtabular);
263 // longtable cannot be rotated with rotating package, only
264 // with [pdf]lscape, which only supports 90 deg.
265 rotateTabularAngleSB->setDisabled(longtabular);
267 // FIXME: This Dialog is really horrible, disabling/enabling a checkbox
268 // depending on the cursor position is very very unintuitive...
269 // We need some edit boxes to show which rows are header/footer/etc
270 // without having to move the cursor first.
271 headerStatusCB->setEnabled(longtabular
272 && (headerStatusCB->isChecked() ?
273 funcEnabled(Tabular::UNSET_LTHEAD) :
274 funcEnabled(Tabular::SET_LTHEAD)));
275 headerBorderAboveCB->setEnabled(longtabular
276 && headerStatusCB->isChecked());
277 headerBorderBelowCB->setEnabled(longtabular
278 && headerStatusCB->isChecked());
280 // first header can only be suppressed when there is a header
281 // firstheader_suppressable_ is set in paramsToDialog
282 firstheaderNoContentsCB->setEnabled(longtabular && firstheader_suppressable_);
283 // check if setting a first header is allowed
284 // additionally check firstheaderNoContentsCB because when this is
285 // the case a first header makes no sense
286 firstheaderStatusCB->setEnabled((firstheaderStatusCB->isChecked() ?
287 funcEnabled(Tabular::UNSET_LTFIRSTHEAD) :
288 funcEnabled(Tabular::SET_LTFIRSTHEAD))
289 && longtabular && !firstheaderNoContentsCB->isChecked());
290 firstheaderBorderAboveCB->setEnabled(longtabular
291 && firstheaderStatusCB->isChecked());
292 firstheaderBorderBelowCB->setEnabled(longtabular
293 && firstheaderStatusCB->isChecked());
295 footerStatusCB->setEnabled(longtabular
296 && (footerStatusCB->isChecked() ?
297 funcEnabled(Tabular::UNSET_LTFOOT) :
298 funcEnabled(Tabular::SET_LTFOOT)));
299 footerBorderAboveCB->setEnabled(longtabular
300 && footerBorderAboveCB->isChecked());
301 footerBorderBelowCB->setEnabled(longtabular
302 && footerBorderAboveCB->isChecked());
304 // last footer can only be suppressed when there is a footer
305 // lastfooter_suppressable_ is set in paramsToDialog
306 lastfooterNoContentsCB->setEnabled(longtabular && lastfooter_suppressable_);
307 // check if setting a last footer is allowed
308 // additionally check lastfooterNoContentsCB because when this is
309 // the case a last footer makes no sense
310 lastfooterStatusCB->setEnabled((lastfooterStatusCB->isChecked() ?
311 funcEnabled(Tabular::UNSET_LTLASTFOOT) :
312 funcEnabled(Tabular::SET_LTLASTFOOT))
313 && longtabular && !lastfooterNoContentsCB->isChecked());
314 lastfooterBorderAboveCB->setEnabled(longtabular
315 && lastfooterBorderAboveCB->isChecked());
316 lastfooterBorderBelowCB->setEnabled(longtabular
317 && lastfooterBorderAboveCB->isChecked());
319 captionStatusCB->setEnabled(funcEnabled(Tabular::TOGGLE_LTCAPTION)
322 multicolumnCB->setEnabled(funcEnabled(Tabular::MULTICOLUMN)
323 && !dalign && !multirowCB->isChecked());
324 multirowCB->setEnabled(funcEnabled(Tabular::MULTIROW)
325 && !dalign && !multicolumnCB->isChecked());
326 bool const enable_mr = multirowCB->isChecked();
327 multirowOffsetLA->setEnabled(enable_mr);
328 multirowOffsetED->setEnabled(enable_mr);
329 multirowOffsetUnitLC->setEnabled(enable_mr);
331 // Vertical lines cannot be set in formal tables
332 borders->setLeftEnabled(!booktabsRB->isChecked());
333 borders->setRightEnabled(!booktabsRB->isChecked());
337 void GuiTabular::checkEnabled()
344 void GuiTabular::borderSet_clicked()
346 borders->setTop(GuiSetBorder::LINE_SET);
347 borders->setBottom(GuiSetBorder::LINE_SET);
348 borders->setLeft(GuiSetBorder::LINE_SET);
349 borders->setRight(GuiSetBorder::LINE_SET);
350 // repaint the setborder widget
356 void GuiTabular::borderUnset_clicked()
358 borders->setTop(GuiSetBorder::LINE_UNSET);
359 borders->setBottom(GuiSetBorder::LINE_UNSET);
360 borders->setLeft(GuiSetBorder::LINE_UNSET);
361 borders->setRight(GuiSetBorder::LINE_UNSET);
362 // repaint the setborder widget
368 static void setParam(string & param_str, Tabular::Feature f, string const & arg = string())
371 param_str += featureAsString(f) + ' ' + arg;
375 void GuiTabular::setHAlign(string & param_str) const
377 Tabular::Feature num = Tabular::ALIGN_LEFT;
378 Tabular::Feature multi_num = Tabular::M_ALIGN_LEFT;
380 fromqstr(hAlignCO->itemData(hAlignCO->currentIndex()).toString());
381 if (align == "left") {
382 num = Tabular::ALIGN_LEFT;
383 multi_num = Tabular::M_ALIGN_LEFT;
384 } else if (align == "center") {
385 num = Tabular::ALIGN_CENTER;
386 multi_num = Tabular::M_ALIGN_CENTER;
387 } else if (align == "right") {
388 num = Tabular::ALIGN_RIGHT;
389 multi_num = Tabular::M_ALIGN_RIGHT;
390 } else if (align == "justified") {
391 num = Tabular::ALIGN_BLOCK;
392 //multi_num: no equivalent
393 } else if (align == "decimal") {
394 num = Tabular::ALIGN_DECIMAL;
395 //multi_num: no equivalent
398 if (multicolumnCB->isChecked())
399 setParam(param_str, multi_num);
401 setParam(param_str, num);
405 void GuiTabular::setVAlign(string & param_str) const
407 int const align = vAlignCO->currentIndex();
408 enum VALIGN { TOP, MIDDLE, BOTTOM };
412 case 0: v = TOP; break;
413 case 1: v = MIDDLE; break;
414 case 2: v = BOTTOM; break;
417 Tabular::Feature num = Tabular::VALIGN_MIDDLE;
418 Tabular::Feature multi_num = Tabular::M_VALIGN_MIDDLE;
422 num = Tabular::VALIGN_TOP;
423 multi_num = Tabular::M_VALIGN_TOP;
426 num = Tabular::VALIGN_MIDDLE;
427 multi_num = Tabular::M_VALIGN_MIDDLE;
430 num = Tabular::VALIGN_BOTTOM;
431 multi_num = Tabular::M_VALIGN_BOTTOM;
434 if (multicolumnCB->isChecked() || multirowCB->isChecked())
435 setParam(param_str, multi_num);
437 setParam(param_str, num);
441 void GuiTabular::setTableAlignment(string & param_str) const
443 int const align = TableAlignCO->currentIndex();
445 case 0: setParam(param_str, Tabular::TABULAR_VALIGN_TOP);
447 case 1: setParam(param_str, Tabular::TABULAR_VALIGN_MIDDLE);
449 case 2: setParam(param_str, Tabular::TABULAR_VALIGN_BOTTOM);
455 docstring GuiTabular::dialogToParams() const
457 string param_str = "tabular";
460 string tabwidth = widgetsToLength(tabularWidthED, tabularWidthUnitLC);
461 if (tabwidth.empty())
463 setParam(param_str, Tabular::SET_TABULAR_WIDTH, tabwidth);
465 // apply the fixed width values
466 // this must be done before applying the column alignment
467 // because its value influences the alignment of multirow cells
468 string width = widgetsToLength(columnWidthED, columnWidthUnitLC);
471 if (multicolumnCB->isChecked())
472 setParam(param_str, Tabular::SET_MPWIDTH, width);
474 setParam(param_str, Tabular::SET_PWIDTH, width);
476 // apply the column alignment
477 // multirows inherit the alignment from the column; if a column width
478 // is set, multirows are always left-aligned so that in this case
479 // its alignment must not be applied (see bug #8084)
480 if (!(multirowCB->isChecked() && width != "0pt"))
481 setHAlign(param_str);
483 // SET_DECIMAL_POINT must come after setHAlign() (ALIGN_DECIMAL)
484 string decimal_point = fromqstr(decimalPointED->text());
485 if (decimal_point.empty())
486 decimal_point = lyxrc.default_decimal_point;
487 setParam(param_str, Tabular::SET_DECIMAL_POINT, decimal_point);
489 setVAlign(param_str);
490 setTableAlignment(param_str);
492 if (booktabsRB->isChecked())
493 setParam(param_str, Tabular::SET_BOOKTABS);
495 setParam(param_str, Tabular::UNSET_BOOKTABS);
498 switch (topspaceCO->currentIndex()) {
500 setParam(param_str, Tabular::SET_TOP_SPACE, "none");
503 setParam(param_str, Tabular::SET_TOP_SPACE, "default");
506 if (!topspaceED->text().isEmpty())
507 setParam(param_str, Tabular::SET_TOP_SPACE,
508 widgetsToLength(topspaceED, topspaceUnitLC));
513 switch (bottomspaceCO->currentIndex()) {
515 setParam(param_str, Tabular::SET_BOTTOM_SPACE, "none");
518 setParam(param_str, Tabular::SET_BOTTOM_SPACE, "default");
521 if (!bottomspaceED->text().isEmpty())
522 setParam(param_str, Tabular::SET_BOTTOM_SPACE,
523 widgetsToLength(bottomspaceED,
529 switch (interlinespaceCO->currentIndex()) {
531 setParam(param_str, Tabular::SET_INTERLINE_SPACE, "none");
534 setParam(param_str, Tabular::SET_INTERLINE_SPACE, "default");
537 if (!interlinespaceED->text().isEmpty())
538 setParam(param_str, Tabular::SET_INTERLINE_SPACE,
539 widgetsToLength(interlinespaceED,
540 interlinespaceUnitLC));
545 if (borders->topLineSet() && borders->bottomLineSet() && borders->leftLineSet()
546 && borders->rightLineSet())
547 setParam(param_str, Tabular::SET_ALL_LINES);
548 else if (borders->topLineUnset() && borders->bottomLineUnset() && borders->leftLineUnset()
549 && borders->rightLineUnset())
550 setParam(param_str, Tabular::UNSET_ALL_LINES);
552 if (borders->getLeft() != GuiSetBorder::LINE_UNDECIDED)
553 setParam(param_str, Tabular::SET_LINE_LEFT,
554 borders->leftLineSet() ? "true" : "false");
555 if (borders->getRight() != GuiSetBorder::LINE_UNDECIDED)
556 setParam(param_str, Tabular::SET_LINE_RIGHT,
557 borders->rightLineSet() ? "true" : "false");
558 if (borders->getTop() != GuiSetBorder::LINE_UNDECIDED)
559 setParam(param_str, Tabular::SET_LINE_TOP,
560 borders->topLineSet() ? "true" : "false");
561 if (borders->getBottom() != GuiSetBorder::LINE_UNDECIDED)
562 setParam(param_str, Tabular::SET_LINE_BOTTOM,
563 borders->bottomLineSet() ? "true" : "false");
566 // apply the special alignment
567 string special = fromqstr(specialAlignmentED->text());
568 if (support::trim(special).empty())
570 if (multicolumnCB->isChecked())
571 setParam(param_str, Tabular::SET_SPECIAL_MULTICOLUMN, special);
573 setParam(param_str, Tabular::SET_SPECIAL_COLUMN, special);
576 if (multicolumnCB->isChecked())
577 setParam(param_str, Tabular::SET_MULTICOLUMN);
579 setParam(param_str, Tabular::UNSET_MULTICOLUMN);
581 // apply the multirow offset
582 string mroffset = widgetsToLength(multirowOffsetED, multirowOffsetUnitLC);
583 if (mroffset.empty())
585 if (multirowCB->isChecked())
586 setParam(param_str, Tabular::SET_MROFFSET, mroffset);
588 if (multirowCB->isChecked())
589 setParam(param_str, Tabular::SET_MULTIROW);
591 setParam(param_str, Tabular::UNSET_MULTIROW);
592 // store the table rotation angle
593 string const tabular_angle = convert<string>(rotateTabularAngleSB->value());
594 if (rotateTabularCB->isChecked())
595 setParam(param_str, Tabular::SET_ROTATE_TABULAR, tabular_angle);
597 setParam(param_str, Tabular::UNSET_ROTATE_TABULAR, tabular_angle);
598 // store the cell rotation angle
599 string const cell_angle = convert<string>(rotateCellAngleSB->value());
600 if (rotateCellCB->isChecked())
601 setParam(param_str, Tabular::SET_ROTATE_CELL, cell_angle);
603 setParam(param_str, Tabular::UNSET_ROTATE_CELL, cell_angle);
605 if (longTabularCB->isChecked())
606 setParam(param_str, Tabular::SET_LONGTABULAR);
608 setParam(param_str, Tabular::UNSET_LONGTABULAR);
610 if (newpageCB->isChecked())
611 setParam(param_str, Tabular::SET_LTNEWPAGE);
613 setParam(param_str, Tabular::UNSET_LTNEWPAGE);
615 if (captionStatusCB->isChecked())
616 setParam(param_str, Tabular::SET_LTCAPTION);
618 setParam(param_str, Tabular::UNSET_LTCAPTION);
620 if (headerStatusCB->isChecked())
621 setParam(param_str, Tabular::SET_LTHEAD, "none");
623 setParam(param_str, Tabular::UNSET_LTHEAD, "none");
625 if (headerBorderAboveCB->isChecked())
626 setParam(param_str, Tabular::SET_LTHEAD, "dl_above");
628 setParam(param_str, Tabular::UNSET_LTHEAD, "dl_above");
630 if (headerBorderBelowCB->isChecked())
631 setParam(param_str, Tabular::SET_LTHEAD, "dl_below");
633 setParam(param_str, Tabular::UNSET_LTHEAD, "dl_below");
634 if (firstheaderBorderAboveCB->isChecked())
635 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "dl_above");
637 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "dl_above");
638 if (firstheaderBorderBelowCB->isChecked())
639 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "dl_below");
641 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "dl_below");
642 if (firstheaderStatusCB->isChecked())
643 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "none");
645 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "none");
646 if (firstheaderNoContentsCB->isChecked())
647 setParam(param_str, Tabular::SET_LTFIRSTHEAD, "empty");
649 setParam(param_str, Tabular::UNSET_LTFIRSTHEAD, "empty");
650 if (footerStatusCB->isChecked())
651 setParam(param_str, Tabular::SET_LTFOOT, "none");
653 setParam(param_str, Tabular::UNSET_LTFOOT, "none");
654 if (footerBorderAboveCB->isChecked())
655 setParam(param_str, Tabular::SET_LTFOOT, "dl_above");
657 setParam(param_str, Tabular::UNSET_LTFOOT, "dl_above");
658 if (footerBorderBelowCB->isChecked())
659 setParam(param_str, Tabular::SET_LTFOOT, "dl_below");
661 setParam(param_str, Tabular::UNSET_LTFOOT, "dl_below");
662 if (lastfooterStatusCB->isChecked())
663 setParam(param_str, Tabular::SET_LTLASTFOOT, "none");
665 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "none");
666 if (lastfooterBorderAboveCB->isChecked())
667 setParam(param_str, Tabular::SET_LTLASTFOOT, "dl_above");
669 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "dl_above");
670 if (lastfooterBorderBelowCB->isChecked())
671 setParam(param_str, Tabular::SET_LTLASTFOOT, "dl_below");
673 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "dl_below");
674 if (lastfooterNoContentsCB->isChecked())
675 setParam(param_str, Tabular::SET_LTLASTFOOT, "empty");
677 setParam(param_str, Tabular::UNSET_LTLASTFOOT, "empty");
679 if (leftRB->isChecked())
680 setParam(param_str, Tabular::LONGTABULAR_ALIGN_LEFT);
681 else if (centerRB->isChecked())
682 setParam(param_str, Tabular::LONGTABULAR_ALIGN_CENTER);
683 else if (rightRB->isChecked())
684 setParam(param_str, Tabular::LONGTABULAR_ALIGN_RIGHT);
686 return from_utf8(param_str);
690 static Length getColumnPWidth(Tabular const & t, size_t cell)
692 return t.column_info[t.cellColumn(cell)].p_width;
696 static Length getMColumnPWidth(Tabular const & t, size_t cell)
698 if (t.isMultiColumn(cell) || t.isMultiRow(cell))
699 return t.cellInfo(cell).p_width;
704 static Length getMROffset(Tabular const & t, size_t cell)
706 if (t.isMultiRow(cell))
707 return t.cellInfo(cell).mroffset;
712 static docstring getAlignSpecial(Tabular const & t, size_t cell, int what)
714 if (what == Tabular::SET_SPECIAL_MULTICOLUMN)
715 return t.cellInfo(cell).align_special;
716 return t.column_info[t.cellColumn(cell)].align_special;
720 GuiSetBorder::BorderState GuiTabular::borderState(GuiSetBorder::BorderState bs,
723 if (bs == GuiSetBorder::LINE_UNDEF)
724 bs = line ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
725 else if ((bs == GuiSetBorder::LINE_SET && !line)
726 || (bs == GuiSetBorder::LINE_UNSET && line))
727 bs = GuiSetBorder::LINE_UNDECIDED;
732 void GuiTabular::paramsToDialog(Inset const * inset)
734 InsetTabular const * itab = static_cast<InsetTabular const *>(inset);
735 // Copy Tabular of current inset.
736 Tabular const & tabular = itab->tabular;
738 BufferView const * bv = guiApp->currentView()->currentBufferView();
739 size_t const cell = bv->cursor().idx();
741 Tabular::row_type const row = tabular.cellRow(cell);
742 Tabular::col_type const col = tabular.cellColumn(cell);
744 tabularRowED->setText(QString::number(row + 1));
745 tabularColumnED->setText(QString::number(col + 1));
747 bool const multicol = tabular.isMultiColumn(cell);
748 multicolumnCB->setChecked(multicol);
750 bool const multirow = tabular.isMultiRow(cell);
751 multirowCB->setChecked(multirow);
753 rotateCellCB->setChecked(tabular.getRotateCell(cell) != 0);
754 if (rotateCellCB->isChecked()) {
755 if (tabular.getRotateCell(cell) != 0)
756 rotateCellAngleSB->setValue(tabular.getRotateCell(cell));
758 rotateCellAngleSB->setValue(90);
761 longTabularCB->setChecked(tabular.is_long_tabular);
763 rotateTabularCB->setChecked(tabular.rotate != 0);
764 if (rotateTabularCB->isChecked()) {
765 if (longTabularCB->isChecked())
766 rotateTabularAngleSB->setValue(90);
768 rotateTabularAngleSB->setValue(tabular.rotate != 0 ? tabular.rotate : 90);
771 // In what follows, we check the borders of all selected cells,
772 // and if there are diverging settings, we use the LINE_UNDECIDED
774 GuiSetBorder::BorderState lt = GuiSetBorder::LINE_UNDEF;
775 GuiSetBorder::BorderState lb = GuiSetBorder::LINE_UNDEF;
776 GuiSetBorder::BorderState ll = GuiSetBorder::LINE_UNDEF;
777 GuiSetBorder::BorderState lr = GuiSetBorder::LINE_UNDEF;
778 CursorSlice const & beg = bv->cursor().selBegin();
779 CursorSlice const & end = bv->cursor().selEnd();
781 Tabular::col_type cs = tabular.cellColumn(beg.idx());
782 Tabular::col_type ce = tabular.cellColumn(end.idx());
785 Tabular::row_type rs = tabular.cellRow(beg.idx());
786 Tabular::row_type re = tabular.cellRow(end.idx());
789 for (Tabular::row_type r = rs; r <= re; ++r)
790 for (Tabular::col_type c = cs; c <= ce; ++c) {
791 idx_type const cc = tabular.cellIndex(r, c);
792 lt = borderState(lt, tabular.topLine(cc));
793 lb = borderState(lb, tabular.bottomLine(cc));
794 ll = borderState(ll, tabular.leftLine(cc));
795 lr = borderState(lr, tabular.rightLine(cc));
798 lt = tabular.topLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
799 lb = tabular.bottomLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
800 ll = tabular.leftLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
801 lr = tabular.rightLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET;
804 borders->setBottom(lb);
805 borders->setLeft(ll);
806 borders->setRight(lr);
807 // repaint the setborder widget
810 Length::UNIT const default_unit = Length::defaultUnit();
812 ///////////////////////////////////
813 // Set width and alignment
815 Length const tabwidth = tabular.tabularWidth();
817 && !(tabularWidthED->hasFocus() && tabularWidthED->text() == "0"))
818 tabularWidthED->clear();
820 lengthToWidgets(tabularWidthED, tabularWidthUnitLC,
821 tabwidth.asString(), default_unit);
826 special = getAlignSpecial(tabular, cell,
827 Tabular::SET_SPECIAL_MULTICOLUMN);
828 pwidth = getMColumnPWidth(tabular, cell);
830 special = getAlignSpecial(tabular, cell,
831 Tabular::SET_SPECIAL_COLUMN);
832 pwidth = getColumnPWidth(tabular, cell);
836 && !(columnWidthED->hasFocus() && columnWidthED->text() == "0"))
837 columnWidthED->clear();
839 colwidth = pwidth.asString();
840 lengthToWidgets(columnWidthED, columnWidthUnitLC,
841 colwidth, default_unit);
845 mroffset = getMROffset(tabular, cell);
848 && !(multirowOffsetED->hasFocus() && multirowOffsetED->text() == "0"))
849 multirowOffsetED->clear();
851 offset = mroffset.asString();
852 lengthToWidgets(multirowOffsetED, multirowOffsetUnitLC,
853 offset, default_unit);
855 specialAlignmentED->setText(toqstr(special));
856 ///////////////////////////////////
859 borderDefaultRB->setChecked(!tabular.use_booktabs);
860 booktabsRB->setChecked(tabular.use_booktabs);
862 if (tabular.row_info[row].top_space.empty()
863 && !tabular.row_info[row].top_space_default) {
864 topspaceCO->setCurrentIndex(0);
865 } else if (tabular.row_info[row].top_space_default) {
866 topspaceCO->setCurrentIndex(1);
868 topspaceCO->setCurrentIndex(2);
869 lengthToWidgets(topspaceED,
871 tabular.row_info[row].top_space.asString(),
875 if (tabular.row_info[row].bottom_space.empty()
876 && !tabular.row_info[row].bottom_space_default) {
877 bottomspaceCO->setCurrentIndex(0);
878 } else if (tabular.row_info[row].bottom_space_default) {
879 bottomspaceCO->setCurrentIndex(1);
881 bottomspaceCO->setCurrentIndex(2);
882 lengthToWidgets(bottomspaceED,
884 tabular.row_info[row].bottom_space.asString(),
888 if (tabular.row_info[row].interline_space.empty()
889 && !tabular.row_info[row].interline_space_default) {
890 interlinespaceCO->setCurrentIndex(0);
891 } else if (tabular.row_info[row].interline_space_default) {
892 interlinespaceCO->setCurrentIndex(1);
894 interlinespaceCO->setCurrentIndex(2);
895 lengthToWidgets(interlinespaceED,
896 interlinespaceUnitLC,
897 tabular.row_info[row].interline_space.asString(),
902 hAlignCO->addItem(qt_("Left"), toqstr("left"));
903 hAlignCO->addItem(qt_("Center"), toqstr("center"));
904 hAlignCO->addItem(qt_("Right"), toqstr("right"));
905 if (!multicol && !pwidth.zero())
906 hAlignCO->addItem(qt_("Justified"), toqstr("justified"));
907 if (!multicol && !multirow)
908 hAlignCO->addItem(qt_("At Decimal Separator"), toqstr("decimal"));
911 switch (tabular.getAlignment(cell)) {
915 case LYX_ALIGN_CENTER:
918 case LYX_ALIGN_RIGHT:
921 case LYX_ALIGN_BLOCK:
923 if (!multicol && !pwidth.zero())
927 case LYX_ALIGN_DECIMAL:
929 if (!multicol && !multirow)
934 // we should never end up here
937 hAlignCO->setCurrentIndex(hAlignCO->findData(toqstr(align)));
940 QString decimal_point = toqstr(tabular.column_info[col].decimal_point);
941 if (decimal_point.isEmpty())
942 decimal_point = toqstr(from_utf8(lyxrc.default_decimal_point));
943 decimalPointED->setText(decimal_point);
946 switch (tabular.getVAlignment(cell)) {
947 case Tabular::LYX_VALIGN_TOP:
950 case Tabular::LYX_VALIGN_MIDDLE:
953 case Tabular::LYX_VALIGN_BOTTOM:
962 vAlignCO->setCurrentIndex(valign);
965 switch (tabular.tabular_valignment) {
966 case Tabular::LYX_VALIGN_TOP:
969 case Tabular::LYX_VALIGN_MIDDLE:
972 case Tabular::LYX_VALIGN_BOTTOM:
979 TableAlignCO->setCurrentIndex(tableValign);
981 if (!tabular.is_long_tabular) {
982 headerStatusCB->setChecked(false);
983 headerBorderAboveCB->setChecked(false);
984 headerBorderBelowCB->setChecked(false);
985 firstheaderStatusCB->setChecked(false);
986 firstheaderBorderAboveCB->setChecked(false);
987 firstheaderBorderBelowCB->setChecked(false);
988 firstheaderNoContentsCB->setChecked(false);
989 footerStatusCB->setChecked(false);
990 footerBorderAboveCB->setChecked(false);
991 footerBorderBelowCB->setChecked(false);
992 lastfooterStatusCB->setChecked(false);
993 lastfooterBorderAboveCB->setChecked(false);
994 lastfooterBorderBelowCB->setChecked(false);
995 lastfooterNoContentsCB->setChecked(false);
996 newpageCB->setChecked(false);
997 captionStatusCB->blockSignals(true);
998 captionStatusCB->setChecked(false);
999 captionStatusCB->blockSignals(false);
1003 // longtables cannot have a vertical alignment
1004 TableAlignCO->setCurrentIndex(Tabular::LYX_VALIGN_MIDDLE);
1006 switch (tabular.longtabular_alignment) {
1007 case Tabular::LYX_LONGTABULAR_ALIGN_LEFT:
1008 leftRB->setChecked(true);
1010 case Tabular::LYX_LONGTABULAR_ALIGN_CENTER:
1011 centerRB->setChecked(true);
1013 case Tabular::LYX_LONGTABULAR_ALIGN_RIGHT:
1014 rightRB->setChecked(true);
1017 centerRB->setChecked(true);
1020 captionStatusCB->blockSignals(true);
1021 captionStatusCB->setChecked(tabular.ltCaption(row));
1022 captionStatusCB->blockSignals(false);
1024 Tabular::ltType ltt;
1026 bool row_set = tabular.getRowOfLTHead(row, ltt);
1027 headerStatusCB->setChecked(row_set);
1029 headerBorderAboveCB->setChecked(ltt.topDL);
1030 headerBorderBelowCB->setChecked(ltt.bottomDL);
1033 headerBorderAboveCB->setChecked(false);
1034 headerBorderBelowCB->setChecked(false);
1035 firstheaderNoContentsCB->setChecked(false);
1039 row_set = tabular.getRowOfLTFirstHead(row, ltt);
1040 firstheaderStatusCB->setChecked(row_set);
1041 if (ltt.set && (!ltt.empty || !use_empty)) {
1042 firstheaderBorderAboveCB->setChecked(ltt.topDL);
1043 firstheaderBorderBelowCB->setChecked(ltt.bottomDL);
1045 firstheaderBorderAboveCB->setChecked(false);
1046 firstheaderBorderBelowCB->setChecked(false);
1049 row_set = tabular.getRowOfLTFoot(row, ltt);
1050 footerStatusCB->setChecked(row_set);
1052 footerBorderAboveCB->setChecked(ltt.topDL);
1053 footerBorderBelowCB->setChecked(ltt.bottomDL);
1056 footerBorderAboveCB->setChecked(false);
1057 footerBorderBelowCB->setChecked(false);
1058 lastfooterNoContentsCB->setChecked(false);
1062 row_set = tabular.getRowOfLTLastFoot(row, ltt);
1063 lastfooterStatusCB->setChecked(row_set);
1064 if (ltt.set && (!ltt.empty || !use_empty)) {
1065 lastfooterBorderAboveCB->setChecked(ltt.topDL);
1066 lastfooterBorderBelowCB->setChecked(ltt.bottomDL);
1068 lastfooterBorderAboveCB->setChecked(false);
1069 lastfooterBorderBelowCB->setChecked(false);
1071 newpageCB->setChecked(tabular.getLTNewPage(row));
1073 // first header can only be suppressed when there is a header
1074 firstheader_suppressable_ = tabular.haveLTHead()
1075 && !tabular.haveLTFirstHead();
1076 // last footer can only be suppressed when there is a footer
1077 lastfooter_suppressable_ = tabular.haveLTFoot()
1078 && !tabular.haveLTLastFoot();
1080 // after setting the features, check if they are enabled
1085 bool GuiTabular::checkWidgets(bool readonly) const
1087 tabularRowED->setReadOnly(readonly);
1088 tabularColumnED->setReadOnly(readonly);
1089 tabularWidthED->setReadOnly(readonly);
1090 specialAlignmentED->setReadOnly(readonly);
1091 columnWidthED->setReadOnly(readonly);
1092 multirowOffsetED->setReadOnly(readonly);
1093 decimalPointED->setReadOnly(readonly);
1096 multicolumnCB->setEnabled(false);
1097 multirowCB->setEnabled(false);
1098 rotateCellCB->setEnabled(false);
1099 rotateCellAngleSB->setEnabled(false);
1100 rotateTabularCB->setEnabled(false);
1101 rotateTabularAngleSB->setEnabled(false);
1102 longTabularCB->setEnabled(false);
1103 borders->setEnabled(false);
1104 tabularWidthUnitLC->setEnabled(false);
1105 columnWidthUnitLC->setEnabled(false);
1106 multirowOffsetUnitLC->setEnabled(false);
1107 setBordersGB->setEnabled(false);
1108 allBordersGB->setEnabled(false);
1109 borderStyleGB->setEnabled(false);
1110 booktabsRB->setEnabled(false);
1111 topspaceCO->setEnabled(false);
1112 topspaceUnitLC->setEnabled(false);
1113 bottomspaceCO->setEnabled(false);
1114 bottomspaceUnitLC->setEnabled(false);
1115 interlinespaceCO->setEnabled(false);
1116 interlinespaceUnitLC->setEnabled(false);
1117 hAlignCO->setEnabled(false);
1118 vAlignCO->setEnabled(false);
1119 TableAlignCO->setEnabled(false);
1120 longtableGB->setEnabled(false);
1121 alignmentGB->setEnabled(false);
1125 return InsetParamsWidget::checkWidgets();
1129 bool GuiTabular::funcEnabled(Tabular::Feature f) const
1131 FuncRequest r(LFUN_INSET_MODIFY, "tabular for-dialog" + featureAsString(f));
1132 return getStatus(r).enabled();
1136 } // namespace frontend
1139 #include "moc_GuiTabular.cpp"