X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt4%2FGuiTabular.cpp;h=a09d9df62128efcffe74365dac91e44549024e7e;hb=f60bda37a608d74a13f6dd34eac6c10b15d18bc5;hp=a2dec894bb9c51ab19016b592622bdd4db6bf721;hpb=ecc492a3ce04dce62970946e4a3cd1e092a120d0;p=lyx.git diff --git a/src/frontends/qt4/GuiTabular.cpp b/src/frontends/qt4/GuiTabular.cpp index a2dec894bb..a09d9df621 100644 --- a/src/frontends/qt4/GuiTabular.cpp +++ b/src/frontends/qt4/GuiTabular.cpp @@ -31,7 +31,9 @@ #include "insets/InsetTabular.h" +#include "support/convert.h" #include "support/debug.h" +#include "support/lstrings.h" #include #include @@ -44,53 +46,60 @@ namespace lyx { namespace frontend { GuiTabular::GuiTabular(QWidget * parent) - : InsetParamsWidget(parent) + : InsetParamsWidget(parent), firstheader_suppressable_(false), + lastfooter_suppressable_(false), orig_leftborder_(GuiSetBorder::LINE_UNDEF), + orig_rightborder_(GuiSetBorder::LINE_UNDEF), lastrow_(0) + { setupUi(this); - widthED->setValidator(unsignedLengthValidator(widthED)); + tabularWidthED->setValidator(unsignedLengthValidator(tabularWidthED)); + columnWidthED->setValidator(unsignedLengthValidator(columnWidthED)); multirowOffsetED->setValidator(new LengthValidator(multirowOffsetED)); topspaceED->setValidator(new LengthValidator(topspaceED)); bottomspaceED->setValidator(new LengthValidator(bottomspaceED)); interlinespaceED->setValidator(new LengthValidator(interlinespaceED)); - widthUnitCB->setCurrentItem(Length::defaultUnit()); - multirowOffsetUnitCB->setCurrentItem(Length::defaultUnit()); - topspaceUnitCB->setCurrentItem(Length::defaultUnit()); - bottomspaceUnitCB->setCurrentItem(Length::defaultUnit()); - interlinespaceUnitCB->setCurrentItem(Length::defaultUnit()); + tabularWidthUnitLC->setCurrentItem(Length::defaultUnit()); + columnWidthUnitLC->setCurrentItem(Length::defaultUnit()); + multirowOffsetUnitLC->setCurrentItem(Length::defaultUnit()); + topspaceUnitLC->setCurrentItem(Length::defaultUnit()); + bottomspaceUnitLC->setCurrentItem(Length::defaultUnit()); + interlinespaceUnitLC->setCurrentItem(Length::defaultUnit()); - connect(topspaceED, SIGNAL(editingFinished()), + connect(topspaceED, SIGNAL(textEdited(const QString &)), this, SLOT(checkEnabled())); - connect(topspaceUnitCB, SIGNAL(selectionChanged(lyx::Length::UNIT)), + connect(topspaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)), this, SLOT(checkEnabled())); - connect(bottomspaceED, SIGNAL(editingFinished()), + connect(bottomspaceED, SIGNAL(textEdited(const QString &)), this, SLOT(checkEnabled())); - connect(bottomspaceUnitCB, SIGNAL(selectionChanged(lyx::Length::UNIT)), + connect(bottomspaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)), this, SLOT(checkEnabled())); - connect(interlinespaceED, SIGNAL(editingFinished()), + connect(interlinespaceED, SIGNAL(textEdited(const QString &)), this, SLOT(checkEnabled())); - connect(interlinespaceUnitCB, SIGNAL(selectionChanged(lyx::Length::UNIT)), + connect(interlinespaceUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)), this, SLOT(checkEnabled())); connect(booktabsRB, SIGNAL(clicked(bool)), - this, SLOT(checkEnabled())); + this, SLOT(booktabs_toggled(bool))); connect(borderDefaultRB, SIGNAL(clicked(bool)), - this, SLOT(checkEnabled())); + this, SLOT(nonbooktabs_toggled(bool))); connect(borderSetPB, SIGNAL(clicked()), this, SLOT(borderSet_clicked())); connect(borderUnsetPB, SIGNAL(clicked()), this, SLOT(borderUnset_clicked())); - connect(hAlignCB, SIGNAL(activated(int)), + connect(resetFormalCB, SIGNAL(clicked()), + this, SLOT(checkEnabled())); + connect(hAlignCO, SIGNAL(activated(int)), this, SLOT(checkEnabled())); - connect(vAlignCB, SIGNAL(activated(int)), + connect(vAlignCO, SIGNAL(activated(int)), this, SLOT(checkEnabled())); connect(multicolumnCB, SIGNAL(clicked()), this, SLOT(checkEnabled())); connect(multirowCB, SIGNAL(clicked()), this, SLOT(checkEnabled())); - connect(multirowOffsetED, SIGNAL(editingFinished()), + connect(multirowOffsetED, SIGNAL(textEdited(const QString &)), this, SLOT(checkEnabled())); - connect(multirowOffsetUnitCB, SIGNAL(selectionChanged(lyx::Length::UNIT)), + connect(multirowOffsetUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)), this, SLOT(checkEnabled())); connect(newpageCB, SIGNAL(clicked()), this, SLOT(checkEnabled())); @@ -124,25 +133,37 @@ GuiTabular::GuiTabular(QWidget * parent) this, SLOT(checkEnabled())); connect(captionStatusCB, SIGNAL(clicked()), this, SLOT(checkEnabled())); - connect(specialAlignmentED, SIGNAL(editingFinished()), + connect(specialAlignmentED, SIGNAL(textEdited(const QString &)), + this, SLOT(checkEnabled())); + connect(columnWidthED, SIGNAL(textEdited(const QString &)), + this, SLOT(checkEnabled())); + connect(columnWidthUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)), + this, SLOT(checkEnabled())); + connect(borders, SIGNAL(topSet()), + this, SLOT(checkEnabled())); + connect(borders, SIGNAL(bottomSet()), this, SLOT(checkEnabled())); - connect(widthED, SIGNAL(editingFinished()), + connect(borders, SIGNAL(rightSet()), this, SLOT(checkEnabled())); - connect(widthUnitCB, SIGNAL(selectionChanged(lyx::Length::UNIT)), + connect(borders, SIGNAL(leftSet()), this, SLOT(checkEnabled())); - connect(borders, SIGNAL(topSet(bool)), + connect(borders, SIGNAL(topLTSet()), this, SLOT(checkEnabled())); - connect(borders, SIGNAL(bottomSet(bool)), + connect(borders, SIGNAL(topRTSet()), this, SLOT(checkEnabled())); - connect(borders, SIGNAL(rightSet(bool)), + connect(borders, SIGNAL(bottomLTSet()), this, SLOT(checkEnabled())); - connect(borders, SIGNAL(leftSet(bool)), + connect(borders, SIGNAL(bottomRTSet()), this, SLOT(checkEnabled())); connect(rotateTabularCB, SIGNAL(clicked()), this, SLOT(checkEnabled())); + connect(rotateTabularAngleSB, SIGNAL(valueChanged(int)), + this, SLOT(checkEnabled())); connect(rotateCellCB, SIGNAL(clicked()), this, SLOT(checkEnabled())); - connect(TableAlignCB, SIGNAL(activated(int)), + connect(rotateCellAngleSB, SIGNAL(valueChanged(int)), + this, SLOT(checkEnabled())); + connect(TableAlignCO, SIGNAL(activated(int)), this, SLOT(checkEnabled())); connect(longTabularCB, SIGNAL(clicked()), this, SLOT(checkEnabled())); @@ -152,13 +173,19 @@ GuiTabular::GuiTabular(QWidget * parent) this, SLOT(checkEnabled())); connect(rightRB, SIGNAL(clicked()), this, SLOT(checkEnabled())); + connect(tabularWidthED, SIGNAL(textEdited(const QString &)), + this, SLOT(checkEnabled())); + + decimalPointED->setInputMask("X; "); + decimalPointED->setMaxLength(1); // initialize the length validator - addCheckedWidget(widthED, fixedWidthColLA); + addCheckedWidget(columnWidthED, columnWidthLA); addCheckedWidget(multirowOffsetED, multirowOffsetLA); addCheckedWidget(topspaceED, topspaceLA); addCheckedWidget(bottomspaceED, bottomspaceLA); addCheckedWidget(interlinespaceED, interlinespaceLA); + addCheckedWidget(tabularWidthED, tabularWidthLA); } @@ -166,7 +193,7 @@ void GuiTabular::on_topspaceCO_activated(int index) { bool const enable = (index == 2); topspaceED->setEnabled(enable); - topspaceUnitCB->setEnabled(enable); + topspaceUnitLC->setEnabled(enable); } @@ -174,7 +201,7 @@ void GuiTabular::on_bottomspaceCO_activated(int index) { bool const enable = (index == 2); bottomspaceED->setEnabled(enable); - bottomspaceUnitCB->setEnabled(enable); + bottomspaceUnitLC->setEnabled(enable); } @@ -182,50 +209,90 @@ void GuiTabular::on_interlinespaceCO_activated(int index) { bool const enable = (index == 2); interlinespaceED->setEnabled(enable); - interlinespaceUnitCB->setEnabled(enable); + interlinespaceUnitLC->setEnabled(enable); } -void GuiTabular::checkEnabled() +void GuiTabular::on_columnTypeCO_activated(int index) { - // if there is a LaTeX argument, the width and alignment will be overwrtitten + checkEnabled(); + if (index == 2) + columnWidthED->setFocus(); +} + + +void GuiTabular::enableWidgets() const +{ + // if there is a LaTeX argument, the width and alignment will be overwritten // therefore disable them in this case - widthED->setEnabled(specialAlignmentED->text().isEmpty()); + bool const fixed = specialAlignmentED->text().isEmpty() + && columnTypeCO->currentIndex() == 2; + columnWidthED->setEnabled(fixed); + columnWidthUnitLC->setEnabled(fixed); // if the column has a width, multirows are always left-aligned // therefore disable hAlignCB in this case - hAlignCB->setEnabled(!(multirowCB->isChecked() - && !widgetsToLength(widthED, widthUnitCB).empty()) - && specialAlignmentED->text().isEmpty()); - bool dalign = - hAlignCB->itemData(hAlignCB->currentIndex()).toString() == QString("decimal"); - decimalPointLE->setEnabled(dalign); - decimalL->setEnabled(dalign); - - vAlignCB->setEnabled(!multirowCB->isChecked() - && !widgetsToLength(widthED, widthUnitCB).empty() + hAlignCO->setEnabled(!(multirowCB->isChecked() + && !widgetsToLength(columnWidthED, columnWidthUnitLC).empty()) && specialAlignmentED->text().isEmpty()); + // decimal alignment is only possible for non-multicol and non-multirow cells + if ((multicolumnCB->isChecked() || multirowCB->isChecked() || columnTypeCO->currentIndex() == 1) + && hAlignCO->findData(toqstr("decimal"))) + hAlignCO->removeItem(hAlignCO->findData(toqstr("decimal"))); + else if (!multicolumnCB->isChecked() && !multirowCB->isChecked() + && hAlignCO->findData(toqstr("decimal")) == -1) + hAlignCO->addItem(qt_("At Decimal Separator"), toqstr("decimal")); + bool const dalign = + hAlignCO->itemData(hAlignCO->currentIndex()).toString() == QString("decimal"); + decimalPointED->setEnabled(dalign); + decimalLA->setEnabled(dalign); + resetFormalCB->setEnabled(booktabsRB->isChecked()); + + bool const setwidth = TableAlignCO->currentText() == qt_("Middle"); + tabularWidthLA->setEnabled(setwidth); + tabularWidthED->setEnabled(setwidth); + tabularWidthUnitLC->setEnabled(setwidth); + + rotateTabularAngleSB->setEnabled(rotateTabularCB->isChecked() + && !longTabularCB->isChecked()); + rotateCellAngleSB->setEnabled(rotateCellCB->isChecked()); + + bool const enable_valign = + !multirowCB->isChecked() + && !widgetsToLength(columnWidthED, columnWidthUnitLC).empty() + && specialAlignmentED->text().isEmpty(); + vAlignCO->setEnabled(enable_valign); + vAlignLA->setEnabled(enable_valign); topspaceED->setEnabled(topspaceCO->currentIndex() == 2); - topspaceUnitCB->setEnabled(topspaceCO->currentIndex() == 2); + topspaceED->setEnabled(topspaceCO->currentIndex() == 2); + topspaceUnitLC->setEnabled(topspaceCO->currentIndex() == 2); bottomspaceED->setEnabled(bottomspaceCO->currentIndex() == 2); - bottomspaceUnitCB->setEnabled(bottomspaceCO->currentIndex() == 2); + bottomspaceUnitLC->setEnabled(bottomspaceCO->currentIndex() == 2); interlinespaceED->setEnabled(interlinespaceCO->currentIndex() == 2); - interlinespaceUnitCB->setEnabled(interlinespaceCO->currentIndex() == 2); + interlinespaceUnitLC->setEnabled(interlinespaceCO->currentIndex() == 2); // setting as longtable is not allowed when table is inside a float + bool const is_tabular_star = !tabularWidthED->text().isEmpty(); longTabularCB->setEnabled(funcEnabled(Tabular::SET_LONGTABULAR)); bool const longtabular = longTabularCB->isChecked(); longtableGB->setEnabled(true); newpageCB->setEnabled(longtabular); alignmentGB->setEnabled(longtabular); - // longtables cannot have a vertical alignment - TableAlignCB->setDisabled(longtabular); + // longtables and tabular* cannot have a vertical alignment + TableAlignLA->setDisabled(is_tabular_star || longtabular); + TableAlignCO->setDisabled(is_tabular_star || longtabular); + // longtable cannot be rotated with rotating package, only + // with [pdf]lscape, which only supports 90 deg. + rotateTabularAngleSB->setDisabled(longtabular); // FIXME: This Dialog is really horrible, disabling/enabling a checkbox // depending on the cursor position is very very unintuitive... // We need some edit boxes to show which rows are header/footer/etc // without having to move the cursor first. - headerStatusCB->setEnabled(longtabular); + headerStatusCB->setEnabled(longtabular + && (headerStatusCB->isChecked() ? + funcEnabled(Tabular::UNSET_LTHEAD) : + funcEnabled(Tabular::SET_LTHEAD))); headerBorderAboveCB->setEnabled(longtabular && headerStatusCB->isChecked()); headerBorderBelowCB->setEnabled(longtabular @@ -237,14 +304,19 @@ void GuiTabular::checkEnabled() // check if setting a first header is allowed // additionally check firstheaderNoContentsCB because when this is // the case a first header makes no sense - firstheaderStatusCB->setEnabled(funcEnabled(Tabular::SET_LTFIRSTHEAD) + firstheaderStatusCB->setEnabled((firstheaderStatusCB->isChecked() ? + funcEnabled(Tabular::UNSET_LTFIRSTHEAD) : + funcEnabled(Tabular::SET_LTFIRSTHEAD)) && longtabular && !firstheaderNoContentsCB->isChecked()); firstheaderBorderAboveCB->setEnabled(longtabular && firstheaderStatusCB->isChecked()); firstheaderBorderBelowCB->setEnabled(longtabular && firstheaderStatusCB->isChecked()); - footerStatusCB->setEnabled(longtabular); + footerStatusCB->setEnabled(longtabular + && (footerStatusCB->isChecked() ? + funcEnabled(Tabular::UNSET_LTFOOT) : + funcEnabled(Tabular::SET_LTFOOT))); footerBorderAboveCB->setEnabled(longtabular && footerBorderAboveCB->isChecked()); footerBorderBelowCB->setEnabled(longtabular @@ -256,7 +328,9 @@ void GuiTabular::checkEnabled() // check if setting a last footer is allowed // additionally check lastfooterNoContentsCB because when this is // the case a last footer makes no sense - lastfooterStatusCB->setEnabled(funcEnabled(Tabular::SET_LTLASTFOOT) + lastfooterStatusCB->setEnabled((lastfooterStatusCB->isChecked() ? + funcEnabled(Tabular::UNSET_LTLASTFOOT) : + funcEnabled(Tabular::SET_LTLASTFOOT)) && longtabular && !lastfooterNoContentsCB->isChecked()); lastfooterBorderAboveCB->setEnabled(longtabular && lastfooterBorderAboveCB->isChecked()); @@ -266,21 +340,52 @@ void GuiTabular::checkEnabled() captionStatusCB->setEnabled(funcEnabled(Tabular::TOGGLE_LTCAPTION) && longtabular); - multicolumnCB->setEnabled(funcEnabled(Tabular::MULTICOLUMN)); - multirowCB->setEnabled(funcEnabled(Tabular::MULTIROW)); - multirowOffsetED->setEnabled(multirowCB->isChecked()); - multirowOffsetUnitCB->setEnabled(multirowCB->isChecked()); + multicolumnCB->setEnabled(funcEnabled(Tabular::MULTICOLUMN) + && !dalign && !multirowCB->isChecked()); + multirowCB->setEnabled(funcEnabled(Tabular::MULTIROW) + && !dalign && !multicolumnCB->isChecked()); + bool const enable_mr = multirowCB->isChecked(); + multirowOffsetLA->setEnabled(enable_mr); + multirowOffsetED->setEnabled(enable_mr); + multirowOffsetUnitLC->setEnabled(enable_mr); + + // Vertical lines cannot be set in formal tables + borders->setLeftEnabled(!booktabsRB->isChecked()); + borders->setRightEnabled(!booktabsRB->isChecked()); + // Trimming is only allowed in booktabs and if the line is set + int const row = tabularRowED->text().toInt(); + borders->setTopLeftTrimEnabled(booktabsRB->isChecked() + && borders->topLineSet() + && row > 1); + borders->setTopRightTrimEnabled(booktabsRB->isChecked() + && borders->topLineSet() + && row > 1); + borders->setBottomLeftTrimEnabled(booktabsRB->isChecked() + && borders->bottomLineSet() + && row < lastrow_); + borders->setBottomRightTrimEnabled(booktabsRB->isChecked() + && borders->bottomLineSet() + && row < lastrow_); +} + +void GuiTabular::checkEnabled() +{ + enableWidgets(); changed(); } void GuiTabular::borderSet_clicked() { - borders->setTop(true); - borders->setBottom(true); - borders->setLeft(true); - borders->setRight(true); + borders->setTop(GuiSetBorder::LINE_SET); + borders->setBottom(GuiSetBorder::LINE_SET); + borders->setLeft(GuiSetBorder::LINE_SET); + borders->setRight(GuiSetBorder::LINE_SET); + borders->setTopLeftTrim(GuiSetBorder::LINE_SET); + borders->setBottomLeftTrim(GuiSetBorder::LINE_SET); + borders->setTopRightTrim(GuiSetBorder::LINE_SET); + borders->setBottomRightTrim(GuiSetBorder::LINE_SET); // repaint the setborder widget borders->update(); checkEnabled(); @@ -289,16 +394,39 @@ void GuiTabular::borderSet_clicked() void GuiTabular::borderUnset_clicked() { - borders->setTop(false); - borders->setBottom(false); - borders->setLeft(false); - borders->setRight(false); + borders->setTop(GuiSetBorder::LINE_UNSET); + borders->setBottom(GuiSetBorder::LINE_UNSET); + borders->setLeft(GuiSetBorder::LINE_UNSET); + borders->setRight(GuiSetBorder::LINE_UNSET); + borders->setTopLeftTrim(GuiSetBorder::LINE_UNSET); + borders->setBottomLeftTrim(GuiSetBorder::LINE_UNSET); + borders->setTopRightTrim(GuiSetBorder::LINE_UNSET); + borders->setBottomRightTrim(GuiSetBorder::LINE_UNSET); + // repaint the setborder widget + borders->update(); + checkEnabled(); +} + + +void GuiTabular::booktabs_toggled(bool const check) +{ + // when switching from formal, restore the left/right lines + if (!check) { + borders->setLeft(orig_leftborder_); + borders->setRight(orig_rightborder_); + } // repaint the setborder widget borders->update(); checkEnabled(); } +void GuiTabular::nonbooktabs_toggled(bool const check) +{ + booktabs_toggled(!check); +} + + static void setParam(string & param_str, Tabular::Feature f, string const & arg = string()) { param_str += ' '; @@ -311,7 +439,7 @@ void GuiTabular::setHAlign(string & param_str) const Tabular::Feature num = Tabular::ALIGN_LEFT; Tabular::Feature multi_num = Tabular::M_ALIGN_LEFT; string const align = - fromqstr(hAlignCB->itemData(hAlignCB->currentIndex()).toString()); + fromqstr(hAlignCO->itemData(hAlignCO->currentIndex()).toString()); if (align == "left") { num = Tabular::ALIGN_LEFT; multi_num = Tabular::M_ALIGN_LEFT; @@ -338,7 +466,7 @@ void GuiTabular::setHAlign(string & param_str) const void GuiTabular::setVAlign(string & param_str) const { - int const align = vAlignCB->currentIndex(); + int const align = vAlignCO->currentIndex(); enum VALIGN { TOP, MIDDLE, BOTTOM }; VALIGN v = TOP; @@ -374,7 +502,7 @@ void GuiTabular::setVAlign(string & param_str) const void GuiTabular::setTableAlignment(string & param_str) const { - int const align = TableAlignCB->currentIndex(); + int const align = TableAlignCO->currentIndex(); switch (align) { case 0: setParam(param_str, Tabular::TABULAR_VALIGN_TOP); break; @@ -388,25 +516,41 @@ void GuiTabular::setTableAlignment(string & param_str) const docstring GuiTabular::dialogToParams() const { - // FIXME: We should use Tabular directly. string param_str = "tabular"; + // table width + string tabwidth = widgetsToLength(tabularWidthED, tabularWidthUnitLC); + if (tabwidth.empty()) + tabwidth = "0pt"; + setParam(param_str, Tabular::SET_TABULAR_WIDTH, tabwidth); + // apply the fixed width values // this must be done before applying the column alignment // because its value influences the alignment of multirow cells - string width = widgetsToLength(widthED, widthUnitCB); - if (width.empty()) + string width = widgetsToLength(columnWidthED, columnWidthUnitLC); + if (width.empty() || columnTypeCO->currentIndex() != 2) width = "0pt"; if (multicolumnCB->isChecked()) setParam(param_str, Tabular::SET_MPWIDTH, width); else setParam(param_str, Tabular::SET_PWIDTH, width); + bool const varwidth = specialAlignmentED->text().isEmpty() + && columnTypeCO->currentIndex() == 1; + if (varwidth) + setParam(param_str, Tabular::TOGGLE_VARWIDTH_COLUMN, "on"); + else + setParam(param_str, Tabular::TOGGLE_VARWIDTH_COLUMN, "off"); + // apply the column alignment - setHAlign(param_str); + // multirows inherit the alignment from the column; if a column width + // is set, multirows are always left-aligned so that in this case + // its alignment must not be applied (see bug #8084) + if (!(multirowCB->isChecked() && width != "0pt")) + setHAlign(param_str); // SET_DECIMAL_POINT must come after setHAlign() (ALIGN_DECIMAL) - string decimal_point = fromqstr(decimalPointLE->text()); + string decimal_point = fromqstr(decimalPointED->text()); if (decimal_point.empty()) decimal_point = lyxrc.default_decimal_point; setParam(param_str, Tabular::SET_DECIMAL_POINT, decimal_point); @@ -430,7 +574,7 @@ docstring GuiTabular::dialogToParams() const case 2: if (!topspaceED->text().isEmpty()) setParam(param_str, Tabular::SET_TOP_SPACE, - widgetsToLength(topspaceED, topspaceUnitCB)); + widgetsToLength(topspaceED, topspaceUnitLC)); break; } @@ -446,7 +590,7 @@ docstring GuiTabular::dialogToParams() const if (!bottomspaceED->text().isEmpty()) setParam(param_str, Tabular::SET_BOTTOM_SPACE, widgetsToLength(bottomspaceED, - bottomspaceUnitCB)); + bottomspaceUnitLC)); break; } @@ -462,31 +606,53 @@ docstring GuiTabular::dialogToParams() const if (!interlinespaceED->text().isEmpty()) setParam(param_str, Tabular::SET_INTERLINE_SPACE, widgetsToLength(interlinespaceED, - interlinespaceUnitCB)); + interlinespaceUnitLC)); break; } // - if (borders->getTop() && borders->getBottom() && borders->getLeft() - && borders->getRight()) + if (resetFormalCB->isChecked()) + setParam(param_str, Tabular::RESET_FORMAL_DEFAULT); + else if (borders->topLineSet() && borders->bottomLineSet() && borders->leftLineSet() + && borders->rightLineSet()) setParam(param_str, Tabular::SET_ALL_LINES); - else if (!borders->getTop() && !borders->getBottom() && !borders->getLeft() - && !borders->getRight()) + else if (borders->topLineUnset() && borders->bottomLineUnset() && borders->leftLineUnset() + && borders->rightLineUnset()) setParam(param_str, Tabular::UNSET_ALL_LINES); else { - setParam(param_str, Tabular::SET_LINE_LEFT, - borders->getLeft() ? "true" : "false"); - setParam(param_str, Tabular::SET_LINE_RIGHT, - borders->getRight() ? "true" : "false"); - setParam(param_str, Tabular::SET_LINE_TOP, - borders->getTop() ? "true" : "false"); - setParam(param_str, Tabular::SET_LINE_BOTTOM, - borders->getBottom() ? "true" : "false"); + if (borders->getLeft() != GuiSetBorder::LINE_UNDECIDED) + setParam(param_str, Tabular::SET_LINE_LEFT, + borders->leftLineSet() ? "true" : "false"); + if (borders->getRight() != GuiSetBorder::LINE_UNDECIDED) + setParam(param_str, Tabular::SET_LINE_RIGHT, + borders->rightLineSet() ? "true" : "false"); + if (borders->getTop() != GuiSetBorder::LINE_UNDECIDED) + setParam(param_str, Tabular::SET_LINE_TOP, + borders->topLineSet() ? "true" : "false"); + if (borders->getBottom() != GuiSetBorder::LINE_UNDECIDED) + setParam(param_str, Tabular::SET_LINE_BOTTOM, + borders->bottomLineSet() ? "true" : "false"); } + if (borders->topLineLTSet()) + setParam(param_str, Tabular::SET_LTRIM_TOP, "false"); + else if (borders->topLineLTUnset()) + setParam(param_str, Tabular::SET_LTRIM_TOP, "true"); + if (borders->topLineRTSet()) + setParam(param_str, Tabular::SET_RTRIM_TOP, "false"); + else if (borders->topLineRTUnset()) + setParam(param_str, Tabular::SET_RTRIM_TOP, "true"); + if (borders->bottomLineLTSet()) + setParam(param_str, Tabular::SET_LTRIM_BOTTOM, "false"); + else if (borders->bottomLineLTUnset()) + setParam(param_str, Tabular::SET_LTRIM_BOTTOM, "true"); + if (borders->bottomLineRTSet()) + setParam(param_str, Tabular::SET_RTRIM_BOTTOM, "false"); + else if (borders->bottomLineRTUnset()) + setParam(param_str, Tabular::SET_RTRIM_BOTTOM, "true"); // apply the special alignment string special = fromqstr(specialAlignmentED->text()); - if (special.empty()) + if (support::trim(special).empty()) special = "none"; if (multicolumnCB->isChecked()) setParam(param_str, Tabular::SET_SPECIAL_MULTICOLUMN, special); @@ -500,7 +666,7 @@ docstring GuiTabular::dialogToParams() const setParam(param_str, Tabular::UNSET_MULTICOLUMN); // apply the multirow offset - string mroffset = widgetsToLength(multirowOffsetED, multirowOffsetUnitCB); + string mroffset = widgetsToLength(multirowOffsetED, multirowOffsetUnitLC); if (mroffset.empty()) mroffset = "0pt"; if (multirowCB->isChecked()) @@ -510,16 +676,18 @@ docstring GuiTabular::dialogToParams() const setParam(param_str, Tabular::SET_MULTIROW); else setParam(param_str, Tabular::UNSET_MULTIROW); - // + // store the table rotation angle + string const tabular_angle = convert(rotateTabularAngleSB->value()); if (rotateTabularCB->isChecked()) - setParam(param_str, Tabular::SET_ROTATE_TABULAR); + setParam(param_str, Tabular::SET_ROTATE_TABULAR, tabular_angle); else - setParam(param_str, Tabular::UNSET_ROTATE_TABULAR); - // + setParam(param_str, Tabular::UNSET_ROTATE_TABULAR, tabular_angle); + // store the cell rotation angle + string const cell_angle = convert(rotateCellAngleSB->value()); if (rotateCellCB->isChecked()) - setParam(param_str, Tabular::SET_ROTATE_CELL); + setParam(param_str, Tabular::SET_ROTATE_CELL, cell_angle); else - setParam(param_str, Tabular::UNSET_ROTATE_CELL); + setParam(param_str, Tabular::UNSET_ROTATE_CELL, cell_angle); // if (longTabularCB->isChecked()) setParam(param_str, Tabular::SET_LONGTABULAR); @@ -528,6 +696,8 @@ docstring GuiTabular::dialogToParams() const // if (newpageCB->isChecked()) setParam(param_str, Tabular::SET_LTNEWPAGE); + else + setParam(param_str, Tabular::UNSET_LTNEWPAGE); // if (captionStatusCB->isChecked()) setParam(param_str, Tabular::SET_LTCAPTION); @@ -634,6 +804,18 @@ static docstring getAlignSpecial(Tabular const & t, size_t cell, int what) } +GuiSetBorder::BorderState GuiTabular::borderState(GuiSetBorder::BorderState bs, + bool const line) +{ + if (bs == GuiSetBorder::LINE_UNDEF) + bs = line ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET; + else if ((bs == GuiSetBorder::LINE_SET && !line) + || (bs == GuiSetBorder::LINE_UNSET && line)) + bs = GuiSetBorder::LINE_UNDECIDED; + return bs; +} + + void GuiTabular::paramsToDialog(Inset const * inset) { InsetTabular const * itab = static_cast(inset); @@ -648,6 +830,7 @@ void GuiTabular::paramsToDialog(Inset const * inset) tabularRowED->setText(QString::number(row + 1)); tabularColumnED->setText(QString::number(col + 1)); + lastrow_ = int(tabular.nrows()); bool const multicol = tabular.isMultiColumn(cell); multicolumnCB->setChecked(multicol); @@ -655,15 +838,82 @@ void GuiTabular::paramsToDialog(Inset const * inset) bool const multirow = tabular.isMultiRow(cell); multirowCB->setChecked(multirow); - rotateCellCB->setChecked(tabular.getRotateCell(cell)); - rotateTabularCB->setChecked(tabular.rotate); + rotateCellCB->setChecked(tabular.getRotateCell(cell) != 0); + if (rotateCellCB->isChecked()) { + if (tabular.getRotateCell(cell) != 0) + rotateCellAngleSB->setValue(tabular.getRotateCell(cell)); + else + rotateCellAngleSB->setValue(90); + } longTabularCB->setChecked(tabular.is_long_tabular); - borders->setTop(tabular.topLine(cell)); - borders->setBottom(tabular.bottomLine(cell)); - borders->setLeft(tabular.leftLine(cell)); - borders->setRight(tabular.rightLine(cell)); + rotateTabularCB->setChecked(tabular.rotate != 0); + if (rotateTabularCB->isChecked()) { + if (longTabularCB->isChecked()) + rotateTabularAngleSB->setValue(90); + else + rotateTabularAngleSB->setValue(tabular.rotate != 0 ? tabular.rotate : 90); + } + + // In what follows, we check the borders of all selected cells, + // and if there are diverging settings, we use the LINE_UNDECIDED + // border status. + GuiSetBorder::BorderState ltop = GuiSetBorder::LINE_UNDEF; + GuiSetBorder::BorderState lbottom = GuiSetBorder::LINE_UNDEF; + GuiSetBorder::BorderState lleft = GuiSetBorder::LINE_UNDEF; + GuiSetBorder::BorderState lright = GuiSetBorder::LINE_UNDEF; + GuiSetBorder::BorderState ltop_ltrim = GuiSetBorder::LINE_UNDEF; + GuiSetBorder::BorderState ltop_rtrim = GuiSetBorder::LINE_UNDEF; + GuiSetBorder::BorderState lbottom_ltrim = GuiSetBorder::LINE_UNDEF; + GuiSetBorder::BorderState lbottom_rtrim = GuiSetBorder::LINE_UNDEF; + CursorSlice const & beg = bv->cursor().selBegin(); + CursorSlice const & end = bv->cursor().selEnd(); + if (beg != end) { + Tabular::col_type cs = tabular.cellColumn(beg.idx()); + Tabular::col_type ce = tabular.cellColumn(end.idx()); + if (cs > ce) + swap(cs, ce); + Tabular::row_type rs = tabular.cellRow(beg.idx()); + Tabular::row_type re = tabular.cellRow(end.idx()); + if (rs > re) + swap(rs, re); + for (Tabular::row_type r = rs; r <= re; ++r) + for (Tabular::col_type c = cs; c <= ce; ++c) { + idx_type const cc = tabular.cellIndex(r, c); + ltop = borderState(ltop, tabular.topLine(cc)); + lbottom = borderState(lbottom, tabular.bottomLine(cc)); + lleft = borderState(lleft, tabular.leftLine(cc)); + lright = borderState(lright, tabular.rightLine(cc)); + ltop_ltrim = borderState(ltop_ltrim, !tabular.topLineTrim(cc).first); + ltop_rtrim = borderState(ltop_rtrim, !tabular.topLineTrim(cc).second); + lbottom_ltrim = borderState(lbottom_ltrim, !tabular.bottomLineTrim(cc).first); + lbottom_rtrim = borderState(lbottom_rtrim, !tabular.bottomLineTrim(cc).second); + // store left/right borders for the case of formal/nonformal switch + orig_leftborder_ = borderState(lleft, tabular.leftLine(cc, true)); + orig_rightborder_ = borderState(lright, tabular.rightLine(cc, true)); + } + } else { + ltop = tabular.topLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET; + lbottom = tabular.bottomLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET; + lleft = tabular.leftLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET; + lright = tabular.rightLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET; + ltop_ltrim = tabular.topLineTrim(cell).first ? GuiSetBorder::LINE_UNSET : GuiSetBorder::LINE_SET; + ltop_rtrim = tabular.topLineTrim(cell).second ? GuiSetBorder::LINE_UNSET : GuiSetBorder::LINE_SET; + lbottom_ltrim = tabular.bottomLineTrim(cell).first ? GuiSetBorder::LINE_UNSET : GuiSetBorder::LINE_SET; + lbottom_rtrim = tabular.bottomLineTrim(cell).second ? GuiSetBorder::LINE_UNSET : GuiSetBorder::LINE_SET; + // store left/right borders for the case of formal/nonformal switch + orig_leftborder_ = tabular.leftLine(cell, true) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET; + orig_rightborder_ = tabular.rightLine(cell, true) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET; + } + borders->setTop(ltop); + borders->setBottom(lbottom); + borders->setLeft(lleft); + borders->setRight(lright); + borders->setTopLeftTrim(ltop_ltrim); + borders->setTopRightTrim(ltop_rtrim); + borders->setBottomLeftTrim(lbottom_ltrim); + borders->setBottomRightTrim(lbottom_rtrim); // repaint the setborder widget borders->update(); @@ -671,6 +921,15 @@ void GuiTabular::paramsToDialog(Inset const * inset) /////////////////////////////////// // Set width and alignment + + Length const tabwidth = tabular.tabularWidth(); + if (tabwidth.zero() + && !(tabularWidthED->hasFocus() && tabularWidthED->text() == "0")) + tabularWidthED->clear(); + else + lengthToWidgets(tabularWidthED, tabularWidthUnitLC, + tabwidth.asString(), default_unit); + Length pwidth; docstring special; if (multicol) { @@ -682,23 +941,31 @@ void GuiTabular::paramsToDialog(Inset const * inset) Tabular::SET_SPECIAL_COLUMN); pwidth = getColumnPWidth(tabular, cell); } + bool const varwidth = tabular.column_info[tabular.cellColumn(cell)].varwidth; + if (varwidth) + columnTypeCO->setCurrentIndex(1); string colwidth; - if (pwidth.zero()) - widthED->clear(); - else { + if (pwidth.zero() + && !(columnWidthED->hasFocus() && columnWidthED->text() == "0")) { + columnWidthED->clear(); + if (!varwidth) + columnTypeCO->setCurrentIndex(0); + } else { colwidth = pwidth.asString(); - lengthToWidgets(widthED, widthUnitCB, + lengthToWidgets(columnWidthED, columnWidthUnitLC, colwidth, default_unit); + columnTypeCO->setCurrentIndex(2); } Length mroffset; if (multirow) mroffset = getMROffset(tabular, cell); string offset; - if (mroffset.zero()) + if (mroffset.zero() + && !(multirowOffsetED->hasFocus() && multirowOffsetED->text() == "0")) multirowOffsetED->clear(); else { offset = mroffset.asString(); - lengthToWidgets(multirowOffsetED, multirowOffsetUnitCB, + lengthToWidgets(multirowOffsetED, multirowOffsetUnitLC, offset, default_unit); } specialAlignmentED->setText(toqstr(special)); @@ -716,7 +983,7 @@ void GuiTabular::paramsToDialog(Inset const * inset) } else { topspaceCO->setCurrentIndex(2); lengthToWidgets(topspaceED, - topspaceUnitCB, + topspaceUnitLC, tabular.row_info[row].top_space.asString(), default_unit); } @@ -729,7 +996,7 @@ void GuiTabular::paramsToDialog(Inset const * inset) } else { bottomspaceCO->setCurrentIndex(2); lengthToWidgets(bottomspaceED, - bottomspaceUnitCB, + bottomspaceUnitLC, tabular.row_info[row].bottom_space.asString(), default_unit); } @@ -742,19 +1009,19 @@ void GuiTabular::paramsToDialog(Inset const * inset) } else { interlinespaceCO->setCurrentIndex(2); lengthToWidgets(interlinespaceED, - interlinespaceUnitCB, + interlinespaceUnitLC, tabular.row_info[row].interline_space.asString(), default_unit); } - hAlignCB->clear(); - hAlignCB->addItem(qt_("Left"), toqstr("left")); - hAlignCB->addItem(qt_("Center"), toqstr("center")); - hAlignCB->addItem(qt_("Right"), toqstr("right")); + hAlignCO->clear(); + hAlignCO->addItem(qt_("Left"), toqstr("left")); + hAlignCO->addItem(qt_("Center"), toqstr("center")); + hAlignCO->addItem(qt_("Right"), toqstr("right")); if (!multicol && !pwidth.zero()) - hAlignCB->addItem(qt_("Justified"), toqstr("justified")); - if (!multicol) - hAlignCB->addItem(qt_("At Decimal Separator"), toqstr("decimal")); + hAlignCO->addItem(qt_("Justified"), toqstr("justified")); + if (!multicol && !multirow) + hAlignCO->addItem(qt_("At Decimal Separator"), toqstr("decimal")); string align; switch (tabular.getAlignment(cell)) { @@ -775,7 +1042,7 @@ void GuiTabular::paramsToDialog(Inset const * inset) } case LYX_ALIGN_DECIMAL: { - if (!multicol) + if (!multicol && !multirow) align = "decimal"; break; } @@ -783,13 +1050,13 @@ void GuiTabular::paramsToDialog(Inset const * inset) // we should never end up here break; } - hAlignCB->setCurrentIndex(hAlignCB->findData(toqstr(align))); + hAlignCO->setCurrentIndex(hAlignCO->findData(toqstr(align))); // QString decimal_point = toqstr(tabular.column_info[col].decimal_point); if (decimal_point.isEmpty()) decimal_point = toqstr(from_utf8(lyxrc.default_decimal_point)); - decimalPointLE->setText(decimal_point); + decimalPointED->setText(decimal_point); int valign = 0; switch (tabular.getVAlignment(cell)) { @@ -808,7 +1075,7 @@ void GuiTabular::paramsToDialog(Inset const * inset) } if (pwidth.zero()) valign = 0; - vAlignCB->setCurrentIndex(valign); + vAlignCO->setCurrentIndex(valign); int tableValign = 1; switch (tabular.tabular_valignment) { @@ -825,7 +1092,7 @@ void GuiTabular::paramsToDialog(Inset const * inset) tableValign = 0; break; } - TableAlignCB->setCurrentIndex(tableValign); + TableAlignCO->setCurrentIndex(tableValign); if (!tabular.is_long_tabular) { headerStatusCB->setChecked(false); @@ -850,7 +1117,7 @@ void GuiTabular::paramsToDialog(Inset const * inset) return; } else { // longtables cannot have a vertical alignment - TableAlignCB->setCurrentIndex(Tabular::LYX_VALIGN_MIDDLE); + TableAlignCO->setCurrentIndex(Tabular::LYX_VALIGN_MIDDLE); } switch (tabular.longtabular_alignment) { case Tabular::LYX_LONGTABULAR_ALIGN_LEFT: @@ -931,10 +1198,55 @@ void GuiTabular::paramsToDialog(Inset const * inset) } +bool GuiTabular::checkWidgets(bool readonly) const +{ + tabularRowED->setReadOnly(readonly); + tabularColumnED->setReadOnly(readonly); + tabularWidthED->setReadOnly(readonly); + specialAlignmentED->setReadOnly(readonly); + columnWidthED->setReadOnly(readonly); + multirowOffsetED->setReadOnly(readonly); + decimalPointED->setReadOnly(readonly); + + if (readonly) { + multicolumnCB->setEnabled(false); + multirowCB->setEnabled(false); + rotateCellCB->setEnabled(false); + rotateCellAngleSB->setEnabled(false); + rotateTabularCB->setEnabled(false); + rotateTabularAngleSB->setEnabled(false); + longTabularCB->setEnabled(false); + borders->setEnabled(false); + tabularWidthUnitLC->setEnabled(false); + columnWidthUnitLC->setEnabled(false); + columnTypeCO->setEnabled(false); + multirowOffsetUnitLC->setEnabled(false); + setBordersGB->setEnabled(false); + allBordersGB->setEnabled(false); + borderStyleGB->setEnabled(false); + booktabsRB->setEnabled(false); + topspaceCO->setEnabled(false); + topspaceUnitLC->setEnabled(false); + bottomspaceCO->setEnabled(false); + bottomspaceUnitLC->setEnabled(false); + interlinespaceCO->setEnabled(false); + interlinespaceUnitLC->setEnabled(false); + hAlignCO->setEnabled(false); + vAlignCO->setEnabled(false); + TableAlignCO->setEnabled(false); + longtableGB->setEnabled(false); + alignmentGB->setEnabled(false); + } else + enableWidgets(); + + return InsetParamsWidget::checkWidgets(); +} + + bool GuiTabular::funcEnabled(Tabular::Feature f) const { - string cmd = "tabular " + featureAsString(f); - return getStatus(FuncRequest(LFUN_INSET_MODIFY, cmd)).enabled(); + FuncRequest r(LFUN_INSET_MODIFY, "tabular for-dialog" + featureAsString(f)); + return getStatus(r).enabled(); }