4#include "ui_paletteeditor.h"
10#include <QMetaProperty>
26 , m_currentColorGroup(QPalette::Active)
28 , m_modelUpdated(false)
29 , m_paletteUpdated(false)
33 m_ui->paletteView->setModel(m_paletteModel);
35 m_ui->paletteView->setModel(m_paletteModel);
37 m_ui->paletteView->setItemDelegate(delegate);
38 m_ui->paletteView->setEditTriggers(QAbstractItemView::AllEditTriggers);
39 m_ui->paletteView->setSelectionBehavior(QAbstractItemView::SelectRows);
40 m_ui->paletteView->setDragEnabled(
true);
41 m_ui->paletteView->setDropIndicatorShown(
true);
42 m_ui->paletteView->setRootIsDecorated(
false);
43 m_ui->paletteView->setColumnHidden(2,
true);
44 m_ui->paletteView->setColumnHidden(3,
true);
46 auto saveButton = m_ui->buttonBox->addButton(tr(
"Save…"), QDialogButtonBox::ActionRole);
47 connect(saveButton, &QPushButton::clicked,
this, &PaletteEditor::save);
48 auto loadButton = m_ui->buttonBox->addButton(tr(
"Load…"), QDialogButtonBox::ActionRole);
49 connect(loadButton, &QPushButton::clicked,
this, &PaletteEditor::load);
53 connect(m_ui->computeRadio, &QRadioButton::clicked,
this, &PaletteEditor::handleComputeRadioClicked);
54 connect(m_ui->detailsRadio, &QRadioButton::clicked,
this, &PaletteEditor::handleDetailsRadioClicked);
70#
if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
76 using MaskType = std::remove_cv_t<
decltype(mask)>;
77 for (
int i = 0; i < static_cast<int>(QPalette::NColorRoles); ++i) {
78 if (mask & (
static_cast<MaskType
>(1) <<
static_cast<MaskType
>(i))) {
81 m_editPalette.setBrush(
82 QPalette::Active,
static_cast<QPalette::ColorRole
>(i), m_parentPalette.brush(QPalette::Active,
static_cast<QPalette::ColorRole
>(i)));
83 m_editPalette.setBrush(
84 QPalette::Inactive,
static_cast<QPalette::ColorRole
>(i), m_parentPalette.brush(QPalette::Inactive,
static_cast<QPalette::ColorRole
>(i)));
85 m_editPalette.setBrush(
86 QPalette::Disabled,
static_cast<QPalette::ColorRole
>(i), m_parentPalette.brush(QPalette::Disabled,
static_cast<QPalette::ColorRole
>(i)));
89#
if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
91 m_editPalette = m_editPalette.resolve(m_editPalette)
97 m_paletteUpdated =
true;
98 if (!m_modelUpdated) {
99 m_paletteModel->setPalette(m_editPalette, m_parentPalette);
101 m_paletteUpdated =
false;
106 m_parentPalette = parentPalette;
112 switch (
event->type()) {
113 case QEvent::LanguageChange:
114 m_ui->retranslateUi(
this);
118 return QDialog::event(
event);
121void PaletteEditor::handleComputeRadioClicked()
126 m_ui->paletteView->setColumnHidden(2,
true);
127 m_ui->paletteView->setColumnHidden(3,
true);
132void PaletteEditor::handleDetailsRadioClicked()
137 const int w = m_ui->paletteView->columnWidth(1);
138 m_ui->paletteView->setColumnHidden(2,
false);
139 m_ui->paletteView->setColumnHidden(3,
false);
140 auto *
const header = m_ui->paletteView->header();
141 header->resizeSection(1, w / 3);
142 header->resizeSection(2, w / 3);
143 header->resizeSection(3, w / 3);
145 m_paletteModel->setCompute(
false);
148static inline QString paletteSuffix()
150 return QStringLiteral(
"ini");
153static inline QString paletteFilter()
155 return PaletteEditor::tr(
"Color palette configuration (*.ini)");
158static bool loadPalette(
const QString &fileName, QPalette *pal, QString *errorMessage)
160 const auto settings = QSettings(fileName, QSettings::IniFormat);
161 if (settings.status() != QSettings::NoError) {
162 *errorMessage = PaletteEditor::tr(
"Unable to load \"%1\".").arg(fileName);
165 const auto value = settings.value(QStringLiteral(
"palette"));
166 if (!value.isValid() || !value.canConvert<QPalette>()) {
167 *errorMessage = PaletteEditor::tr(
"\"%1\" does not contain a valid palette.").arg(fileName);
170 *pal = settings.value(QStringLiteral(
"palette")).value<QPalette>();
174static bool savePalette(
const QString &fileName,
const QPalette &pal, QString *errorMessage)
176 auto settings = QSettings(fileName, QSettings::IniFormat);
177 settings.setValue(QStringLiteral(
"palette"), QVariant(pal));
179 if (settings.status() != QSettings::NoError) {
180 *errorMessage = PaletteEditor::tr(
"Unable to write \"%1\".").arg(fileName);
186void PaletteEditor::load()
188 auto dialog = QFileDialog(
this, tr(
"Load palette"), QString(), paletteFilter());
189 dialog.setAcceptMode(QFileDialog::AcceptOpen);
190 if (dialog.exec() != QDialog::Accepted) {
193 auto pal = QPalette();
194 auto errorMessage = QString();
195 if (loadPalette(dialog.selectedFiles().constFirst(), &pal, &errorMessage)) {
200 QMessageBox::warning(
this, tr(
"Error reading palette"), errorMessage);
204void PaletteEditor::save()
206 auto dialog = QFileDialog(
this, tr(
"Save palette"), QString(), paletteFilter());
207 dialog.setAcceptMode(QFileDialog::AcceptSave);
208 dialog.setDefaultSuffix(paletteSuffix());
209 if (dialog.exec() != QDialog::Accepted) {
212 auto errorMessage = QString();
213 if (!savePalette(dialog.selectedFiles().constFirst(),
palette(), &errorMessage)) {
214 QMessageBox::warning(
this, tr(
"Error writing palette"), errorMessage);
218void PaletteEditor::paletteChanged(
const QPalette &palette)
220 m_modelUpdated =
true;
221 if (!m_paletteUpdated) {
224 m_modelUpdated =
false;
227void PaletteEditor::buildPalette()
229 setPalette(QPalette(m_ui->buildButton->color()));
232void PaletteEditor::updateStyledButton()
234 m_ui->buildButton->setColor(
palette().color(QPalette::Active, QPalette::Button));
240 auto parentPalette = parentPal;
241 const auto mask = init.
242#
if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
248 using MaskType = std::remove_cv_t<
decltype(mask)>;
249 for (
int i = 0; i < static_cast<int>(QPalette::NColorRoles); ++i) {
250 if (mask & (
static_cast<MaskType
>(1) <<
static_cast<MaskType
>(i))) {
253 parentPalette.setBrush(
254 QPalette::Active,
static_cast<QPalette::ColorRole
>(i), init.brush(QPalette::Active,
static_cast<QPalette::ColorRole
>(i)));
255 parentPalette.setBrush(
256 QPalette::Inactive,
static_cast<QPalette::ColorRole
>(i), init.brush(QPalette::Inactive,
static_cast<QPalette::ColorRole
>(i)));
257 parentPalette.setBrush(
258 QPalette::Disabled,
static_cast<QPalette::ColorRole
>(i), init.brush(QPalette::Disabled,
static_cast<QPalette::ColorRole
>(i)));
260 dlg.setPalette(init, parentPalette);
262 const int result = dlg.exec();
266 return result == QDialog::Accepted ? dlg.palette() : init;
270 : QAbstractTableModel(parent)
273 const QMetaObject *meta = metaObject();
274 const QMetaProperty
property = meta->property(meta->indexOfProperty(
"colorRole"));
275 const QMetaEnum enumerator =
property.enumerator();
276 for (
int r = QPalette::WindowText; r < QPalette::NColorRoles; ++r) {
277 m_roleNames[
static_cast<QPalette::ColorRole
>(r)] = QLatin1String(enumerator.key(r));
283 return static_cast<int>(m_roleNames.count());
293 if (!index.isValid() || index.row() < 0 || index.row() >= QPalette::NColorRoles || index.column() < 0 || index.column() >= 4) {
297 if (index.column() == 0) {
298 if (role == Qt::DisplayRole) {
299 return m_roleNames[
static_cast<QPalette::ColorRole
>(index.row())];
301 if (role == Qt::EditRole) {
302 const auto mask = m_palette.
303#
if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
309 using MaskType = std::remove_cv_t<
decltype(mask)>;
310 return mask & (
static_cast<MaskType
>(1) <<
static_cast<MaskType
>(index.row()));
315 return m_palette.brush(columnToGroup(index.column()),
static_cast<QPalette::ColorRole
>(index.row()));
322 if (!index.isValid()) {
326 if (index.column() != 0 && role ==
BrushRole) {
327 const QBrush br = qvariant_cast<QBrush>(value);
328 const QPalette::ColorRole r =
static_cast<QPalette::ColorRole
>(index.row());
329 const QPalette::ColorGroup g = columnToGroup(index.column());
330 m_palette.setBrush(g, r, br);
332 QModelIndex idxBegin = PaletteModel::index(r, 0);
333 QModelIndex idxEnd = PaletteModel::index(r, 3);
335 m_palette.setBrush(QPalette::Inactive, r, br);
337 case QPalette::WindowText:
339 case QPalette::ButtonText:
343 m_palette.setBrush(QPalette::Disabled, QPalette::WindowText, br);
344 m_palette.setBrush(QPalette::Disabled, QPalette::Dark, br);
345 m_palette.setBrush(QPalette::Disabled, QPalette::Text, br);
346 m_palette.setBrush(QPalette::Disabled, QPalette::ButtonText, br);
347 idxBegin = PaletteModel::index(0, 0);
348 idxEnd = PaletteModel::index(
static_cast<int>(m_roleNames.count()) - 1, 3);
350 case QPalette::Window:
351 m_palette.setBrush(QPalette::Disabled, QPalette::Base, br);
352 m_palette.setBrush(QPalette::Disabled, QPalette::Window, br);
353 idxBegin = PaletteModel::index(QPalette::Base, 0);
355 case QPalette::Highlight:
356#if (QT_VERSION >= QT_VERSION_CHECK(6, 6, 0))
357 case QPalette::Accent:
361 m_palette.setBrush(QPalette::Disabled, r, br);
366 emit dataChanged(idxBegin, idxEnd);
369 if (index.column() == 0 && role == Qt::EditRole) {
370 auto mask = m_palette.
371#
if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
377 const bool isMask = qvariant_cast<bool>(value);
378 const int r = index.row();
380 mask |= (
static_cast<decltype(mask)
>(1) <<
static_cast<decltype(mask)
>(r));
383 QPalette::Active,
static_cast<QPalette::ColorRole
>(r), m_parentPalette.brush(QPalette::Active,
static_cast<QPalette::ColorRole
>(r)));
384 m_palette.setBrush(QPalette::Inactive,
static_cast<QPalette::ColorRole
>(r),
385 m_parentPalette.brush(QPalette::Inactive,
static_cast<QPalette::ColorRole
>(r)));
386 m_palette.setBrush(QPalette::Disabled,
static_cast<QPalette::ColorRole
>(r),
387 m_parentPalette.brush(QPalette::Disabled,
static_cast<QPalette::ColorRole
>(r)));
388 mask &= ~static_cast<decltype(mask)>((
static_cast<decltype(mask)
>(1) <<
static_cast<decltype(mask)
>(index.row())));
391#
if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
392 setResolveMask(mask);
393 m_palette = m_palette.resolve(m_palette)
399 const QModelIndex idxEnd = PaletteModel::index(r, 3);
400 emit dataChanged(index, idxEnd);
408 if (!index.isValid())
409 return Qt::ItemIsEnabled;
410 return Qt::ItemIsEditable | Qt::ItemIsEnabled;
415 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
417 return tr(
"Color Role");
418 if (section == groupToColumn(QPalette::Active))
420 if (section == groupToColumn(QPalette::Inactive))
421 return tr(
"Inactive");
422 if (section == groupToColumn(QPalette::Disabled))
423 return tr(
"Disabled");
435 m_parentPalette = parentPalette;
437 const QModelIndex idxBegin = index(0, 0);
438 const QModelIndex idxEnd = index(
static_cast<int>(m_roleNames.count()) - 1, 3);
439 emit dataChanged(idxBegin, idxEnd);
442QPalette::ColorGroup PaletteModel::columnToGroup(
int index)
const
445 return QPalette::Active;
447 return QPalette::Inactive;
448 return QPalette::Disabled;
451int PaletteModel::groupToColumn(QPalette::ColorGroup group)
const
453 if (group == QPalette::Active)
455 if (group == QPalette::Inactive)
465 auto *
const layout =
new QHBoxLayout(
this);
466 layout->setContentsMargins(0, 0, 0, 0);
467 layout->addWidget(m_button);
469 setFocusProxy(m_button);
474 m_button->setColor(
brush.color());
480 return QBrush(m_button->color());
483void BrushEditor::brushChanged()
496 , m_label(new QLabel(this))
499 QHBoxLayout *layout =
new QHBoxLayout(
this);
500 layout->setContentsMargins(0, 0, 0, 0);
501 layout->setSpacing(0);
503 layout->addWidget(m_label);
504 m_label->setAutoFillBackground(
true);
505 m_label->setIndent(3);
506 setFocusProxy(m_label);
508 auto *
const button =
new QToolButton(
this);
509 button->setToolButtonStyle(Qt::ToolButtonIconOnly);
510 button->setIcon(QIcon::fromTheme(QStringLiteral(
"edit-clear")));
511 button->setIconSize(QSize(8, 8));
512 button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding));
513 layout->addWidget(button);
514 connect(button, &QAbstractButton::clicked,
this, &RoleEditor::emitResetProperty);
519 m_label->setText(label);
528 m_label->setFont(font);
537void RoleEditor::emitResetProperty()
544 : QItemDelegate(parent)
550 if (index.column() == 0) {
556 using BrushEditorWidgetSignal = void (
BrushEditor::*)(QWidget *);
559 connect(editor,
static_cast<BrushEditorWidgetSignal
>(&
BrushEditor::changed),
this, &ColorDelegate::commitData);
560 editor->setFocusPolicy(Qt::NoFocus);
561 editor->installEventFilter(
const_cast<ColorDelegate *
>(
this));
567 if (index.column() == 0) {
568 const auto mask = qvariant_cast<bool>(index.model()->data(index, Qt::EditRole));
569 auto *
const editor =
static_cast<RoleEditor *
>(ed);
571 const auto colorName = qvariant_cast<QString>(index.model()->data(index, Qt::DisplayRole));
572 editor->setLabel(colorName);
574 const auto br = qvariant_cast<QBrush>(index.model()->data(index,
BrushRole));
575 auto *
const editor =
static_cast<BrushEditor *
>(ed);
582 if (index.column() == 0) {
583 const auto *
const editor =
static_cast<RoleEditor *
>(ed);
584 const auto mask = editor->
edited();
585 model->setData(index, mask, Qt::EditRole);
587 const auto *
const editor =
static_cast<BrushEditor *
>(ed);
588 if (editor->changed()) {
589 QBrush br = editor->brush();
597 QItemDelegate::updateEditorGeometry(ed, option, index);
598 ed->setGeometry(ed->geometry().adjusted(0, 0, -1, -1));
603 QStyleOptionViewItem option = opt;
604 const auto mask = qvariant_cast<bool>(index.model()->data(index, Qt::EditRole));
605 if (index.column() == 0 && mask) {
606 option.font.setBold(
true);
608 auto br = qvariant_cast<QBrush>(index.model()->data(index,
BrushRole));
609 if (br.style() == Qt::LinearGradientPattern || br.style() == Qt::RadialGradientPattern || br.style() == Qt::ConicalGradientPattern) {
611 painter->translate(option.rect.x(), option.rect.y());
612 painter->scale(option.rect.width(), option.rect.height());
613 QGradient gr = *(br.gradient());
614 gr.setCoordinateMode(QGradient::LogicalMode);
616 painter->fillRect(0, 0, 1, 1, br);
620 painter->setBrushOrigin(option.rect.x(), option.rect.y());
621 painter->fillRect(option.rect, br);
624 QItemDelegate::paint(painter, option, index);
626 const QColor color =
static_cast<QRgb
>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &option));
627 const QPen oldPen = painter->pen();
628 painter->setPen(QPen(color));
630 painter->drawLine(option.rect.right(), option.rect.y(), option.rect.right(), option.rect.bottom());
631 painter->drawLine(option.rect.x(), option.rect.bottom(), option.rect.right(), option.rect.bottom());
632 painter->setPen(oldPen);
637 return QItemDelegate::sizeHint(opt, index) + QSize(4, 4);
The BrushEditor class is used by PaletteEditor.
void setBrush(const QBrush &brush)
BrushEditor(QWidget *parent=nullptr)
The ColorDelegate class is used by PaletteEditor.
void setModelData(QWidget *ed, QAbstractItemModel *model, const QModelIndex &index) const override
void updateEditorGeometry(QWidget *ed, const QStyleOptionViewItem &option, const QModelIndex &index) const override
void setEditorData(QWidget *ed, const QModelIndex &index) const override
void paint(QPainter *painter, const QStyleOptionViewItem &opt, const QModelIndex &index) const override
QSize sizeHint(const QStyleOptionViewItem &opt, const QModelIndex &index) const override
ColorDelegate(QObject *parent=nullptr)
QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
~PaletteEditor() override
static QPalette getPalette(QWidget *parent, const QPalette &init=QPalette(), const QPalette &parentPal=QPalette(), int *result=nullptr)
PaletteEditor(QWidget *parent)
bool event(QEvent *event) override
void setPalette(const QPalette &palette)
The PaletteModel class is used by PaletteEditor.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
QPalette getPalette() const
QVariant data(const QModelIndex &index, int role) const override
PaletteModel(QObject *parent=nullptr)
bool setData(const QModelIndex &index, const QVariant &value, int role) override
void setPalette(const QPalette &palette, const QPalette &parentPalette)
void paletteChanged(const QPalette &palette)
The RoleEditor class is used by PaletteEditor.
void changed(QWidget *widget)
RoleEditor(QWidget *parent=nullptr)
void setLabel(const QString &label)