commit 2c1b49b450a6d91d891d48206766eedb2a85d0fe
Author: Juergen Spitzmueller <sp...@lyx.org>
Date:   Fri Feb 21 11:00:57 2025 +0100

    Add dedicated ColorsCombo, subclassed from CategorizedCombo
    
    We will need this sort of combo in several places, provide it with
    colors filled and all
---
 src/frontends/qt/CategorizedCombo.cpp |  60 ++++---------
 src/frontends/qt/CategorizedCombo.h   |  10 ++-
 src/frontends/qt/ColorsCombo.cpp      | 156 ++++++++++++++++++++++++++++++++++
 src/frontends/qt/ColorsCombo.h        |  65 ++++++++++++++
 src/frontends/qt/GuiCharacter.cpp     |  57 +++----------
 src/frontends/qt/GuiCharacter.h       |   4 +-
 src/frontends/qt/Makefile.am          |   2 +
 src/frontends/qt/ui/CharacterUi.ui    |   6 +-
 8 files changed, 264 insertions(+), 96 deletions(-)

diff --git a/src/frontends/qt/CategorizedCombo.cpp 
b/src/frontends/qt/CategorizedCombo.cpp
index 106c901d94..4200ddafab 100644
--- a/src/frontends/qt/CategorizedCombo.cpp
+++ b/src/frontends/qt/CategorizedCombo.cpp
@@ -91,13 +91,11 @@ struct CategorizedCombo::Private
                // 2nd: raw names
                // 3rd: category
                // 4th: availability (bool)
-               // 5th: color
-               model_(new QStandardItemModel(0, 5, p)),
+               model_(new QStandardItemModel(0, 4, p)),
                filterModel_(new CCFilterModel(p)),
                lastSel_(-1),
                CCItemDelegate_(new CCItemDelegate(parent)),
-               visibleCategories_(0), inShowPopup_(false),
-               has_colors_(false)
+               visibleCategories_(0), inShowPopup_(false)
        {
                filterModel_->setSourceModel(model_);
        }
@@ -115,7 +113,6 @@ struct CategorizedCombo::Private
         * 2nd column: raw item name,
         * 3rd column: category,
         * 4th column: availability
-        * 5th column: color
        **/
        QStandardItemModel * model_;
        /// the proxy model filtering \c model_
@@ -130,8 +127,6 @@ struct CategorizedCombo::Private
        unsigned visibleCategories_;
        ///
        bool inShowPopup_;
-       ///
-       bool has_colors_;
 };
 
 
@@ -141,12 +136,6 @@ static QString categoryCC(QAbstractItemModel const & 
model, int row)
 }
 
 
