From 2e65b8e75e16525f84fb53ca1ee179bfe8169b7f Mon Sep 17 00:00:00 2001 From: Juergen Spitzmueller Date: Tue, 24 Jul 2018 13:49:27 +0200 Subject: [PATCH] Implement tri-state in GuiSetBorder A new UNDECIDED state is used if multiple cells with differing border settings are selected. This prevents additional borders to be set without being asked. Fixes: #10010 (cherry picked from commit 99aefa5fd2c2184f0a67930046956df7d8f611df) --- src/frontends/qt4/GuiSetBorder.cpp | 98 ++++++++++++++++++++------- src/frontends/qt4/GuiSetBorder.h | 56 ++++++++++------ src/frontends/qt4/GuiTabular.cpp | 104 +++++++++++++++++++++-------- src/frontends/qt4/GuiTabular.h | 3 + status.23x | 7 +- 5 files changed, 194 insertions(+), 74 deletions(-) diff --git a/src/frontends/qt4/GuiSetBorder.cpp b/src/frontends/qt4/GuiSetBorder.cpp index 80a7d74c4b..f35a17df2b 100644 --- a/src/frontends/qt4/GuiSetBorder.cpp +++ b/src/frontends/qt4/GuiSetBorder.cpp @@ -72,29 +72,29 @@ void GuiSetBorder::mousePressEvent(QMouseEvent * e) if (e->y() > e->x()) { if (e->y() < height() - e->x()) { if (left_.enabled) { - setLeft(!left_.set); + setLeft(left_.set == LINE_SET ? LINE_UNSET : LINE_SET); // emit signal - leftSet(left_.set); + leftSet(); } } else { if (bottom_.enabled) { - setBottom(!bottom_.set); + setBottom(bottom_.set == LINE_SET ? LINE_UNSET : LINE_SET); // emit signal - bottomSet(bottom_.set); + bottomSet(); } } } else { if (e->y() < height() - e->x()) { if (top_.enabled) { - setTop(!top_.set); + setTop(top_.set == LINE_SET ? LINE_UNSET : LINE_SET); // emit signal - topSet(top_.set); + topSet(); } } else { if (right_.enabled) { - setRight(!right_.set); + setRight(right_.set == LINE_SET ? LINE_UNSET : LINE_SET); // emit signal - rightSet(right_.set); + rightSet(); } } } @@ -115,36 +115,84 @@ void GuiSetBorder::drawLine(QColor const & col, int x, int y, int x2, int y2) } -void GuiSetBorder::drawLeft(bool draw) +void GuiSetBorder::drawLeft(BorderState draw) { - QColor col(draw ? Qt::black : Qt::white); + QColor col; + switch (draw) { + case LINE_SET: + col = Qt::black; + break; + case LINE_UNSET: + col = Qt::white; + break; + case LINE_UNDECIDED: + case LINE_UNDEF: + col = Qt::lightGray; + break; + } if (!left_.enabled) col = QColor(Qt::lightGray); drawLine(col, m + l, m + l + 2, m + l, h - m - l - 1); } -void GuiSetBorder::drawRight(bool draw) +void GuiSetBorder::drawRight(BorderState draw) { - QColor col(draw ? Qt::black : Qt::white); + QColor col; + switch (draw) { + case LINE_SET: + col = Qt::black; + break; + case LINE_UNSET: + col = Qt::white; + break; + case LINE_UNDECIDED: + case LINE_UNDEF: + col = Qt::lightGray; + break; + } if (!right_.enabled) col = QColor(Qt::lightGray); drawLine(col, h - m - l + 1, m + l + 2, h - m - l + 1, h - m - l - 1); } -void GuiSetBorder::drawTop(bool draw) +void GuiSetBorder::drawTop(BorderState draw) { - QColor col(draw ? Qt::black : Qt::white); + QColor col; + switch (draw) { + case LINE_SET: + col = Qt::black; + break; + case LINE_UNSET: + col = Qt::white; + break; + case LINE_UNDECIDED: + case LINE_UNDEF: + col = Qt::lightGray; + break; + } if (!top_.enabled) col = QColor(Qt::lightGray); drawLine(col, m + l + 2, m + l, w - m - l - 1, m + l); } -void GuiSetBorder::drawBottom(bool draw) +void GuiSetBorder::drawBottom(BorderState draw) { - QColor col(draw ? Qt::black : Qt::white); + QColor col; + switch (draw) { + case LINE_SET: + col = Qt::black; + break; + case LINE_UNSET: + col = Qt::white; + break; + case LINE_UNDECIDED: + case LINE_UNDEF: + col = Qt::lightGray; + break; + } if (!bottom_.enabled) col = QColor(Qt::lightGray); drawLine(col, m + l + 2, w - m - l + 1, w - m - l - 1, w - m - l + 1); @@ -179,35 +227,35 @@ void GuiSetBorder::setBottomEnabled(bool enabled) } -void GuiSetBorder::setLeft(bool border) +void GuiSetBorder::setLeft(BorderState border) { left_.set = border; drawLeft(border); } -void GuiSetBorder::setRight(bool border) +void GuiSetBorder::setRight(BorderState border) { right_.set = border; drawRight(border); } -void GuiSetBorder::setTop(bool border) +void GuiSetBorder::setTop(BorderState border) { top_.set = border; drawTop(border); } -void GuiSetBorder::setBottom(bool border) +void GuiSetBorder::setBottom(BorderState border) { bottom_.set = border; drawBottom(border); } -void GuiSetBorder::setAll(bool border) +void GuiSetBorder::setAll(BorderState border) { setLeft(border); setRight(border); @@ -216,25 +264,25 @@ void GuiSetBorder::setAll(bool border) } -bool GuiSetBorder::getLeft() +GuiSetBorder::BorderState GuiSetBorder::getLeft() { return left_.set; } -bool GuiSetBorder::getRight() +GuiSetBorder::BorderState GuiSetBorder::getRight() { return right_.set; } -bool GuiSetBorder::getTop() +GuiSetBorder::BorderState GuiSetBorder::getTop() { return top_.set; } -bool GuiSetBorder::getBottom() +GuiSetBorder::BorderState GuiSetBorder::getBottom() { return bottom_.set; } diff --git a/src/frontends/qt4/GuiSetBorder.h b/src/frontends/qt4/GuiSetBorder.h index e064452b84..7230e4d11b 100644 --- a/src/frontends/qt4/GuiSetBorder.h +++ b/src/frontends/qt4/GuiSetBorder.h @@ -28,16 +28,34 @@ class GuiSetBorder : public QWidget public: GuiSetBorder(QWidget * parent = 0, Qt::WindowFlags fl = 0); - bool getLeft(); - bool getRight(); - bool getTop(); - bool getBottom(); + // We need tristate for multi-cell selection + enum BorderState { + LINE_UNSET, + LINE_SET, + LINE_UNDECIDED, + LINE_UNDEF + }; + + BorderState getLeft(); + BorderState getRight(); + BorderState getTop(); + BorderState getBottom(); + + bool leftLineSet() { return getLeft() == LINE_SET; } + bool rightLineSet() { return getRight() == LINE_SET; } + bool topLineSet() { return getTop() == LINE_SET; } + bool bottomLineSet() { return getBottom() == LINE_SET; } + + bool leftLineUnset() { return getLeft() == LINE_UNSET; } + bool rightLineUnset() { return getRight() == LINE_UNSET; } + bool topLineUnset() { return getTop() == LINE_UNSET; } + bool bottomLineUnset() { return getBottom() == LINE_UNSET; } Q_SIGNALS: - void rightSet(bool); - void leftSet(bool); - void topSet(bool); - void bottomSet(bool); + void rightSet(); + void leftSet(); + void topSet(); + void bottomSet(); void clicked(); public Q_SLOTS: @@ -45,11 +63,11 @@ public Q_SLOTS: void setRightEnabled(bool); void setTopEnabled(bool); void setBottomEnabled(bool); - void setLeft(bool); - void setRight(bool); - void setTop(bool); - void setBottom(bool); - void setAll(bool); + void setLeft(BorderState); + void setRight(BorderState); + void setTop(BorderState); + void setBottom(BorderState); + void setAll(BorderState); protected: void mousePressEvent(QMouseEvent * e); @@ -60,15 +78,15 @@ private: void drawLine(QColor const & col, int x, int y, int x2, int y2); - void drawLeft(bool); - void drawRight(bool); - void drawTop(bool); - void drawBottom(bool); + void drawLeft(BorderState); + void drawRight(BorderState); + void drawTop(BorderState); + void drawBottom(BorderState); class Border { public: - Border() : set(true), enabled(true) {} - bool set; + Border() : set(LINE_SET), enabled(true) {} + BorderState set; bool enabled; }; diff --git a/src/frontends/qt4/GuiTabular.cpp b/src/frontends/qt4/GuiTabular.cpp index 645b7744c6..63cd3836c0 100644 --- a/src/frontends/qt4/GuiTabular.cpp +++ b/src/frontends/qt4/GuiTabular.cpp @@ -136,13 +136,13 @@ GuiTabular::GuiTabular(QWidget * parent) this, SLOT(checkEnabled())); connect(columnWidthUnitLC, SIGNAL(selectionChanged(lyx::Length::UNIT)), this, SLOT(checkEnabled())); - connect(borders, SIGNAL(topSet(bool)), + connect(borders, SIGNAL(topSet()), this, SLOT(checkEnabled())); - connect(borders, SIGNAL(bottomSet(bool)), + connect(borders, SIGNAL(bottomSet()), this, SLOT(checkEnabled())); - connect(borders, SIGNAL(rightSet(bool)), + connect(borders, SIGNAL(rightSet()), this, SLOT(checkEnabled())); - connect(borders, SIGNAL(leftSet(bool)), + connect(borders, SIGNAL(leftSet()), this, SLOT(checkEnabled())); connect(rotateTabularCB, SIGNAL(clicked()), this, SLOT(checkEnabled())); @@ -343,10 +343,10 @@ void GuiTabular::checkEnabled() 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); // repaint the setborder widget borders->update(); checkEnabled(); @@ -355,10 +355,10 @@ 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); // repaint the setborder widget borders->update(); checkEnabled(); @@ -542,21 +542,25 @@ docstring GuiTabular::dialogToParams() const } // - if (borders->getTop() && borders->getBottom() && borders->getLeft() - && borders->getRight()) + 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"); } // apply the special alignment @@ -713,6 +717,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); @@ -752,10 +768,42 @@ void GuiTabular::paramsToDialog(Inset const * inset) rotateTabularAngleSB->setValue(tabular.rotate != 0 ? tabular.rotate : 90); } - borders->setTop(tabular.topLine(cell)); - borders->setBottom(tabular.bottomLine(cell)); - borders->setLeft(tabular.leftLine(cell)); - borders->setRight(tabular.rightLine(cell)); + // 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 lt = GuiSetBorder::LINE_UNDEF; + GuiSetBorder::BorderState lb = GuiSetBorder::LINE_UNDEF; + GuiSetBorder::BorderState ll = GuiSetBorder::LINE_UNDEF; + GuiSetBorder::BorderState lr = 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); + lt = borderState(lt, tabular.topLine(cc)); + lb = borderState(lb, tabular.bottomLine(cc)); + ll = borderState(ll, tabular.leftLine(cc)); + lr = borderState(lr, tabular.rightLine(cc)); + } + } else { + lt = tabular.topLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET; + lb = tabular.bottomLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET; + ll = tabular.leftLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET; + lr = tabular.rightLine(cell) ? GuiSetBorder::LINE_SET : GuiSetBorder::LINE_UNSET; + } + borders->setTop(lt); + borders->setBottom(lb); + borders->setLeft(ll); + borders->setRight(lr); // repaint the setborder widget borders->update(); diff --git a/src/frontends/qt4/GuiTabular.h b/src/frontends/qt4/GuiTabular.h index 20f7681780..2cba4810aa 100644 --- a/src/frontends/qt4/GuiTabular.h +++ b/src/frontends/qt4/GuiTabular.h @@ -61,6 +61,9 @@ private: /// bool funcEnabled(Tabular::Feature f) const; /// + GuiSetBorder::BorderState borderState(GuiSetBorder::BorderState bs, + bool const line); + /// bool firstheader_suppressable_; /// bool lastfooter_suppressable_; diff --git a/status.23x b/status.23x index 1691a9cd95..02edc3f16e 100644 --- a/status.23x +++ b/status.23x @@ -61,8 +61,11 @@ What's new - When cloning a buffer, do not start from a parent if it is not the current master (e.g., when compiling a child alone). -- Disallow paragraph customization in some single-par charstyle insets - (bug 9192). +- Disallow paragraph customization in some single-par charstyle insets + (bug 9192). + +- Fix problems with extra table borders added on table modification + (bug 10010). * USER INTERFACE -- 2.39.5