diff --git a/src/gui/field/colorlabelwidget.cpp b/src/gui/field/colorlabelwidget.cpp index 1b52f979..449bf7a8 100644 --- a/src/gui/field/colorlabelwidget.cpp +++ b/src/gui/field/colorlabelwidget.cpp @@ -1,220 +1,263 @@ /*************************************************************************** * Copyright (C) 2004-2019 by Thomas Fischer * * * * This program 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. * * * * This program 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 this program; if not, see . * ***************************************************************************/ #include "colorlabelwidget.h" #include #include #include #include #include #include #include static const QColor NoColor = Qt::black; -class ColorLabelComboBoxModel : public QAbstractItemModel, private NotificationListener +class ColorLabelComboBoxModel : public QAbstractItemModel { Q_OBJECT public: enum ColorLabelComboBoxModelRole { /// Color of a color-label pair ColorRole = Qt::UserRole + 1721 }; struct ColorLabelPair { QColor color; QString label; }; - QList colorLabelPairs; QColor userColor; ColorLabelComboBoxModel(QObject *p = nullptr) - : QAbstractItemModel(p), userColor(Qt::black) { - NotificationHub::registerNotificationListener(this, NotificationHub::EventConfigurationChanged); - } - - void notificationEvent(int eventId) override { - if (eventId == NotificationHub::EventConfigurationChanged) { - beginResetModel(); - /// New data will be pulled automatically via Preferences::instance().colorCodes() - endResetModel(); - } + : QAbstractItemModel(p), userColor(NoColor) { + /// nothing } QModelIndex index(int row, int column, const QModelIndex &parent) const override { return parent == QModelIndex() ? createIndex(row, column) : QModelIndex(); } QModelIndex parent(const QModelIndex & = QModelIndex()) const override { return QModelIndex(); } int rowCount(const QModelIndex &parent = QModelIndex()) const override { return parent == QModelIndex() ? 2 + Preferences::instance().colorCodes().count() : 0; } int columnCount(const QModelIndex &parent = QModelIndex()) const override { return parent == QModelIndex() ? 1 : 0; } QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override { if (role == ColorRole) { - if (index.row() == 0) + const int cci = index.row() - 1; + if (index.row() == 0 || cci < 0 || cci >= Preferences::instance().colorCodes().count()) return NoColor; else if (index.row() == rowCount() - 1) return userColor; else - return Preferences::instance().colorCodes().at(index.row() - 1).first; + return Preferences::instance().colorCodes().at(cci).first; } else if (role == Qt::FontRole && (index.row() == 0 || index.row() == rowCount() - 1)) { /// Set first item's text ("No color") and last item's text ("User-defined color") in italics QFont font; font.setItalic(true); return font; } else if (role == Qt::DecorationRole && index.row() > 0 && (index.row() < rowCount() - 1 || userColor != NoColor)) { /// For items that have a color to choose, draw a little square in this chosen color QColor color = data(index, ColorRole).value(); return ColorLabelWidget::createSolidIcon(color); } else if (role == Qt::DisplayRole) if (index.row() == 0) return i18n("No color"); else if (index.row() == rowCount() - 1) return i18n("User-defined color"); else return Preferences::instance().colorCodes().at(index.row() - 1).second; else return QVariant(); } QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override { if (section != 0 || orientation != Qt::Horizontal || role != Qt::DisplayRole) return QVariant(); return i18n("Color & Label"); } void setColor(const QColor &newColor) { userColor = newColor; const QModelIndex idx = index(rowCount() - 1, 0, QModelIndex()); emit dataChanged(idx, idx); } + + void reset() { + beginResetModel(); + endResetModel(); + } }; -class ColorLabelWidget::ColorLabelWidgetPrivate +class ColorLabelWidget::ColorLabelWidgetPrivate : private NotificationListener { +private: + ColorLabelWidget *parent; + public: ColorLabelComboBoxModel *model; - ColorLabelWidgetPrivate(ColorLabelWidget *parent, ColorLabelComboBoxModel *m) - : model(m) + ColorLabelWidgetPrivate(ColorLabelWidget *_parent, ColorLabelComboBoxModel *m) + : parent(_parent), model(m) { Q_UNUSED(parent) + NotificationHub::registerNotificationListener(this, NotificationHub::EventConfigurationChanged); + } + + void notificationEvent(int eventId) override { + if (eventId == NotificationHub::EventConfigurationChanged) { + /// Avoid triggering signal when current index is set by the program + disconnect(parent, static_cast(&QComboBox::currentIndexChanged), parent, &ColorLabelWidget::slotCurrentIndexChanged); + + const QColor currentColor = parent->currentColor(); + model->reset(); + model->userColor = NoColor; + selectColor(currentColor); + + /// Re-enable triggering signal after setting current index + connect(parent, static_cast(&QComboBox::currentIndexChanged), parent, &ColorLabelWidget::slotCurrentIndexChanged); + } + } + + int selectColor(const QString &color) + { + return selectColor(QColor(color)); + } + + int selectColor(const QColor &color) + { + int rowIndex = 0; + if (color != NoColor) { + /// Find row that matches given color + for (rowIndex = 0; rowIndex < model->rowCount(); ++rowIndex) + if (model->data(model->index(rowIndex, 0, QModelIndex()), ColorLabelComboBoxModel::ColorRole).value() == color) + break; + + if (rowIndex >= model->rowCount()) { + /// Color was not in the list of known colors, so set user color to given color + model->userColor = color; + rowIndex = model->rowCount() - 1; + } + } + return rowIndex; } }; ColorLabelWidget::ColorLabelWidget(QWidget *parent) : QComboBox(parent), d(new ColorLabelWidgetPrivate(this, new ColorLabelComboBoxModel(this))) { setModel(d->model); connect(this, static_cast(&QComboBox::currentIndexChanged), this, &ColorLabelWidget::slotCurrentIndexChanged); } ColorLabelWidget::~ColorLabelWidget() { delete d; } void ColorLabelWidget::clear() { - setCurrentIndex(0); + /// Avoid triggering signal when current index is set by the program + disconnect(this, static_cast(&QComboBox::currentIndexChanged), this, &ColorLabelWidget::slotCurrentIndexChanged); + + d->model->userColor = NoColor; + setCurrentIndex(0); ///< index 0 should be "no color" + + /// Re-enable triggering signal after setting current index + connect(this, static_cast(&QComboBox::currentIndexChanged), this, &ColorLabelWidget::slotCurrentIndexChanged); +} + +QColor ColorLabelWidget::currentColor() const +{ + return d->model->data(d->model->index(currentIndex(), 0, QModelIndex()), ColorLabelComboBoxModel::ColorRole).value(); } bool ColorLabelWidget::reset(const Value &value) { /// Avoid triggering signal when current index is set by the program disconnect(this, static_cast(&QComboBox::currentIndexChanged), this, &ColorLabelWidget::slotCurrentIndexChanged); QSharedPointer verbatimText; + int rowIndex = 0; if (value.count() == 1 && !(verbatimText = value.first().dynamicCast()).isNull()) { - int i = 0; - const QColor color = QColor(verbatimText->text()); - for (; i < d->model->rowCount(); ++i) - if (d->model->data(d->model->index(i, 0, QModelIndex()), ColorLabelComboBoxModel::ColorRole).value() == color) - break; - - if (i >= d->model->rowCount()) { - d->model->userColor = color; - i = d->model->rowCount() - 1; - } - setCurrentIndex(i); - } else - setCurrentIndex(0); + /// Create QColor instance based on given textual representation + rowIndex = d->selectColor(verbatimText->text()); + } + setCurrentIndex(rowIndex); /// Re-enable triggering signal after setting current index connect(this, static_cast(&QComboBox::currentIndexChanged), this, &ColorLabelWidget::slotCurrentIndexChanged); return true; } bool ColorLabelWidget::apply(Value &value) const { - QColor color = d->model->data(d->model->index(currentIndex(), 0, QModelIndex()), ColorLabelComboBoxModel::ColorRole).value(); + const QColor color = currentColor(); value.clear(); if (color != NoColor) value.append(QSharedPointer(new VerbatimText(color.name()))); return true; } bool ColorLabelWidget::validate(QWidget **, QString &) const { return true; } void ColorLabelWidget::setReadOnly(bool isReadOnly) { setEnabled(!isReadOnly); } void ColorLabelWidget::slotCurrentIndexChanged(int index) { if (index == count() - 1) { const QColor initialColor = d->model->userColor; const QColor newColor = QColorDialog::getColor(initialColor, this); if (newColor.isValid()) d->model->setColor(newColor); } emit modified(); } QPixmap ColorLabelWidget::createSolidIcon(const QColor &color) { QFontMetrics fm = QFontMetrics(QFont()); int h = fm.height() - 4; QPixmap pm(h, h); QPainter painter(&pm); painter.setPen(color); painter.setBrush(QBrush(color)); painter.drawRect(0, 0, h, h); return pm; } #include "colorlabelwidget.moc" diff --git a/src/gui/field/colorlabelwidget.h b/src/gui/field/colorlabelwidget.h index 1342982c..6c4e011e 100644 --- a/src/gui/field/colorlabelwidget.h +++ b/src/gui/field/colorlabelwidget.h @@ -1,57 +1,58 @@ /*************************************************************************** - * Copyright (C) 2004-2018 by Thomas Fischer * + * Copyright (C) 2004-2019 by Thomas Fischer * * * * This program 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. * * * * This program 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 this program; if not, see . * ***************************************************************************/ #ifndef KBIBTEX_GUI_COLORLABELWIDGET_H #define KBIBTEX_GUI_COLORLABELWIDGET_H #include #include #include "kbibtexgui_export.h" /** * @author Thomas Fischer */ class KBIBTEXGUI_EXPORT ColorLabelWidget : public QComboBox { Q_OBJECT public: explicit ColorLabelWidget(QWidget *parent = nullptr); ~ColorLabelWidget() override; void clear(); + QColor currentColor() const; bool reset(const Value &value); bool apply(Value &value) const; bool validate(QWidget **widgetWithIssue, QString &message) const; void setReadOnly(bool); static QPixmap createSolidIcon(const QColor &color); signals: void modified(); private slots: void slotCurrentIndexChanged(int); private: class ColorLabelWidgetPrivate; ColorLabelWidget::ColorLabelWidgetPrivate *d; }; #endif // KBIBTEX_GUI_COLORLABELWIDGET_H