-static QString colorCC(QAbstractItemModel const & model, int row)
-{
-       return model.data(model.index(row, 4), Qt::DisplayRole).toString();
-}
-
-
 static int headerHeightCC(QStyleOptionViewItem const & opt)
 {
        return opt.fontMetrics.height();
@@ -162,7 +151,6 @@ void CCItemDelegate::paint(QPainter * painter, 
QStyleOptionViewItem const & opti
        painter->fillRect(opt.rect, opt.palette.color(QPalette::Base));
 
        QString cat = categoryCC(*index.model(), index.row());
-       QString col = colorCC(*index.model(), index.row());
 
        // not the same as in the previous line?
        if (cc_->d->visibleCategories_ > 0
@@ -211,8 +199,8 @@ void CCItemDelegate::drawDisplay(QPainter * painter, 
QStyleOptionViewItem const
 
        QTextFrameFormat fmt = doc.rootFrame()->frameFormat();
        fmt.setMargin(0);
-       if (cc_->d->has_colors_)
-               fmt.setLeftMargin (34);
+       if (cc_->left_margin_ != -1)
+               fmt.setLeftMargin(cc_->left_margin_);
                
        doc.rootFrame()->setFrameFormat(fmt);
 
@@ -474,7 +462,7 @@ bool CategorizedCombo::set(QString const & item, bool const 
report_missing)
        QList<QStandardItem *> r = d->model_->findItems(item, Qt::MatchExactly, 
1);
        if (r.empty()) {
                if (report_missing)
-                       LYXERR0("Trying to select non existent layout type " << 
item);
+                       LYXERR0("Trying to select non existent entry " << item);
                return false;
        }
 
@@ -483,27 +471,10 @@ bool CategorizedCombo::set(QString const & item, bool 
const report_missing)
 }
 
 
-void CategorizedCombo::setColorIcon(int const i, QString const color)
-{
-       if (color.isEmpty())
-               return;
-
-       QPixmap pixmap(32, 20);
-       QColor col(color);
-       pixmap.fill(col);
-       QPainter painter(&pixmap);
-       QRect pixmapRect = QRect(0, 0, 31, 19);
-       painter.drawPixmap(pixmapRect.x(), pixmapRect.y(), pixmap);
-       painter.drawRect(pixmapRect);
-
-       setItemIcon(i, QIcon(pixmap));
-}
-
-
 void CategorizedCombo::addItemSort(QString const & item, QString const & 
guiname,
                                   QString const & category, QString const & 
tooltip,
                                   bool sorted, bool sortedByCat, bool sortCats,
-                                  bool available, bool nocategories, QString 
const color)
+                                  bool available, bool nocategories)
 {
        QString titem = available ? guiname
                                  : toqstr(bformat(_("Unavailable: %1$s"),
@@ -519,16 +490,11 @@ void CategorizedCombo::addItemSort(QString const & item, 
QString const & guiname
        row.append(new QStandardItem(item));
        row.append(new QStandardItem(qcat));
        row.append(new QStandardItem(available));
-       if (!color.isEmpty()) {
-               row.append(new QStandardItem(color));
-               d->has_colors_ = true;
-       }
 
        // the first entry is easy
        int const end = d->model_->rowCount();
        if (end == 0) {
                d->model_->appendRow(row);
-               setColorIcon(0, color);
                return;
        }
 
@@ -553,7 +519,6 @@ void CategorizedCombo::addItemSort(QString const & item, 
QString const & guiname
                        d->model_->insertRow(i, row);
                } else
                        d->model_->appendRow(row);
-               setColorIcon(i, color);
                return;
        }
 
@@ -569,7 +534,6 @@ void CategorizedCombo::addItemSort(QString const & item, 
QString const & guiname
        }
 
        d->model_->insertRow(i, row);
-       setColorIcon(i, color);
 }
 
 
@@ -592,6 +556,12 @@ void CategorizedCombo::resetFilter()
 }
 
 
+void CategorizedCombo::setLeftMargin(int const i)
+{
+       left_margin_ = i;
+}
+
+
 void CategorizedCombo::updateCombo()
 {
        d->countCategories();
@@ -608,6 +578,12 @@ QString const & CategorizedCombo::filter() const
        return d->filter_;
 }
 
+
+QStandardItemModel * CategorizedCombo::model()
+{
+       return d->model_;
+}
+
 } // namespace frontend
 } // namespace lyx
 
diff --git a/src/frontends/qt/CategorizedCombo.h 
b/src/frontends/qt/CategorizedCombo.h
index 93d5c45242..a03ea03eb3 100644
--- a/src/frontends/qt/CategorizedCombo.h
+++ b/src/frontends/qt/CategorizedCombo.h
@@ -18,6 +18,7 @@
 #define LYX_CATEGORIZEDCOMBO_H
 
 #include <QComboBox>
+#include <QStandardItemModel>
 
 
 namespace lyx {
@@ -47,8 +48,7 @@ public:
        void addItemSort(QString const & item, QString const & guiname,
                         QString const & category, QString const & tooltip,
                         bool sorted, bool sortedByCat, bool sortCats,
-                        bool available, bool nocategories = false,
-                        QString color = QString());
+                        bool available, bool nocategories = false);
        ///
        QString getData(int row) const;
        ///
@@ -63,7 +63,9 @@ public:
        ///
        QString const & filter() const;
        ///
-       void setColorIcon(int const i, QString const color);
+       QStandardItemModel * model();
+       ///
+       void setLeftMargin(int const);
 
 private Q_SLOTS:
        ///
@@ -77,6 +79,8 @@ private:
        Private * const d;
        ///
        int lastCurrentIndex_;
+       ///
+       int left_margin_ = -1;
 };
 
 
