Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
paletteeditor.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3
5
6#include <qdesigner_utils_p.h>
7#include <iconloader_p.h>
8#include <qtcolorbutton_p.h>
9
10#include <private/formbuilderextra_p.h>
11#include <private/ui4_p.h>
12
13#include <QtDesigner/abstractformeditor.h>
14#include <QtDesigner/abstractformwindowmanager.h>
15
16#include <QtWidgets/qfiledialog.h>
17#include <QtWidgets/qmessagebox.h>
18#include <QtWidgets/qpushbutton.h>
19#include <QtWidgets/qtoolbutton.h>
20#include <QtWidgets/qlabel.h>
21#include <QtWidgets/qmenu.h>
22#include <QtWidgets/qheaderview.h>
23#include <QtWidgets/qstyle.h>
24
25#include <QtGui/qaction.h>
26#if QT_CONFIG(clipboard)
27# include <QtGui/qclipboard.h>
28#endif
29#include <QtGui/qguiapplication.h>
30#include <QtGui/qpainter.h>
31#include <QtGui/qscreen.h>
32
33#include <QtCore/qfile.h>
34#include <QtCore/qmetaobject.h>
35#include <QtCore/qsavefile.h>
36#include <QtCore/qxmlstream.h>
37
39
40using namespace Qt::StringLiterals;
41
42namespace qdesigner_internal {
43
44enum { BrushRole = 33 };
45
46PaletteEditor::PaletteEditor(QDesignerFormEditorInterface *core, QWidget *parent) :
47 QDialog(parent),
48 m_paletteModel(new PaletteModel(this)),
49 m_core(core)
50{
51 ui.setupUi(this);
52 auto saveButton = ui.buttonBox->addButton(tr("Save..."), QDialogButtonBox::ActionRole);
53 connect(saveButton, &QPushButton::clicked, this, &PaletteEditor::save);
54 auto loadButton = ui.buttonBox->addButton(tr("Load..."), QDialogButtonBox::ActionRole);
55 connect(loadButton, &QPushButton::clicked, this, &PaletteEditor::load);
56
57 connect(ui.buildButton, &QtColorButton::colorChanged,
58 this, &PaletteEditor::buildButtonColorChanged);
59 connect(ui.activeRadio, &QAbstractButton::clicked,
60 this, &PaletteEditor::activeRadioClicked);
61 connect(ui.inactiveRadio, &QAbstractButton::clicked,
62 this, &PaletteEditor::inactiveRadioClicked);
63 connect(ui.disabledRadio, &QAbstractButton::clicked,
64 this, &PaletteEditor::disabledRadioClicked);
65 connect(ui.computeRadio, &QAbstractButton::clicked,
66 this, &PaletteEditor::computeRadioClicked);
67 connect(ui.detailsRadio, &QAbstractButton::clicked,
68 this, &PaletteEditor::detailsRadioClicked);
69
70 ui.paletteView->setModel(m_paletteModel);
71 ui.previewGroupBox->setTitle(tr("Preview (%1)").arg(style()->objectName()));
72 updatePreviewPalette();
73 updateStyledButton();
74 ui.paletteView->setModel(m_paletteModel);
75 ColorDelegate *delegate = new ColorDelegate(core, this);
76 ui.paletteView->setItemDelegate(delegate);
77 ui.paletteView->setEditTriggers(QAbstractItemView::AllEditTriggers);
78 connect(m_paletteModel, &PaletteModel::paletteChanged,
79 this, &PaletteEditor::paletteChanged);
80 ui.paletteView->setSelectionBehavior(QAbstractItemView::SelectRows);
81 ui.paletteView->setDragEnabled(true);
82 ui.paletteView->setDropIndicatorShown(true);
83 ui.paletteView->setRootIsDecorated(false);
84 ui.paletteView->setColumnHidden(2, true);
85 ui.paletteView->setColumnHidden(3, true);
86 ui.paletteView->setContextMenuPolicy(Qt::CustomContextMenu);
87 connect(ui.paletteView, &QWidget::customContextMenuRequested,
88 this, &PaletteEditor::viewContextMenuRequested);
89
90 const auto itemRect = ui.paletteView->visualRect(m_paletteModel->index(0, 0));
91 const int minHeight = qMin(itemRect.height() * QPalette::NColorRoles,
92 (screen()->geometry().height() * 2) / 3);
93 ui.paletteView->setMinimumSize({itemRect.width() * 4, minHeight});
94}
95
96PaletteEditor::~PaletteEditor() = default;
97
99{
100 return m_editPalette;
101}
102
103void PaletteEditor::setPalette(const QPalette &palette)
104{
105 m_editPalette = palette;
106 for (int r = 0; r < static_cast<int>(QPalette::NColorRoles); ++r) {
107 for (int g = 0; g < static_cast<int>(QPalette::NColorGroups); ++g) {
108 const auto role = static_cast<QPalette::ColorRole>(r);
109 const auto group = static_cast<QPalette::ColorGroup>(g);
110 if (!palette.isBrushSet(group, role))
111 m_editPalette.setBrush(group, role, m_parentPalette.brush(group, role));
112 }
113 }
114 m_editPalette.setResolveMask(palette.resolveMask());
115 updatePreviewPalette();
116 updateStyledButton();
117 m_paletteUpdated = true;
118 if (!m_modelUpdated)
119 m_paletteModel->setPalette(m_editPalette, m_parentPalette);
120 m_paletteUpdated = false;
121}
122
123void PaletteEditor::setPalette(const QPalette &palette, const QPalette &parentPalette)
124{
125 m_parentPalette = parentPalette;
126 setPalette(palette);
127}
128
129void PaletteEditor::buildButtonColorChanged()
130{
131 buildPalette();
132}
133
134void PaletteEditor::activeRadioClicked()
135{
136 m_currentColorGroup = QPalette::Active;
137 updatePreviewPalette();
138}
139
140void PaletteEditor::inactiveRadioClicked()
141{
142 m_currentColorGroup = QPalette::Inactive;
143 updatePreviewPalette();
144}
145
146void PaletteEditor::disabledRadioClicked()
147{
148 m_currentColorGroup = QPalette::Disabled;
149 updatePreviewPalette();
150}
151
152void PaletteEditor::computeRadioClicked()
153{
154 if (m_compute)
155 return;
156 ui.paletteView->setColumnHidden(2, true);
157 ui.paletteView->setColumnHidden(3, true);
158 m_compute = true;
159 m_paletteModel->setCompute(true);
160}
161
162void PaletteEditor::detailsRadioClicked()
163{
164 if (!m_compute)
165 return;
166 const int w = ui.paletteView->columnWidth(1);
167 ui.paletteView->setColumnHidden(2, false);
168 ui.paletteView->setColumnHidden(3, false);
169 QHeaderView *header = ui.paletteView->header();
170 header->resizeSection(1, w / 3);
171 header->resizeSection(2, w / 3);
172 header->resizeSection(3, w / 3);
173 m_compute = false;
174 m_paletteModel->setCompute(false);
175}
176
177void PaletteEditor::paletteChanged(const QPalette &palette)
178{
179 m_modelUpdated = true;
180 if (!m_paletteUpdated)
181 setPalette(palette);
182 m_modelUpdated = false;
183}
184
185void PaletteEditor::buildPalette()
186{
187 const QColor btn = ui.buildButton->color();
188 const QPalette temp = QPalette(btn);
189 setPalette(temp);
190}
191
192void PaletteEditor::updatePreviewPalette()
193{
194 const QPalette::ColorGroup g = currentColorGroup();
195 // build the preview palette
196 const QPalette currentPalette = palette();
197 QPalette previewPalette;
198 for (int i = QPalette::WindowText; i < QPalette::NColorRoles; i++) {
199 const QPalette::ColorRole r = static_cast<QPalette::ColorRole>(i);
200 const QBrush &br = currentPalette.brush(g, r);
201 previewPalette.setBrush(QPalette::Active, r, br);
202 previewPalette.setBrush(QPalette::Inactive, r, br);
203 previewPalette.setBrush(QPalette::Disabled, r, br);
204 }
205 ui.previewFrame->setPreviewPalette(previewPalette);
206
207 const bool enabled = g != QPalette::Disabled;
208 ui.previewFrame->setEnabled(enabled);
209 ui.previewFrame->setSubWindowActive(g != QPalette::Inactive);
210}
211
212void PaletteEditor::updateStyledButton()
213{
214 ui.buildButton->setColor(palette().color(QPalette::Active, QPalette::Button));
215}
216
217QPalette PaletteEditor::getPalette(QDesignerFormEditorInterface *core, QWidget* parent, const QPalette &init,
218 const QPalette &parentPal, int *ok)
219{
220 PaletteEditor dlg(core, parent);
221 QPalette parentPalette(parentPal);
222 for (int r = 0; r < static_cast<int>(QPalette::NColorRoles); ++r) {
223 for (int g = 0; g < static_cast<int>(QPalette::NColorGroups); ++g) {
224 const auto role = static_cast<QPalette::ColorRole>(r);
225 const auto group = static_cast<QPalette::ColorGroup>(g);
226 if (!init.isBrushSet(group, role))
227 parentPalette.setBrush(group, role, init.brush(group, role));
228 }
229 }
230 dlg.setPalette(init, parentPalette);
231
232 const int result = dlg.exec();
233 if (ok) *ok = result;
234
235 return result == QDialog::Accepted ? dlg.palette() : init;
236}
237
238void PaletteEditor::viewContextMenuRequested(QPoint pos)
239{
240 const auto index = ui.paletteView->indexAt(pos);
241 if (!index.isValid())
242 return;
243 auto brush = m_paletteModel->brushAt(index);
244 const auto color = brush.color();
245 if (!m_contextMenu) {
246 m_contextMenu = new QMenu(this);
247 m_lighterAction = m_contextMenu->addAction(tr("Lighter"));
248 m_darkerAction = m_contextMenu->addAction(tr("Darker"));
249 m_copyColorAction = m_contextMenu->addAction(QString());
250 }
251 const auto rgb = color.rgb() & 0xffffffu;
252 const bool isBlack = rgb == 0u;
253 m_lighterAction->setEnabled(rgb != 0xffffffu);
254 m_darkerAction->setDisabled(isBlack);
255 m_copyColorAction->setText(tr("Copy color %1").arg(color.name()));
256 auto action = m_contextMenu->exec(ui.paletteView->viewport()->mapToGlobal(pos));
257 if (!action)
258 return;
259 if (action == m_copyColorAction) {
260#if QT_CONFIG(clipboard)
261 QGuiApplication::clipboard()->setText(color.name());
262#endif
263 return;
264 }
265 // Fall through to darker/lighter. Note: black cannot be made lighter due
266 // to QTBUG-9343.
267 enum : int { factor = 120 };
268 const QColor newColor = action == m_darkerAction
269 ? color.darker(factor)
270 : (isBlack ? QColor(0x404040u) : color.lighter(factor));
271 brush.setColor(newColor);
272 m_paletteModel->setData(index, QVariant(brush), BrushRole);
273}
274
275static inline QString paletteFilter()
276{
277 return PaletteEditor::tr("QPalette UI file (*.xml)");
278}
279
280static bool savePalette(const QString &fileName, const QPalette &pal, QString *errorMessage)
281{
282 QSaveFile file;
283 file.setFileName(fileName);
284 if (!file.open(QIODevice::WriteOnly)) {
285 *errorMessage = PaletteEditor::tr("Cannot open %1 for writing: %2")
286 .arg(QDir::toNativeSeparators(fileName), file.errorString());
287 return false;
288 }
289 {
290 QScopedPointer<DomPalette> domPalette(QFormBuilderExtra::savePalette(pal));
291 QXmlStreamWriter writer(&file);
292 writer.setAutoFormatting(true);
293 writer.setAutoFormattingIndent(1);
294 writer.writeStartDocument();
295 domPalette->write(writer);
296 writer.writeEndDocument();
297 }
298 const bool result = file.commit();
299 if (!result) {
300 *errorMessage = PaletteEditor::tr("Cannot write %1: %2")
301 .arg(QDir::toNativeSeparators(fileName), file.errorString());
302 }
303 return result;
304}
305
306static QString msgCannotReadPalette(const QString &fileName, const QXmlStreamReader &reader,
307 const QString &why)
308{
309 return PaletteEditor::tr("Cannot read palette from %1:%2:%3")
310 .arg(QDir::toNativeSeparators(fileName)).arg(reader.lineNumber()).arg(why);
311}
312
313static inline QString msgCannotReadPalette(const QString &fileName, const QXmlStreamReader &reader)
314{
315 return msgCannotReadPalette(fileName, reader, reader.errorString());
316}
317
318static bool loadPalette(const QString &fileName, QPalette *pal, QString *errorMessage)
319{
320 QFile file(fileName);
321 if (!file.open(QIODevice::ReadOnly)) {
322 *errorMessage = PaletteEditor::tr("Cannot open %1 for reading: %2")
323 .arg(QDir::toNativeSeparators(fileName), file.errorString());
324 return false;
325 }
326 QXmlStreamReader reader(&file);
327 if (!reader.readNextStartElement()) {
328 *errorMessage = msgCannotReadPalette(fileName, reader);
329 return false;
330 }
331 if (reader.name() != "palette"_L1) {
332 const auto why = PaletteEditor::tr("Invalid element \"%1\", expected \"palette\".")
333 .arg(reader.name().toString());
334 *errorMessage = msgCannotReadPalette(fileName, reader, why);
335 return false;
336 }
337 QScopedPointer<DomPalette> domPalette(new DomPalette);
338 domPalette->read(reader);
339 if (reader.hasError()) {
340 *errorMessage = msgCannotReadPalette(fileName, reader);
341 return false;
342 }
343 *pal = QFormBuilderExtra::loadPalette(domPalette.data());
344 return true;
345}
346
347void PaletteEditor::save()
348{
349 QFileDialog dialog(this, tr("Save Palette"), QString(), paletteFilter());
350 dialog.setAcceptMode(QFileDialog::AcceptSave);
351 dialog.setDefaultSuffix(u"xml"_s);
352 while (dialog.exec() == QDialog::Accepted) {
353 QString errorMessage;
354 if (savePalette(dialog.selectedFiles().constFirst(), palette(), &errorMessage))
355 break;
356 QMessageBox::warning(this, tr("Error Writing Palette"), errorMessage);
357 }
358}
359
360void PaletteEditor::load()
361{
362 QFileDialog dialog(this, tr("Load Palette"), QString(), paletteFilter());
363 dialog.setAcceptMode(QFileDialog::AcceptOpen);
364 while (dialog.exec() == QDialog::Accepted) {
365 QPalette pal;
366 QString errorMessage;
367 if (loadPalette(dialog.selectedFiles().constFirst(), &pal, &errorMessage)) {
368 setPalette(pal);
369 break;
370 }
371 QMessageBox::warning(this, tr("Error Reading Palette"), errorMessage);
372 }
373}
374
375//////////////////////
376// Column 0: Role name and reset button. Uses a boolean value indicating
377// whether the role is modified for the edit role.
378// Column 1: Color group Active
379// Column 2: Color group Inactive (visibility depending on m_compute/detail radio group)
380// Column 3: Color group Disabled
381
382PaletteModel::PaletteModel(QObject *parent) :
383 QAbstractTableModel(parent)
384{
385 const QMetaObject *meta = metaObject();
386 const int index = meta->indexOfProperty("colorRole");
387 const QMetaProperty p = meta->property(index);
388 const QMetaEnum e = p.enumerator();
389 m_roleEntries.reserve(QPalette::NColorRoles);
390 for (int r = QPalette::WindowText; r < QPalette::NColorRoles; r++) {
391 const auto role = static_cast<QPalette::ColorRole>(r);
392 if (role != QPalette::NoRole)
393 m_roleEntries.append({QLatin1StringView(e.key(r)), role});
394 }
395}
396
397int PaletteModel::rowCount(const QModelIndex &) const
398{
399 return m_roleEntries.size();
400}
401
402int PaletteModel::columnCount(const QModelIndex &) const
403{
404 return 4;
405}
406
407QBrush PaletteModel::brushAt(const QModelIndex &index) const
408{
409 return m_palette.brush(columnToGroup(index.column()), roleAt(index.row()));
410}
411
412// Palette resolve mask with all group bits for a row/role
413quint64 PaletteModel::rowMask(const QModelIndex &index) const
414{
415 return paletteResolveMask(roleAt(index.row()));
416}
417
418QVariant PaletteModel::data(const QModelIndex &index, int role) const
419{
420 if (!index.isValid())
421 return QVariant();
422 if (index.row() < 0 || index.row() >= m_roleEntries.size())
423 return QVariant();
424 if (index.column() < 0 || index.column() >= 4)
425 return QVariant();
426
427 if (index.column() == 0) { // Role name/bold print if changed
428 if (role == Qt::DisplayRole)
429 return m_roleEntries.at(index.row()).name;
430 if (role == Qt::EditRole)
431 return (rowMask(index) & m_palette.resolveMask()) != 0;
432 return QVariant();
433 }
434 if (role == Qt::ToolTipRole)
435 return brushAt(index).color().name();
436 if (role == BrushRole)
437 return brushAt(index);
438 return QVariant();
439}
440
441bool PaletteModel::setData(const QModelIndex &index, const QVariant &value, int role)
442{
443 if (!index.isValid())
444 return false;
445
446 const int row = index.row();
447 const auto colorRole = roleAt(row);
448
449 if (index.column() != 0 && role == BrushRole) {
450 const QBrush br = qvariant_cast<QBrush>(value);
451 const QPalette::ColorGroup g = columnToGroup(index.column());
452 m_palette.setBrush(g, colorRole, br);
453
454 QModelIndex idxBegin = PaletteModel::index(row, 0);
455 QModelIndex idxEnd = PaletteModel::index(row, 3);
456 if (m_compute) {
457 m_palette.setBrush(QPalette::Inactive, colorRole, br);
458 switch (colorRole) {
459 case QPalette::WindowText:
460 case QPalette::Text:
461 case QPalette::ButtonText:
462 case QPalette::Base:
463 break;
464 case QPalette::Dark:
465 m_palette.setBrush(QPalette::Disabled, QPalette::WindowText, br);
466 m_palette.setBrush(QPalette::Disabled, QPalette::Dark, br);
467 m_palette.setBrush(QPalette::Disabled, QPalette::Text, br);
468 m_palette.setBrush(QPalette::Disabled, QPalette::ButtonText, br);
469 idxBegin = PaletteModel::index(0, 0);
470 idxEnd = PaletteModel::index(m_roleEntries.size() - 1, 3);
471 break;
472 case QPalette::Window:
473 m_palette.setBrush(QPalette::Disabled, QPalette::Base, br);
474 m_palette.setBrush(QPalette::Disabled, QPalette::Window, br);
475 idxBegin = PaletteModel::index(rowOf(QPalette::Base), 0);
476 break;
477 case QPalette::Highlight:
478 //m_palette.setBrush(QPalette::Disabled, QPalette::Highlight, c.dark(120));
479 break;
480 default:
481 m_palette.setBrush(QPalette::Disabled, colorRole, br);
482 break;
483 }
484 }
485 emit paletteChanged(m_palette);
486 emit dataChanged(idxBegin, idxEnd);
487 return true;
488 }
489 if (index.column() == 0 && role == Qt::EditRole) {
490 auto mask = m_palette.resolveMask();
491 const bool isMask = qvariant_cast<bool>(value);
492 const auto bitMask = rowMask(index);
493 if (isMask) {
494 mask |= bitMask;
495 } else {
496 m_palette.setBrush(QPalette::Active, colorRole,
497 m_parentPalette.brush(QPalette::Active, colorRole));
498 m_palette.setBrush(QPalette::Inactive, colorRole,
499 m_parentPalette.brush(QPalette::Inactive, colorRole));
500 m_palette.setBrush(QPalette::Disabled, colorRole,
501 m_parentPalette.brush(QPalette::Disabled, colorRole));
502
503 mask &= ~bitMask;
504 }
505 m_palette.setResolveMask(mask);
506 emit paletteChanged(m_palette);
507 const QModelIndex idxEnd = PaletteModel::index(row, 3);
508 emit dataChanged(index, idxEnd);
509 return true;
510 }
511 return false;
512}
513
514Qt::ItemFlags PaletteModel::flags(const QModelIndex &index) const
515{
516 if (!index.isValid())
517 return Qt::ItemIsEnabled;
518 return Qt::ItemIsEditable | Qt::ItemIsEnabled;
519}
520
521QVariant PaletteModel::headerData(int section, Qt::Orientation orientation,
522 int role) const
523{
524 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
525 if (section == 0)
526 return tr("Color Role");
527 if (section == groupToColumn(QPalette::Active))
528 return tr("Active");
529 if (section == groupToColumn(QPalette::Inactive))
530 return tr("Inactive");
531 if (section == groupToColumn(QPalette::Disabled))
532 return tr("Disabled");
533 }
534 return QVariant();
535}
536
538{
539 return m_palette;
540}
541
542void PaletteModel::setPalette(const QPalette &palette, const QPalette &parentPalette)
543{
544 m_parentPalette = parentPalette;
545 m_palette = palette;
546 const QModelIndex idxBegin = index(0, 0);
547 const QModelIndex idxEnd = index(m_roleEntries.size() - 1, 3);
548 emit dataChanged(idxBegin, idxEnd);
549}
550
551QPalette::ColorGroup PaletteModel::columnToGroup(int index) const
552{
553 if (index == 1)
554 return QPalette::Active;
555 if (index == 2)
556 return QPalette::Inactive;
557 return QPalette::Disabled;
558}
559
560int PaletteModel::groupToColumn(QPalette::ColorGroup group) const
561{
562 if (group == QPalette::Active)
563 return 1;
564 if (group == QPalette::Inactive)
565 return 2;
566 return 3;
567}
568
569int PaletteModel::rowOf(QPalette::ColorRole role) const
570{
571 for (qsizetype row = 0, size = m_roleEntries.size(); row < size; ++row) {
572 if (m_roleEntries.at(row).role == role)
573 return row;
574 }
575 return -1;
576}
577
578//////////////////////////
579
580BrushEditor::BrushEditor(QDesignerFormEditorInterface *core, QWidget *parent) :
581 QWidget(parent),
582 m_button(new QtColorButton(this)),
583 m_core(core)
584{
585 QLayout *layout = new QHBoxLayout(this);
586 layout->setContentsMargins(QMargins());
587 layout->addWidget(m_button);
588 connect(m_button, &QtColorButton::colorChanged, this, &BrushEditor::brushChanged);
589 setFocusProxy(m_button);
590}
591
592void BrushEditor::setBrush(const QBrush &brush)
593{
594 m_button->setColor(brush.color());
595 m_changed = false;
596}
597
599{
600 return QBrush(m_button->color());
601}
602
603void BrushEditor::brushChanged()
604{
605 m_changed = true;
606 emit changed(this);
607}
608
609bool BrushEditor::changed() const
610{
611 return m_changed;
612}
613
614//////////////////////////
615
616RoleEditor::RoleEditor(QWidget *parent) :
617 QWidget(parent),
618 m_label(new QLabel(this))
619{
620 QHBoxLayout *layout = new QHBoxLayout(this);
621 layout->setContentsMargins(QMargins());
622 layout->setSpacing(0);
623
624 layout->addWidget(m_label);
625 m_label->setAutoFillBackground(true);
626 m_label->setIndent(3); // ### hardcode it should have the same value of textMargin in QItemDelegate
627 setFocusProxy(m_label);
628
629 QToolButton *button = new QToolButton(this);
630 button->setToolButtonStyle(Qt::ToolButtonIconOnly);
631 button->setIcon(createIconSet("resetproperty.png"_L1));
632 button->setIconSize(QSize(8,8));
633 button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding));
634 layout->addWidget(button);
635 connect(button, &QAbstractButton::clicked, this, &RoleEditor::emitResetProperty);
636}
637
638void RoleEditor::setLabel(const QString &label)
639{
640 m_label->setText(label);
641}
642
643void RoleEditor::setEdited(bool on)
644{
645 QFont font;
646 if (on)
647 font.setBold(on);
648 m_label->setFont(font);
649 m_edited = on;
650}
651
652bool RoleEditor::edited() const
653{
654 return m_edited;
655}
656
657void RoleEditor::emitResetProperty()
658{
659 setEdited(false);
660 emit changed(this);
661}
662
663//////////////////////////
664ColorDelegate::ColorDelegate(QDesignerFormEditorInterface *core, QObject *parent) :
665 QItemDelegate(parent),
666 m_core(core)
667{
668}
669
670QWidget *ColorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &,
671 const QModelIndex &index) const
672{
673 QWidget *ed = nullptr;
674 if (index.column() == 0) {
675 RoleEditor *editor = new RoleEditor(parent);
676 connect(editor, &RoleEditor::changed, this, &ColorDelegate::commitData);
677 //editor->setFocusPolicy(Qt::NoFocus);
678 //editor->installEventFilter(const_cast<ColorDelegate *>(this));
679 ed = editor;
680 } else {
681 BrushEditor *editor = new BrushEditor(m_core, parent);
682 connect(editor, QOverload<QWidget *>::of(&BrushEditor::changed),
683 this, &ColorDelegate::commitData);
684 editor->setFocusPolicy(Qt::NoFocus);
685 editor->installEventFilter(const_cast<ColorDelegate *>(this));
686 ed = editor;
687 }
688 return ed;
689}
690
691void ColorDelegate::setEditorData(QWidget *ed, const QModelIndex &index) const
692{
693 if (index.column() == 0) {
694 const bool mask = qvariant_cast<bool>(index.model()->data(index, Qt::EditRole));
695 RoleEditor *editor = static_cast<RoleEditor *>(ed);
696 editor->setEdited(mask);
697 const QString colorName = qvariant_cast<QString>(index.model()->data(index, Qt::DisplayRole));
698 editor->setLabel(colorName);
699 } else {
700 const QBrush br = qvariant_cast<QBrush>(index.model()->data(index, BrushRole));
701 BrushEditor *editor = static_cast<BrushEditor *>(ed);
702 editor->setBrush(br);
703 }
704}
705
706void ColorDelegate::setModelData(QWidget *ed, QAbstractItemModel *model,
707 const QModelIndex &index) const
708{
709 if (index.column() == 0) {
710 RoleEditor *editor = static_cast<RoleEditor *>(ed);
711 const bool mask = editor->edited();
712 model->setData(index, mask, Qt::EditRole);
713 } else {
714 BrushEditor *editor = static_cast<BrushEditor *>(ed);
715 if (editor->changed()) {
716 QBrush br = editor->brush();
717 model->setData(index, br, BrushRole);
718 }
719 }
720}
721
722void ColorDelegate::updateEditorGeometry(QWidget *ed,
723 const QStyleOptionViewItem &option, const QModelIndex &index) const
724{
725 QItemDelegate::updateEditorGeometry(ed, option, index);
726 ed->setGeometry(ed->geometry().adjusted(0, 0, -1, -1));
727}
728
729void ColorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opt,
730 const QModelIndex &index) const
731{
732 QStyleOptionViewItem option = opt;
733 const bool mask = qvariant_cast<bool>(index.model()->data(index, Qt::EditRole));
734 if (index.column() == 0 && mask) {
735 option.font.setBold(true);
736 }
737 QBrush br = qvariant_cast<QBrush>(index.model()->data(index, BrushRole));
738 if (br.style() == Qt::LinearGradientPattern ||
739 br.style() == Qt::RadialGradientPattern ||
740 br.style() == Qt::ConicalGradientPattern) {
741 painter->save();
742 painter->translate(option.rect.x(), option.rect.y());
743 painter->scale(option.rect.width(), option.rect.height());
744 QGradient gr = *(br.gradient());
745 gr.setCoordinateMode(QGradient::LogicalMode);
746 br = QBrush(gr);
747 painter->fillRect(0, 0, 1, 1, br);
748 painter->restore();
749 } else {
750 painter->save();
751 painter->setBrushOrigin(option.rect.x(), option.rect.y());
752 painter->fillRect(option.rect, br);
753 painter->restore();
754 }
755 QItemDelegate::paint(painter, option, index);
756
757
758 const QColor color = static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor, &option));
759 const QPen oldPen = painter->pen();
760 painter->setPen(QPen(color));
761
762 painter->drawLine(option.rect.right(), option.rect.y(),
763 option.rect.right(), option.rect.bottom());
764 painter->drawLine(option.rect.x(), option.rect.bottom(),
765 option.rect.right(), option.rect.bottom());
766 painter->setPen(oldPen);
767}
768
769QSize ColorDelegate::sizeHint(const QStyleOptionViewItem &opt, const QModelIndex &index) const
770{
771 return QItemDelegate::sizeHint(opt, index) + QSize(4, 4);
772}
773}
774
775QT_END_NAMESPACE
void setBrush(const QBrush &brush)
QSize sizeHint(const QStyleOptionViewItem &opt, const QModelIndex &index) const override
This pure abstract function must be reimplemented if you want to provide custom rendering.
void paint(QPainter *painter, const QStyleOptionViewItem &opt, const QModelIndex &index) const override
This pure abstract function must be reimplemented if you want to provide custom rendering.
void setPalette(const QPalette &palette)
void setPalette(const QPalette &palette, const QPalette &parentPalette)
QBrush brushAt(const QModelIndex &index) const
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Returns the data for the given role and section in the header with the specified orientation.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of columns for the children of the given parent.
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Returns the number of rows under the given parent.
quint64 rowMask(const QModelIndex &index) const
QVariant data(const QModelIndex &index, int role) const override
Returns the data stored under the given role for the item referred to by the index.
bool setData(const QModelIndex &index, const QVariant &value, int role) override
Sets the role data for the item at index to value.
Qt::ItemFlags flags(const QModelIndex &index) const override
Returns the item flags for the given index.
void setPalette(const QPalette &palette, const QPalette &parentPalette)
Combined button and popup list for selecting options.
Auxiliary methods to store/retrieve settings.
static QString paletteFilter()
static bool savePalette(const QString &fileName, const QPalette &pal, QString *errorMessage)
static QString msgCannotReadPalette(const QString &fileName, const QXmlStreamReader &reader)
static QString msgCannotReadPalette(const QString &fileName, const QXmlStreamReader &reader, const QString &why)
static bool loadPalette(const QString &fileName, QPalette *pal, QString *errorMessage)