diff --git a/cmake/qet_compilation_vars.cmake b/cmake/qet_compilation_vars.cmake index a053d688d..33230fc74 100644 --- a/cmake/qet_compilation_vars.cmake +++ b/cmake/qet_compilation_vars.cmake @@ -707,6 +707,8 @@ set(QET_SRC_FILES ${QET_DIR}/sources/ui/conductorpropertiesdialog.h ${QET_DIR}/sources/ui/conductorcolortoolbutton.cpp ${QET_DIR}/sources/ui/conductorcolortoolbutton.h + ${QET_DIR}/sources/ui/diagrambgcolorbutton.cpp + ${QET_DIR}/sources/ui/diagrambgcolorbutton.h ${QET_DIR}/sources/ui/conductorpropertieswidget.cpp ${QET_DIR}/sources/ui/conductorpropertieswidget.h ${QET_DIR}/sources/ui/configsaveloaderwidget.cpp diff --git a/sources/bordertitleblock.cpp b/sources/bordertitleblock.cpp index 0dd52bc7f..3db2c29f9 100644 --- a/sources/bordertitleblock.cpp +++ b/sources/bordertitleblock.cpp @@ -505,7 +505,10 @@ void BorderTitleBlock::draw(QPainter *painter) { //Set the QPainter painter -> save(); - QPen pen(Qt::black); + //Use a pen color that contrasts with the background + QColor border_color = Diagram::background_color.lightness() < 128 + ? QColor(Qt::white) : QColor(Qt::black); + QPen pen(border_color); painter -> setPen(pen); painter -> setBrush(Qt::NoBrush); diff --git a/sources/palettegraphicsview.cpp b/sources/palettegraphicsview.cpp index b18bf725b..ab9b322db 100644 --- a/sources/palettegraphicsview.cpp +++ b/sources/palettegraphicsview.cpp @@ -99,7 +99,7 @@ bool PaletteGraphicsView::eventFilter(QObject *watched, QEvent *event) */ void PaletteGraphicsView::paintEvent(QPaintEvent *event) { - if (invertsLightness()) + if (invertsLightness() && !customBackgroundColor()) { paintInverted(event); return; diff --git a/sources/palettegraphicsview.h b/sources/palettegraphicsview.h index 512bba283..080897545 100644 --- a/sources/palettegraphicsview.h +++ b/sources/palettegraphicsview.h @@ -63,6 +63,9 @@ class PaletteGraphicsView : public QGraphicsView bool invertsLightness() const; + static void setCustomBackgroundColor(bool custom) { s_custom_bg = custom; } + static bool customBackgroundColor() { return s_custom_bg; } + protected: bool eventFilter(QObject *watched, QEvent *event) override; void paintEvent(QPaintEvent *event) override; @@ -90,6 +93,7 @@ class PaletteGraphicsView : public QGraphicsView QPainter m_buffer_painter; /// True while paintEvent() paints for an inverted display. bool m_inverting = false; + static inline bool s_custom_bg = false; }; #endif diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index d928e24f8..cd29dd096 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -51,6 +51,7 @@ #include "shortcutmanager.h" #include "ui/bomexportdialog.h" #include "ui/conductorcolortoolbutton.h" +#include "ui/diagrambgcolorbutton.h" #include "ui/jumptoelementdialog.h" #include "ui/diagrampropertieseditordockwidget.h" #include "ui/backupdialog.h" @@ -413,15 +414,8 @@ void QETDiagramEditor::setUpActions() pv->project()->setAutoBreakConductor(abc); }); - //Switch background color - m_grey_background = new QAction (QET::Icons::DiagramBg, tr("Couleur de fond blanc/gris","Tool tip of white/grey background button"), this); - m_grey_background -> setStatusTip (tr("Affiche la couleur de fond du folio en blanc ou en gris", "Status tip of white/grey background button")); - m_grey_background -> setCheckable (true); - connect (m_grey_background, &QAction::triggered, [this](bool checked) { - Diagram::background_color = checked ? Qt::darkGray : Qt::white; - if (this->currentDiagramView() && this->currentDiagramView()->diagram()) - this->currentDiagramView()->diagram()->update(); - }); + //Diagram background color picker + m_background_color_button = new DiagramBgColorToolButton(this, this); //Draw or not the background grid m_draw_grid = new QAction ( QET::Icons::Grid, tr("Afficher la grille"), this); @@ -912,7 +906,7 @@ void QETDiagramEditor::setUpToolBar() view_tool_bar -> addSeparator(); view_tool_bar -> addAction(m_draw_grid); view_tool_bar -> addAction(m_draw_guides); - view_tool_bar -> addAction (m_grey_background); + view_tool_bar -> addWidget(m_background_color_button); view_tool_bar -> addSeparator(); view_tool_bar -> addActions(m_zoom_action_toolBar); @@ -1063,7 +1057,7 @@ void QETDiagramEditor::setUpMenu() menu_affichage -> addSeparator(); menu_affichage -> addAction(m_draw_grid); menu_affichage -> addAction(m_draw_guides); - menu_affichage -> addAction(m_grey_background); + menu_affichage -> addMenu(m_background_color_button->menu()); menu_affichage -> addSeparator(); menu_affichage -> addActions(m_zoom_actions_group.actions()); @@ -1880,7 +1874,7 @@ void QETDiagramEditor::slot_updateActions() m_select_actions_group. setEnabled(opened_diagram); m_add_item_actions_group. setEnabled(editable_project); m_row_column_actions_group. setEnabled(editable_project); - m_grey_background-> setEnabled(opened_diagram); + m_background_color_button-> setEnabled(opened_diagram); m_draw_grid-> setEnabled(opened_diagram); m_draw_guides-> setEnabled(opened_diagram); diff --git a/sources/qetdiagrameditor.h b/sources/qetdiagrameditor.h index b6f39abfa..4ca557eac 100644 --- a/sources/qetdiagrameditor.h +++ b/sources/qetdiagrameditor.h @@ -34,6 +34,7 @@ class QETResult; class ProjectView; class ConductorColorToolButton; class CustomElement; +class DiagramBgColorToolButton; class Diagram; class DiagramView; class Element; @@ -200,7 +201,6 @@ class QETDiagramEditor : public QETMainWindow *m_paste, ///< Paste clipboard content on the current diagram *m_auto_conductor, ///< Enable/Disable the use of auto conductor *m_auto_break_conductor, ///< Enable/Disable the use of auto break conductor - *m_grey_background, ///< Switch the background color in white or grey *m_draw_grid, ///< Switch the background grid display or not *m_draw_guides = nullptr, ///< Switch the custom guides display or not *m_project_edit_properties, ///< Edit the properties of the current project. @@ -240,6 +240,8 @@ class QETDiagramEditor : public QETMainWindow ///< One-click conductor colour, in the "Schéma" toolbar ConductorColorToolButton *m_conductor_color_button = nullptr; + ///< Diagram background color picker, in the "Affichage" toolbar + DiagramBgColorToolButton *m_background_color_button = nullptr; QList m_zoom_action_toolBar; ///Only zoom action must displayed in the toolbar diff --git a/sources/titleblocktemplate.cpp b/sources/titleblocktemplate.cpp index d38c893f6..f3c0b04a0 100644 --- a/sources/titleblocktemplate.cpp +++ b/sources/titleblocktemplate.cpp @@ -19,6 +19,7 @@ #include "NameList/nameslist.h" #include "createdxf.h" +#include "diagram.h" #include "qet.h" #include "qetapp.h" // uncomment the line below to get more debug information @@ -1589,8 +1590,10 @@ void TitleBlockTemplate::render(QPainter &painter, int titleblock_height = height(); painter.save(); - //Setup the QPainter - QPen pen(Qt::black); + //Setup the QPainter - use a color that contrasts with the background + QColor ink = Diagram::background_color.lightness() < 128 + ? QColor(Qt::white) : QColor(Qt::black); + QPen pen(ink); painter.setPen(pen); // draw the titleblock border @@ -1737,7 +1740,9 @@ void TitleBlockTemplate::renderCell(QPainter &painter, { // draw the border rect of the current cell QPen pen(QBrush(), 1, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin); - pen.setColor(Qt::black); + QColor ink = Diagram::background_color.lightness() < 128 + ? QColor(Qt::white) : QColor(Qt::black); + pen.setColor(ink); painter.setPen(pen); painter.drawRect(cell_rect); diff --git a/sources/ui/diagrambgcolorbutton.cpp b/sources/ui/diagrambgcolorbutton.cpp new file mode 100644 index 000000000..608ccac25 --- /dev/null +++ b/sources/ui/diagrambgcolorbutton.cpp @@ -0,0 +1,242 @@ +/* + Copyright 2006-2026 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#include "diagrambgcolorbutton.h" + +#include "../diagram.h" +#include "../diagramview.h" +#include "../palettegraphicsview.h" +#include "../qetdiagrameditor.h" +#include "../projectview.h" +#include "../qetproject.h" + +#include +#include +#include +#include +#include + +namespace { + struct NamedColor { const char *context_name; QColor color; }; + + QList standardColors() + { + return { + {QT_TRANSLATE_NOOP("DiagramBgColorToolButton", "Blanc"), QColor(0xFF, 0xFF, 0xFF)}, + {QT_TRANSLATE_NOOP("DiagramBgColorToolButton", "Blanc cassé"), QColor(0xFD, 0xFB, 0xF5)}, + {QT_TRANSLATE_NOOP("DiagramBgColorToolButton", "Gris clair"), QColor(0xE0, 0xE0, 0xE0)}, + {QT_TRANSLATE_NOOP("DiagramBgColorToolButton", "Gris"), QColor(0x80, 0x80, 0x80)}, + {QT_TRANSLATE_NOOP("DiagramBgColorToolButton", "Gris foncé"), QColor(0x40, 0x40, 0x40)}, + {QT_TRANSLATE_NOOP("DiagramBgColorToolButton", "Noir"), QColor(0x00, 0x00, 0x00)}, + }; + } + + const int MAX_RECENT = 6; +} + +/** + @brief DiagramBgColorToolButton::DiagramBgColorToolButton + @param editor : the diagram editor this button acts on + @param parent +*/ +DiagramBgColorToolButton::DiagramBgColorToolButton(QETDiagramEditor *editor, QWidget *parent) : + QToolButton(parent), + m_editor(editor) +{ + setPopupMode(QToolButton::InstantPopup); + setToolTip(tr("Couleur de fond du folio")); + setStatusTip(tr("Choisir la couleur de fond du folio", + "status bar tip")); + + m_is_system_color = true; + m_current = QApplication::palette().color(QPalette::Base); + setMenu(new QMenu(this)); + rebuildMenu(); + setSwatch(m_current); +} + +/** + @brief DiagramBgColorToolButton::rebuildMenu +*/ +void DiagramBgColorToolButton::rebuildMenu() +{ + QMenu *m = menu(); + m->clear(); + + QAction *sys = m->addAction(tr("Couleur système")); + connect(sys, &QAction::triggered, this, &DiagramBgColorToolButton::applySystemColor); + m->addSeparator(); + + for (const auto &nc : standardColors()) + { + const QColor c = nc.color; + QAction *a = m->addAction(swatchIcon(c), + tr(nc.context_name)); + connect(a, &QAction::triggered, this, [this, c]() { applyColor(c); }); + } + + if (!m_recent.isEmpty()) + { + m->addSeparator(); + QAction *title = m->addAction(tr("Récemment utilisées")); + title->setEnabled(false); + for (const QColor &c : std::as_const(m_recent)) + { + QAction *a = m->addAction(swatchIcon(c), c.name()); + connect(a, &QAction::triggered, this, [this, c]() { applyColor(c); }); + } + } + + m->addSeparator(); + QAction *other = m->addAction(tr("Autre couleur…")); + connect(other, &QAction::triggered, this, &DiagramBgColorToolButton::chooseOtherColor); +} + +/** + @brief DiagramBgColorToolButton::applyColor + Set a custom background color on all open diagrams. + @param color +*/ +void DiagramBgColorToolButton::applyColor(const QColor &color) +{ + if (!color.isValid()) { + return; + } + + m_is_system_color = false; + rememberRecent(color); + setSwatch(color); + + PaletteGraphicsView::setCustomBackgroundColor(true); + Diagram::background_color = color; + + QETDiagramEditor *editor = m_editor; + if (!editor) { + return; + } + for (ProjectView *pv : editor->openedProjects()) + for (Diagram *d : pv->project()->diagrams()) + d->update(); +} + +/** + @brief DiagramBgColorToolButton::applySystemColor + Restore the system-default background and re-enable dark-mode + inversion. +*/ +void DiagramBgColorToolButton::applySystemColor() +{ + m_is_system_color = true; + m_current = QApplication::palette().color(QPalette::Base); + setSwatch(m_current); + + PaletteGraphicsView::setCustomBackgroundColor(false); + Diagram::background_color = Qt::white; + + QETDiagramEditor *editor = m_editor; + if (!editor) { + return; + } + for (ProjectView *pv : editor->openedProjects()) + for (Diagram *d : pv->project()->diagrams()) + d->update(); +} + +/** + @brief DiagramBgColorToolButton::chooseOtherColor +*/ +void DiagramBgColorToolButton::chooseOtherColor() +{ + const QColor c = QColorDialog::getColor(m_current, this, + tr("Choisir une couleur de fond")); + if (c.isValid()) { + applyColor(c); + } +} + +/** + @brief DiagramBgColorToolButton::rememberRecent + Most recent first, no duplicates, capped. + @param color +*/ +void DiagramBgColorToolButton::rememberRecent(const QColor &color) +{ + for (const auto &nc : standardColors()) { + if (nc.color == color) { + return; + } + } + + m_recent.removeAll(color); + m_recent.prepend(color); + while (m_recent.size() > MAX_RECENT) { + m_recent.removeLast(); + } + rebuildMenu(); +} + +/** + @brief DiagramBgColorToolButton::setSwatch + @param color +*/ +void DiagramBgColorToolButton::setSwatch(const QColor &color) +{ + m_current = color; + setIcon(swatchIcon(color)); +} + +/** + @brief DiagramBgColorToolButton::syncFromDiagram + Sync the button swatch to whatever Diagram::background_color is + currently set to. Called when the active folio changes. +*/ +void DiagramBgColorToolButton::syncFromDiagram() +{ + if (m_is_system_color) { + m_current = QApplication::palette().color(QPalette::Base); + } else { + m_current = Diagram::background_color; + } + setSwatch(m_current); +} + +/** + @brief DiagramBgColorToolButton::updateEnabledState +*/ +void DiagramBgColorToolButton::updateEnabledState() +{ + setEnabled(m_editor && m_editor->currentProjectView()); +} + +/** + @brief DiagramBgColorToolButton::swatchIcon + @param color + @return a plain square of that colour, outlined so that white and very + light colours are still visible against the toolbar. +*/ +QIcon DiagramBgColorToolButton::swatchIcon(const QColor &color) +{ + QPixmap pix(16, 16); + pix.fill(Qt::transparent); + QPainter p(&pix); + p.setRenderHint(QPainter::Antialiasing, false); + p.setBrush(color); + p.setPen(QPen(QColor(0x40, 0x40, 0x40), 1)); + p.drawRect(0, 0, 15, 15); + p.end(); + return QIcon(pix); +} diff --git a/sources/ui/diagrambgcolorbutton.h b/sources/ui/diagrambgcolorbutton.h new file mode 100644 index 000000000..6da4d8806 --- /dev/null +++ b/sources/ui/diagrambgcolorbutton.h @@ -0,0 +1,64 @@ +/* + Copyright 2006-2026 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#ifndef DIAGRAMBGCOLORTOOLBUTTON_H +#define DIAGRAMBGCOLORTOOLBUTTON_H + +#include +#include +#include + +class QETDiagramEditor; + +/** + @brief The DiagramBgColorToolButton class + Color picker for the diagram sheet background, placed in the + "Affichage" toolbar. Mirrors the ConductorColorToolButton UX: + preset colors in the dropdown, "Autre couleur..." at the bottom, + and a swatch icon on the button itself. + + Picking "Couleur système" clears any custom colour and lets the + dark-mode inversion handle the background as before. +*/ +class DiagramBgColorToolButton : public QToolButton +{ + Q_OBJECT + + public: + explicit DiagramBgColorToolButton(QETDiagramEditor *editor, + QWidget *parent = nullptr); + + public slots: + void updateEnabledState(); + void syncFromDiagram(); + + private: + void rebuildMenu(); + void applyColor(const QColor &color); + void applySystemColor(); + void chooseOtherColor(); + void rememberRecent(const QColor &color); + void setSwatch(const QColor &color); + static QIcon swatchIcon(const QColor &color); + + QETDiagramEditor *m_editor = nullptr; + QList m_recent; + QColor m_current; + bool m_is_system_color = false; +}; + +#endif // DIAGRAMBGCOLORTOOLBUTTON_H