diff --git a/src/frontends/qt/ColorsCombo.cpp b/src/frontends/qt/ColorsCombo.cpp
new file mode 100644
index 0000000000..6517f58500
--- /dev/null
+++ b/src/frontends/qt/ColorsCombo.cpp
@@ -0,0 +1,156 @@
+/**
+ * \file qt/ColorsCombo.cpp
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+ * \author Jürgen Spitzmüller
+ *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#include <config.h>
+
+#include "ColorsCombo.h"
+#include "LaTeXColors.h"
+
+#include "support/gettext.h"
+#include "qt_helpers.h"
+
+#include "support/qstring_helpers.h"
+
+#include <QPainter>
+
+using namespace lyx::support;
+
+namespace lyx {
+namespace frontend {
+
+
+ColorsCombo::ColorsCombo(QWidget * parent)
+       : CategorizedCombo(parent),
+         params_(BufferParams()),
+         has_ignore_(false), has_inherit_(false)
+{
+       setLeftMargin(32);
+       fillComboColor();
+}
+
+
+ColorsCombo::~ColorsCombo()
+{}
+
+
+void ColorsCombo::setColorIcon(int const i, QString const color)
+{
+       if (color.isEmpty())
+               return;
+
+       QPixmap pixmap(32, 20);
+       QColor col(color);
+       pixmap.fill(col);
+       QPainter painter(&pixmap);
+       QRect pixmapRect = QRect(0, 0, 31, 19);
+       painter.drawPixmap(pixmapRect.x(), pixmapRect.y(), pixmap);
+       painter.drawRect(pixmapRect);
+
+       setItemIcon(i, QIcon(pixmap));
+}
+
+
+void ColorsCombo::addItemSort(QString const & item, QString const & guiname,
+                             QString const & category, QString const color)
+{
+       QString titem = guiname;
+       bool const uncategorized = category.isEmpty();
+
+       QList<QStandardItem *> row;
+       QStandardItem * gui = new QStandardItem(titem);
+       row.append(gui);
+       row.append(new QStandardItem(item));
+       row.append(new QStandardItem(category));
+       row.append(new QStandardItem(true));
+       if (!color.isEmpty())
+               row.append(new QStandardItem(color));
+
+       // the first entry is easy
+       int const end = model()->rowCount();
+       if (end == 0) {
+               model()->appendRow(row);
+               setColorIcon(0, color);
+               return;
+       }
+
+       // find category
+       int i = 0;
+       // Sort categories alphabetically, uncategorized at the end.
+       while (i < end && model()->item(i, 2)->text() != category
+              && ((!uncategorized && model()->item(i, 
2)->text().localeAwareCompare(category) < 0
+                      && model()->item(i, 2)->text() != qt_("Uncategorized"))
+                  || (uncategorized && model()->item(i, 2)->text() != 
qt_("Uncategorized"))))
+               ++i;
+
+       // find row to insert the item, after the separator if it exists
+       if (i < end) {
+               // find alphabetic position, unavailable at the end
+               while (i != end
+                      && (model()->item(i, 
0)->text().localeAwareCompare(titem) < 0)
+                      && (model()->item(i, 2)->text() == category))
+                       ++i;
+       }
+
+       model()->insertRow(i, row);
+       setColorIcon(i, color);
+}
+
+
+void ColorsCombo::setBufferParams(BufferParams const params)
+{
+       params_ = params;
+       fillComboColor();
+}
+
+
+void ColorsCombo::fillComboColor()
+{
+       reset();
+       // at first add the general values as required
+       if (has_ignore_)
+               addItemSort(QString("ignore"), qt_("No change"),
+                           QString());
+       addItemSort(QString("none"), qt_("Default"),
+                   QString());
+       if (has_inherit_)
+               addItemSort(QString("inherit"), qt_("(Without)[[color]]"),
+                           QString());
+       // now custom colors
+       for (auto const & lc : params_.custom_colors) {
+               QString const lyxname = toqstr(lc.first);
+               QString const guiname = toqstr(lc.first);
+               QString const category = qt_("Custom Colors");
+               QString const plaincategory = toqstr("custom");
+               QString const color = toqstr(lc.second);
+               addItemSort(lyxname,
+                           guiname,
+                           category,
+                           color);
+       }
+       // then real colors
+       for (auto const & lc : theLaTeXColors().getLaTeXColors()) {
+               QString const lyxname = toqstr(lc.first);
+               QString const guiname = 
toqstr(translateIfPossible(lc.second.guiname()));
+               QString const category = 
toqstr(translateIfPossible(lc.second.category()));
+               QString const plaincategory = toqstr(lc.second.category());
+               QString const color = toqstr(lc.second.hexname());
+               addItemSort(lyxname,
+                           guiname,
+                           category,
+                           color);
+       }
+}
+
+
+} // namespace frontend
+} // namespace lyx
+
+
+#include "moc_ColorsCombo.cpp"
diff --git a/src/frontends/qt/ColorsCombo.h b/src/frontends/qt/ColorsCombo.h
new file mode 100644
index 0000000000..6f7d443d9e
--- /dev/null
+++ b/src/frontends/qt/ColorsCombo.h
@@ -0,0 +1,65 @@
+// -*- C++ -*-
+/**
+ * \file ColorsCombo.h
+ * This file is part of LyX, the document processor.
+ * Licence details can be found in the file COPYING.
+ *
+  * \author Jürgen Spitzmüller
+  *
+ * Full author contact details are available in file CREDITS.
+ */
+
+#ifndef LYX_COLORSCOMBO_H
+#define LYX_COLORSCOMBO_H
+
+#include "CategorizedCombo.h"
+#include "BufferParams.h"
+
+#include <QComboBox>
+
+
+namespace lyx {
+namespace frontend {
+
+class CCItemDelegate;
+
+/**
+ * A combo box with categorization
+ */
+class ColorsCombo : public CategorizedCombo
+{
+       Q_OBJECT
+public:
+       ColorsCombo(QWidget * parent);
+       ~ColorsCombo();
+
+       /// Update combobox.
+       void updateCombo();
+       /// Add item to combo with optional color icon
+       void addItemSort(QString const & item, QString const & guiname,
+                        QString const & category, QString color = QString());
+       /// Set BufferParams to access custom colors
+       void setBufferParams(BufferParams const params);
+       /// Add "ignore" color entry?
+       void hasIgnore(bool const b) { has_ignore_ = b; }
+       /// Add "inherit" color entry?
+       void hasInherit(bool const b) { has_inherit_ = b; }
+
+private:
+       ///
+       void setColorIcon(int const i, QString const color);
+       ///
+       void fillComboColor();
+       ///
+       BufferParams params_;
+       ///
+       bool has_ignore_;
+       ///
+       bool has_inherit_;
+};
+
+
+} // namespace frontend
+} // namespace lyx
+
+#endif // LYX_CATEGORIZEDCOMBO_H
diff --git a/src/frontends/qt/GuiCharacter.cpp 
b/src/frontends/qt/GuiCharacter.cpp
index 22313d4419..980f852083 100644
--- a/src/frontends/qt/GuiCharacter.cpp
+++ b/src/frontends/qt/GuiCharacter.cpp
@@ -15,7 +15,7 @@
 
 #include "GuiCharacter.h"
 
