diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index 75290f55e..34bf5a2f9 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -494,7 +494,12 @@ void QETDiagramEditor::setUpActions() //The texts of the selected symbols, label and notes, as one block at //one of nine points around the symbol: the nine points of the text //alignment dialog. A click places them at the point chosen last. - m_place_texts = new QAction(QET::Icons::AlignRight, tr("Place symbol texts"), this); + const auto chosen_point = []() { + return Qt::Alignment(QSettings().value(QStringLiteral("diagrameditor/place_texts_point"), + int(Qt::AlignLeft | Qt::AlignVCenter)).toInt()); + }; + //The button shows where its click will put the texts + m_place_texts = new QAction(SymbolTextPlacement::icon(chosen_point()), tr("Place symbol texts"), this); m_place_texts->setStatusTip(tr("Place the label and the notes of the selected symbols as one block beside them", "status bar tip")); ShortcutManager::instance().registerAction(m_place_texts, "diagrameditor.place_symbol_texts", tr("Diagram editors"), QKeySequence()); { @@ -503,21 +508,22 @@ void QETDiagramEditor::setUpActions() auto *grid = new QGridLayout(grid_widget); grid->setContentsMargins(6, 6, 6, 6); grid->setSpacing(2); - const struct { Qt::Alignment where; const char *arrow; const char *tip; } points[] = { - {Qt::AlignLeft | Qt::AlignTop, "\u2196", QT_TR_NOOP("Above, left")}, - {Qt::AlignHCenter | Qt::AlignTop, "\u2191", QT_TR_NOOP("Above")}, - {Qt::AlignRight | Qt::AlignTop, "\u2197", QT_TR_NOOP("Above, right")}, - {Qt::AlignLeft | Qt::AlignVCenter, "\u2190", QT_TR_NOOP("Left")}, - {Qt::AlignCenter, "\u25CF", QT_TR_NOOP("On the symbol")}, - {Qt::AlignRight | Qt::AlignVCenter, "\u2192", QT_TR_NOOP("Right")}, - {Qt::AlignLeft | Qt::AlignBottom, "\u2199", QT_TR_NOOP("Below, left")}, - {Qt::AlignHCenter | Qt::AlignBottom, "\u2193", QT_TR_NOOP("Below")}, - {Qt::AlignRight | Qt::AlignBottom, "\u2198", QT_TR_NOOP("Below, right")}}; + const struct { Qt::Alignment where; const char *tip; } points[] = { + {Qt::AlignLeft | Qt::AlignTop, QT_TR_NOOP("Above, left")}, + {Qt::AlignHCenter | Qt::AlignTop, QT_TR_NOOP("Above")}, + {Qt::AlignRight | Qt::AlignTop, QT_TR_NOOP("Above, right")}, + {Qt::AlignLeft | Qt::AlignVCenter, QT_TR_NOOP("Left")}, + {Qt::AlignCenter, QT_TR_NOOP("On the symbol")}, + {Qt::AlignRight | Qt::AlignVCenter, QT_TR_NOOP("Right")}, + {Qt::AlignLeft | Qt::AlignBottom, QT_TR_NOOP("Below, left")}, + {Qt::AlignHCenter | Qt::AlignBottom, QT_TR_NOOP("Below")}, + {Qt::AlignRight | Qt::AlignBottom, QT_TR_NOOP("Below, right")}}; int n = 0; for (const auto &point : points) { auto *button = new QToolButton(grid_widget); - button->setText(QString::fromUtf8(point.arrow)); + button->setIcon(SymbolTextPlacement::icon(point.where)); + button->setIconSize(QSize(24, 24)); button->setToolTip(tr(point.tip)); button->setObjectName(QStringLiteral("place_texts_%1").arg(n)); button->setFixedSize(28, 28); @@ -526,6 +532,7 @@ void QETDiagramEditor::setUpActions() connect(button, &QToolButton::clicked, this, [this, menu, where]() { menu->close(); QSettings().setValue(QStringLiteral("diagrameditor/place_texts_point"), int(where)); + m_place_texts->setIcon(SymbolTextPlacement::icon(where)); placeSymbolTexts(where); }); grid->addWidget(button, n / 3, n % 3); @@ -536,10 +543,8 @@ void QETDiagramEditor::setUpActions() menu->addAction(grid_action); m_place_texts->setMenu(menu); } - connect(m_place_texts, &QAction::triggered, this, [this]() { - const int where = QSettings().value(QStringLiteral("diagrameditor/place_texts_point"), - int(Qt::AlignLeft | Qt::AlignVCenter)).toInt(); - placeSymbolTexts(Qt::Alignment(where)); + connect(m_place_texts, &QAction::triggered, this, [this, chosen_point]() { + placeSymbolTexts(chosen_point()); }); //Duplicate: copy the selection and place it at a configured, diff --git a/sources/symboltextplacement.cpp b/sources/symboltextplacement.cpp index c43ee178e..7dfec5033 100644 --- a/sources/symboltextplacement.cpp +++ b/sources/symboltextplacement.cpp @@ -22,7 +22,11 @@ #include "qetgraphicsitem/element.h" #include "qetgraphicsitem/elementtextitemgroup.h" +#include #include +#include +#include +#include #include namespace { @@ -127,3 +131,40 @@ QUndoCommand *SymbolTextPlacement::place(const QList &elements, Qt::A } return undo; } + +QIcon SymbolTextPlacement::icon(Qt::Alignment where) +{ + const Qt::Alignment lines = linesFor(where); + const QPalette palette = QApplication::palette(); + QIcon icon; + for (int size : {16, 22, 24, 32, 48}) + { + QPixmap pixmap(size, size); + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + painter.setRenderHint(QPainter::Antialiasing); + painter.scale(size / 24.0, size / 24.0); + + //The symbol + painter.setPen(Qt::NoPen); + painter.setBrush(palette.color(QPalette::Mid)); + painter.drawRect(QRectF(7, 7, 10, 10)); + + //Two lines of text, a long one over a short one + const qreal right = (where & Qt::AlignLeft) ? 5.5 : (where & Qt::AlignRight) ? 24 : 18.5; + const qreal left = (where & Qt::AlignLeft) ? 0 : (where & Qt::AlignRight) ? 18.5 : 5.5; + const qreal top = (where & Qt::AlignTop) ? 0 : (where & Qt::AlignBottom) ? 18.5 : 9.25; + painter.setBrush(palette.color(QPalette::WindowText)); + for (int i = 0; i < 2; ++i) + { + const qreal width = i == 0 ? right - left : (right - left) * 0.6; + const qreal x = lines == Qt::AlignRight ? right - width + : lines == Qt::AlignLeft ? left + : (left + right - width) / 2; + painter.drawRect(QRectF(x, top + i * 3, width, 2.5)); + } + painter.end(); + icon.addPixmap(pixmap); + } + return icon; +} diff --git a/sources/symboltextplacement.h b/sources/symboltextplacement.h index eb1d9c0a7..5100c98d3 100644 --- a/sources/symboltextplacement.h +++ b/sources/symboltextplacement.h @@ -18,6 +18,7 @@ #ifndef SYMBOLTEXTPLACEMENT_H #define SYMBOLTEXTPLACEMENT_H +#include #include #include @@ -47,6 +48,13 @@ namespace SymbolTextPlacement nullptr when none of the symbols has a text */ QUndoCommand *place(const QList &elements, Qt::Alignment where); + + /** + @return a picture of @a where: a grey square for the symbol, and + two bars for the lines of text where they will go, lined up as + they will be (left of the symbol, aligned right) + */ + QIcon icon(Qt::Alignment where); } #endif // SYMBOLTEXTPLACEMENT_H diff --git a/tests/qttest/symbol_text_placement_probe.cpp b/tests/qttest/symbol_text_placement_probe.cpp index e0902ecb6..5f29402b0 100644 --- a/tests/qttest/symbol_text_placement_probe.cpp +++ b/tests/qttest/symbol_text_placement_probe.cpp @@ -11,6 +11,8 @@ // placed in the folio's directions, and one undo puts everything back. #include #include +#include +#include #include #include #include @@ -141,6 +143,37 @@ int main(int argc, char **argv) for (DynamicElementTextItem *t : other->dynamicTextItems()) t->setVisible(false); check(SymbolTextPlacement::place({other}, Qt::AlignLeft) == nullptr, "a symbol without texts gives no undo step"); } + // The icons show where the texts go: bars left of the grey square + // for "left", right of it for "right", above it for "above". + auto dark = [](const QImage &img, const QRect &r) { + int n = 0; + for (int y = r.top(); y <= r.bottom(); ++y) + for (int x = r.left(); x <= r.right(); ++x) { + const QColor c = img.pixelColor(x, y); + if (c.alpha() > 128 && c.lightness() < 60) ++n; + } + return n; + }; + const QImage left = SymbolTextPlacement::icon(Qt::AlignLeft | Qt::AlignVCenter).pixmap(24, 24).toImage(); + const QImage right = SymbolTextPlacement::icon(Qt::AlignRight | Qt::AlignVCenter).pixmap(24, 24).toImage(); + const QImage above = SymbolTextPlacement::icon(Qt::AlignHCenter | Qt::AlignTop).pixmap(24, 24).toImage(); + check(dark(left, QRect(0, 8, 7, 8)) > 10 && dark(left, QRect(17, 0, 7, 24)) == 0, "the icon for left has its bars left of the symbol"); + check(dark(right, QRect(17, 8, 7, 8)) > 10 && dark(right, QRect(0, 0, 7, 24)) == 0, "the icon for right has them right of it"); + check(dark(above, QRect(6, 0, 12, 7)) > 10 && dark(above, QRect(0, 17, 24, 7)) == 0, "the icon for above has them above it"); + + //All nine side by side, to look at + QImage sheet(3 * 52, 3 * 52, QImage::Format_ARGB32); + sheet.fill(Qt::white); + QPainter p(&sheet); + const Qt::Alignment nine[] = { + Qt::AlignLeft | Qt::AlignTop, Qt::AlignHCenter | Qt::AlignTop, Qt::AlignRight | Qt::AlignTop, + Qt::AlignLeft | Qt::AlignVCenter, Qt::AlignCenter, Qt::AlignRight | Qt::AlignVCenter, + Qt::AlignLeft | Qt::AlignBottom, Qt::AlignHCenter | Qt::AlignBottom, Qt::AlignRight | Qt::AlignBottom}; + for (int i = 0; i < 9; ++i) + p.drawPixmap((i % 3) * 52 + 2, (i / 3) * 52 + 2, SymbolTextPlacement::icon(nine[i]).pixmap(48, 48)); + p.end(); + if (argc > 3) sheet.save(QString::fromLocal8Bit(argv[3]) + "/icons.png"); + std::puts("PASS"); } catch (const std::exception &error)