-#include "CategorizedCombo.h"
+#include "ColorsCombo.h"
 
 #include "GuiApplication.h"
 #include "qt_helpers.h"
@@ -29,8 +29,6 @@
 #include "Language.h"
 #include "Paragraph.h"
 
-#include "support/gettext.h"
-
 #include <QAbstractItemModel>
 #include <QPushButton>
 #include <QComboBox>
@@ -200,8 +198,11 @@ GuiCharacter::GuiCharacter(GuiView & lv)
        fillCombo(shapeCO, shape);
        fillCombo(ulineCO, bar);
        fillCombo(strikeCO, strike);
-       fillComboColor();
        fillCombo(langCO, language);
+       colorCO->hasIgnore(true);
+       colorCO->hasInherit(true);
+       colorCO->setBufferParams(buffer().masterParams());
+       custom_colors_cache_ = buffer().masterParams().custom_colors;
 
        colorCO->setToolTip(qt_("You can also directly type on the list to 
filter on color names."));
 
@@ -394,48 +395,6 @@ void GuiCharacter::change_adaptor()
 }
 
 
-void GuiCharacter::fillComboColor()
-{
-       // at first add the 2 colors "No change" and "No color"
-       colorCO->addItemSort(QString("ignore"), qt_("No change"),
-                          QString(), QString(),
-                          false, false, false, true, true);
-       colorCO->addItemSort(QString("none"), qt_("Default"),
-                          QString(), QString(),
-                          false, false, false, true, true);
-       colorCO->addItemSort(QString("inherit"), qt_("(Without)[[color]]"),
-                          QString(), QString(),
-                          false, false, false, true, true);
-       // custom colors
-       for (auto const & lc : buffer().masterParams().custom_colors) {
-               QString const lyxname = toqstr(lc.first);
-               QString const guiname = toqstr(lc.first);
-               QString const category = qt_("Custom Colors");
-               QString const plaincategory = toqstr("custom");
-               QString const color = toqstr(lc.second);
-               colorCO->addItemSort(lyxname,
-                                  guiname,
-                                  category,
-                                  QString(),
-                                  false, true, false, true, false,
-                                  color);
-       }
-       // now add the real colors
-       for (auto const & lc : theLaTeXColors().getLaTeXColors()) {
-               QString const lyxname = toqstr(lc.first);
-               QString const guiname = 
toqstr(translateIfPossible(lc.second.guiname()));
-               QString const category = 
toqstr(translateIfPossible(lc.second.category()));
-               QString const plaincategory = toqstr(lc.second.category());
-               QString const color = toqstr(lc.second.hexname());
-               colorCO->addItemSort(lyxname,
-                                  guiname,
-                                  category,
-                                  QString(),
-                                  false, true, false, true, false,
-                                  color);
-       }
-}
-
 
 void GuiCharacter::checkRestoreDefaults()
 {
@@ -528,6 +487,12 @@ void GuiCharacter::updateContents()
        if (font_.language() == buffer().params().language)
                font_.setLanguage(reset_language);
 
+       // Update custom colors if needed
+       if (custom_colors_cache_ != buffer().masterParams().custom_colors) {
+               colorCO->setBufferParams(buffer().masterParams());
+               custom_colors_cache_ = buffer().masterParams().custom_colors;
+       }
+
        paramsToDialog(font_);
 
        checkRestoreDefaults();
diff --git a/src/frontends/qt/GuiCharacter.h b/src/frontends/qt/GuiCharacter.h
index bfecc6a848..e968f7f381 100644
--- a/src/frontends/qt/GuiCharacter.h
+++ b/src/frontends/qt/GuiCharacter.h
@@ -92,8 +92,6 @@ private:
        void setBar(FontInfo & fi, FontDeco val);
        ///
        void setStrike(FontInfo & fi, FontDeco val);
-       ///
-       void fillComboColor();
 
        QList<FamilyPair> family;
        QList<SeriesPair> series;
@@ -111,6 +109,8 @@ private:
        bool noun_;
        ///
        bool nospellcheck_;
+       ///
+       std::map<std::string, std::string> custom_colors_cache_;
 
        ///
        QAction * resetdefault_ = new QAction(this);
diff --git a/src/frontends/qt/Makefile.am b/src/frontends/qt/Makefile.am
index 19c72c4b1e..3587bb0855 100644
--- a/src/frontends/qt/Makefile.am
+++ b/src/frontends/qt/Makefile.am
@@ -48,6 +48,7 @@ SOURCEFILES = \
        BulletsModule.cpp \
        ButtonController.cpp \
        CategorizedCombo.cpp \
+       ColorsCombo.cpp \
        ColorCache.cpp \
        CustomizedWidgets.cpp \
        DialogView.cpp \
@@ -172,6 +173,7 @@ MOCHEADER = \
        Action.h \
        BulletsModule.h \
        CategorizedCombo.h \
+       ColorsCombo.h \
        CustomizedWidgets.h \
        DialogView.h \
        DockView.h \
diff --git a/src/frontends/qt/ui/CharacterUi.ui 
b/src/frontends/qt/ui/CharacterUi.ui
index 3733edb8a0..1fe115cc8a 100644
--- a/src/frontends/qt/ui/CharacterUi.ui
+++ b/src/frontends/qt/ui/CharacterUi.ui
@@ -190,7 +190,7 @@
            </widget>
           </item>
           <item row="0" column="1">
-           <widget class="lyx::frontend::CategorizedCombo" name="colorCO">
+           <widget class="lyx::frontend::ColorsCombo" name="colorCO">
             <property name="inputMethodHints">
              
<set>Qt::InputMethodHint::ImhDigitsOnly|Qt::InputMethodHint::ImhLatinOnly</set>
             </property>
@@ -386,9 +386,9 @@
  </widget>
  <customwidgets>
   <customwidget>
-   <class>lyx::frontend::CategorizedCombo</class>
+   <class>lyx::frontend::ColorsCombo</class>
    <extends>QComboBox</extends>
-   <header>CategorizedCombo.h</header>
+   <header>ColorsCombo.h</header>
   </customwidget>
  </customwidgets>
  <tabstops>
-- 
lyx-cvs mailing list
lyx-cvs@lists.lyx.org
https://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to