1 // qsamplerPaletteForm.cpp
2 //
3 /****************************************************************************
4    Copyright (C) 2004-2020, rncbc aka Rui Nuno Capela. All rights reserved.
5    Copyright (C) 2007, Christian Schoenebeck
6 
7    This program is free software; you can redistribute it and/or
8    modify it under the terms of the GNU General Public License
9    as published by the Free Software Foundation; either version 2
10    of the License, or (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License along
18    with this program; if not, write to the Free Software Foundation, Inc.,
19    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 
21 *****************************************************************************/
22 
23 #include "qsamplerAbout.h"
24 #include "qsamplerPaletteForm.h"
25 
26 #include "ui_qsamplerPaletteForm.h"
27 
28 #include <QMetaProperty>
29 #include <QToolButton>
30 #include <QHeaderView>
31 #include <QLabel>
32 
33 #include <QHash>
SeqDriver(JackDriver * p_jackSync,int p_portCount,void * callback_context,bool (* midi_event_received_callback)(void * context,MidiEvent ev),void (* tick_callback)(void * context,bool echo_from_trig))34 
35 #include <QPainter>
36 #include <QStyle>
37 #include <QStyleOption>
38 
39 #include <QColorDialog>
40 #include <QFileDialog>
41 #include <QMessageBox>
42 
43 
44 namespace QSampler {
45 
46 // Local static consts.
47 static const char *ColorThemesGroup   = "/ColorThemes/";
48 
49 static const char *PaletteEditorGroup = "/PaletteEditor/";
50 static const char *DefaultDirKey      = "DefaultDir";
51 static const char *ShowDetailsKey     = "ShowDetails";
52 static const char *DefaultSuffix      = "conf";
53 
54 
55 static struct
56 {
57 	const char *key;
58 	QPalette::ColorRole value;
59 
60 } g_colorRoles[] = {
61 
62 	{ "Window",          QPalette::Window          },
63 	{ "WindowText",      QPalette::WindowText      },
64 	{ "Button",          QPalette::Button          },
65 	{ "ButtonText",      QPalette::ButtonText      },
66 	{ "Light",           QPalette::Light           },
67 	{ "Midlight",        QPalette::Midlight        },
68 	{ "Dark",            QPalette::Dark            },
69 	{ "Mid",             QPalette::Mid             },
70 	{ "Text",            QPalette::Text            },
71 	{ "BrightText",      QPalette::BrightText      },
72 	{ "Base",            QPalette::Base            },
73 	{ "AlternateBase",   QPalette::AlternateBase   },
74 	{ "Shadow",          QPalette::Shadow          },
75 	{ "Highlight",       QPalette::Highlight       },
76 	{ "HighlightedText", QPalette::HighlightedText },
77 	{ "Link",            QPalette::Link            },
78 	{ "LinkVisited",     QPalette::LinkVisited     },
79 	{ "ToolTipBase",     QPalette::ToolTipBase     },
80 	{ "ToolTipText",     QPalette::ToolTipText     },
81 #if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)
82 	{ "PlaceholderText", QPalette::PlaceholderText },
83 #endif
84 	{ "NoRole",          QPalette::NoRole          },
85 
86 	{  nullptr,          QPalette::NoRole          }
87 };
88 
89 
90 //-------------------------------------------------------------------------
91 // Qsampler::PaletteForm
92 
93 PaletteForm::PaletteForm ( QWidget *parent, const QPalette& pal )
94 	: QDialog(parent), p_ui(new Ui::qsamplerPaletteForm), m_ui(*p_ui)
95 {
96 	m_ui.setupUi(this);
97 
98 	m_settings = nullptr;
99 	m_owner = false;
100 
101 	m_modelUpdated = false;
102 	m_paletteUpdated = false;
103 	m_dirtyCount = 0;
104 	m_dirtyTotal = 0;
105 
106 	updateGenerateButton();
107 
108 	m_paletteModel = new PaletteModel(this);
109 	m_ui.paletteView->setModel(m_paletteModel);
110 	ColorDelegate *delegate = new ColorDelegate(this);
111 	m_ui.paletteView->setItemDelegate(delegate);
112 	m_ui.paletteView->setEditTriggers(QAbstractItemView::AllEditTriggers);
113 //	m_ui.paletteView->setAlternatingRowColors(true);
114 	m_ui.paletteView->setSelectionBehavior(QAbstractItemView::SelectRows);
115 	m_ui.paletteView->setDragEnabled(true);
116 	m_ui.paletteView->setDropIndicatorShown(true);
117 	m_ui.paletteView->setRootIsDecorated(false);
118 	m_ui.paletteView->setColumnHidden(2, true);
119 	m_ui.paletteView->setColumnHidden(3, true);
120 
121 	QObject::connect(m_ui.nameCombo,
122 		SIGNAL(editTextChanged(const QString&)),
123 		SLOT(nameComboChanged(const QString&)));
124 	QObject::connect(m_ui.saveButton,
125 		SIGNAL(clicked()),
126 		SLOT(saveButtonClicked()));
127 	QObject::connect(m_ui.deleteButton,
128 		SIGNAL(clicked()),
129 		SLOT(deleteButtonClicked()));
130 
131 	QObject::connect(m_ui.generateButton,
132 		SIGNAL(changed()),
133 		SLOT(generateButtonChanged()));
134 	QObject::connect(m_ui.resetButton,
135 		SIGNAL(clicked()),
136 		SLOT(resetButtonClicked()));
137 	QObject::connect(m_ui.detailsCheck,
138 		SIGNAL(clicked()),
139 		SLOT(detailsCheckClicked()));
140 	QObject::connect(m_ui.importButton,
141 		SIGNAL(clicked()),
142 		SLOT(importButtonClicked()));
143 	QObject::connect(m_ui.exportButton,
144 		SIGNAL(clicked()),
145 		SLOT(exportButtonClicked()));
146 
147 	QObject::connect(m_paletteModel,
148 		SIGNAL(paletteChanged(const QPalette&)),
149 		SLOT(paletteChanged(const QPalette&)));
150 
151 	QObject::connect(m_ui.dialogButtons,
152 		SIGNAL(accepted()),
153 		SLOT(accept()));
154 	QObject::connect(m_ui.dialogButtons,
155 		SIGNAL(rejected()),
156 		SLOT(reject()));
157 
158 	setPalette(pal, pal);
159 
160 	QDialog::adjustSize();
161 }
162 
163 
164 PaletteForm::~PaletteForm (void)
165 {
166 	setSettings(nullptr);
167 }
168 
169 
170 void PaletteForm::setPalette ( const QPalette& pal )
171 {
172 	m_palette = pal;
173 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
174 	const uint mask = pal.resolveMask();
175 #else
176 	const uint mask = pal.resolve();
177 #endif
178 	for (int i = 0; g_colorRoles[i].key; ++i) {
179 		if ((mask & (1 << i)) == 0) {
180 			const QPalette::ColorRole cr = QPalette::ColorRole(i);
181 			m_palette.setBrush(QPalette::Active, cr,
182 				m_parentPalette.brush(QPalette::Active, cr));
183 			m_palette.setBrush(QPalette::Inactive, cr,
184 				m_parentPalette.brush(QPalette::Inactive, cr));
185 			m_palette.setBrush(QPalette::Disabled, cr,
186 				m_parentPalette.brush(QPalette::Disabled, cr));
187 		}
188 	}
189 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
190 	m_palette.setResolveMask(mask);
191 #else
192 	m_palette.resolve(mask);
193 #endif
194 
195 	updateGenerateButton();
196 
197 	m_paletteUpdated = true;
198 	if (!m_modelUpdated)
199 		m_paletteModel->setPalette(m_palette, m_parentPalette);
200 	m_paletteUpdated = false;
201 }
202 
203 
204 void PaletteForm::setPalette ( const QPalette& pal, const QPalette& parentPal )
205 {
206 	m_parentPalette = parentPal;
207 
208 	setPalette(pal);
209 }
210 
211 
212 const QPalette& PaletteForm::palette (void) const
213 {
214 	return m_palette;
215 }
216 
217 
218 void PaletteForm::setSettings ( QSettings *settings, bool owner )
219 {
220 	if (m_settings && m_owner)
221 		delete m_settings;
222 
223 	m_settings = settings;
224 	m_owner = owner;
225 
226 	m_ui.detailsCheck->setChecked(isShowDetails());
227 
228 	updateNamedPaletteList();
229 	updateDialogButtons();
230 }
231 
232 
233 QSettings *PaletteForm::settings (void) const
234 {
235 	return m_settings;
236 }
237 
238 
239 void PaletteForm::nameComboChanged ( const QString& name )
240 {
241 	if (m_dirtyCount > 0 || m_ui.nameCombo->findText(name) < 0) {
242 		updateDialogButtons();
243 	} else {
244 		setPaletteName(name);
245 		++m_dirtyTotal;
246 	}
247 }
248 
249 
250 void PaletteForm::saveButtonClicked (void)
251 {
252 	const QString& name = m_ui.nameCombo->currentText();
253 	if (!name.isEmpty()) {
254 		saveNamedPalette(name, m_palette);
255 		setPalette(m_palette, m_palette);
256 		updateNamedPaletteList();
257 		resetButtonClicked();
258 	}
259 }
260 
261 
262 void PaletteForm::deleteButtonClicked (void)
263 {
264 	const QString& name = m_ui.nameCombo->currentText();
265 	if (m_ui.nameCombo->findText(name) >= 0) {
266 		deleteNamedPalette(name);
267 		updateNamedPaletteList();
268 		updateDialogButtons();
269 	}
270 }
271 
272 
273 void PaletteForm::generateButtonChanged (void)
274 {
275 	const QColor& color
276 		= m_ui.generateButton->brush().color();
277 	const QPalette& pal = QPalette(color);
278 	setPalette(pal);
279 
280 	++m_dirtyCount;
281 	updateDialogButtons();
282 }
283 
284 
285 void PaletteForm::resetButtonClicked (void)
286 {
287 	const bool blocked = blockSignals(true);
288 
289 	for (int i = 0; g_colorRoles[i].key; ++i) {
290 		const QPalette::ColorRole cr = g_colorRoles[i].value;
291 		const QModelIndex& index = m_paletteModel->index(cr, 0);
292 		m_paletteModel->setData(index, false, Qt::EditRole);
293 	}
294 
295 	m_dirtyCount = 0;
296 	updateDialogButtons();
297 
298 	blockSignals(blocked);
299 }
300 
301 
302 void PaletteForm::detailsCheckClicked (void)
303 {
304 	const int cw = (m_ui.paletteView->viewport()->width() >> 2);
305 	QHeaderView *header = m_ui.paletteView->header();
306 	header->resizeSection(0, cw);
307 	if (m_ui.detailsCheck->isChecked()) {
308 		m_ui.paletteView->setColumnHidden(2, false);
309 		m_ui.paletteView->setColumnHidden(3, false);
310 		header->resizeSection(1, cw);
311 		header->resizeSection(2, cw);
312 		header->resizeSection(3, cw);
313 		m_paletteModel->setGenerate(false);
314 	} else {
315 		m_ui.paletteView->setColumnHidden(2, true);
316 		m_ui.paletteView->setColumnHidden(3, true);
317 		header->resizeSection(1, cw * 3);
318 		m_paletteModel->setGenerate(true);
319 	}
320 }
321 
322 
323 void PaletteForm::importButtonClicked (void)
324 {
325 	const QString& title
326 		= tr("Import File - %1").arg(QDialog::windowTitle());
327 
328 	QStringList filters;
329 	filters.append(tr("Palette files (*.%1)").arg(DefaultSuffix));
330 	filters.append(tr("All files (*.*)"));
331 
332 	const QString& filename
333 		= QFileDialog::getOpenFileName(this,
334 			title, defaultDir(), filters.join(";;"));
335 
336 	if (filename.isEmpty())
337 		return;
338 
339 	int imported = 0;
340 	QSettings settings(filename, QSettings::IniFormat);
341 	settings.beginGroup(ColorThemesGroup);
342 	QStringListIterator name_iter(settings.childGroups());
343 	while (name_iter.hasNext()) {
344 		const QString& name = name_iter.next();
345 		if (!name.isEmpty()) {
346 			QPalette pal;
347 			int result = 0;
348 		#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
349 			uint mask = pal.resolveMask();
350 		#else
351 			uint mask = pal.resolve();
352 		#endif
353 			settings.beginGroup(name + '/');
354 			QStringListIterator iter(settings.childKeys());
355 			while (iter.hasNext()) {
356 				const QString& key = iter.next();
357 				const QPalette::ColorRole cr
358 					= PaletteForm::colorRole(key);
359 				const QStringList& clist
360 					= settings.value(key).toStringList();
361 				if (clist.count() == 3) {
362 					pal.setColor(QPalette::Active,   cr, QColor(clist.at(0)));
363 					pal.setColor(QPalette::Inactive, cr, QColor(clist.at(1)));
364 					pal.setColor(QPalette::Disabled, cr, QColor(clist.at(2)));
365 					mask &= ~(1 << int(cr));
366 					++result;
367 				}
368 			}
369 		#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
370 			pal.setResolveMask(mask);
371 		#else
372 			pal.resolve(mask);
373 		#endif
374 			settings.endGroup();
375 			if (result > 0) {
376 				saveNamedPalette(name, pal);
377 				setPaletteName(name);
378 				++imported;
379 			}
380 		}
381 	}
382 	settings.endGroup();
383 
384 	if (imported > 0) {
385 		updateNamedPaletteList();
386 		resetButtonClicked();
387 		setDefaultDir(QFileInfo(filename).absolutePath());
388 	} else {
389 		QMessageBox::warning(this,
390 			tr("Warning - %1").arg(QDialog::windowTitle()),
391 			tr("Could not import from file:\n\n"
392 			"%1\n\nSorry.").arg(filename));
393 	}
394 }
395 
396 
397 void PaletteForm::exportButtonClicked (void)
398 {
399 	const QString& title
400 		= tr("Export File - %1").arg(QDialog::windowTitle());
401 
402 	QStringList filters;
403 	filters.append(tr("Palette files (*.%1)").arg(DefaultSuffix));
404 	filters.append(tr("All files (*.*)"));
405 
406 	QString dirname = defaultDir();
407 	if (!dirname.isEmpty())
408 		dirname.append(QDir::separator());
409 	dirname.append(paletteName() + '.' + DefaultSuffix);
410 
411 	const QString& filename
412 		= QFileDialog::getSaveFileName(this,
413 			title, dirname, filters.join(";;"));
414 
415 	if (filename.isEmpty())
416 		return;
417 
418 	const QPalette& pal = m_palette;
419 
420 	QSettings settings(filename, QSettings::IniFormat);
421 	settings.beginGroup(ColorThemesGroup);
422 	settings.beginGroup(QFileInfo(filename).baseName() + '/');
423 	for (int i = 0; g_colorRoles[i].key; ++i) {
424 		const QString& key
425 			= QString::fromLatin1(g_colorRoles[i].key);
426 		const QPalette::ColorRole cr
427 			= g_colorRoles[i].value;
428 		QStringList clist;
429 		clist.append(pal.color(QPalette::Active,   cr).name());
430 		clist.append(pal.color(QPalette::Inactive, cr).name());
431 		clist.append(pal.color(QPalette::Disabled, cr).name());
432 		settings.setValue(key, clist);
433 	}
434 	settings.endGroup();
435 	settings.endGroup();
436 
437 	setDefaultDir(QFileInfo(filename).absolutePath());
438 }
439 
440 
441 void PaletteForm::paletteChanged ( const QPalette& pal )
442 {
443 	m_modelUpdated = true;
444 	if (!m_paletteUpdated)
445 		setPalette(pal);
446 	m_modelUpdated = false;
447 
448 	++m_dirtyCount;
449 	updateDialogButtons();
450 }
451 
452 
453 void PaletteForm::setPaletteName ( const QString& name )
454 {
455 	const bool blocked = m_ui.nameCombo->blockSignals(true);
456 
457 	m_ui.nameCombo->setEditText(name);
458 
459 	QPalette pal;
460 
461 	if (namedPalette(m_settings, name, pal, true))
462 		setPalette(pal, pal);
463 
464 	m_dirtyCount = 0;
465 	updateDialogButtons();
466 
467 	m_ui.nameCombo->blockSignals(blocked);
468 }
469 
470 
471 QString PaletteForm::paletteName (void) const
472 {
473 	return m_ui.nameCombo->currentText();
474 }
475 
476 
477 void PaletteForm::updateNamedPaletteList (void)
478 {
479 	const bool blocked = m_ui.nameCombo->blockSignals(true);
480 	const QString old_name = m_ui.nameCombo->currentText();
481 
482 	m_ui.nameCombo->clear();
483 	m_ui.nameCombo->insertItems(0, namedPaletteList());
484 //	m_ui.nameCombo->model()->sort(0);
485 
486 	const int i = m_ui.nameCombo->findText(old_name);
487 	if (i >= 0)
488 		m_ui.nameCombo->setCurrentIndex(i);
489 	else
490 		m_ui.nameCombo->setEditText(old_name);
491 
492 	m_ui.nameCombo->blockSignals(blocked);
493 }
494 
495 
496 void PaletteForm::updateGenerateButton (void)
497 {
498 	m_ui.generateButton->setBrush(
499 		m_palette.brush(QPalette::Active, QPalette::Button));
500 }
501 
502 
503 void PaletteForm::updateDialogButtons (void)
504 {
505 	const QString& name = m_ui.nameCombo->currentText();
506 	const int i = m_ui.nameCombo->findText(name);
507 	m_ui.saveButton->setEnabled(!name.isEmpty() && (m_dirtyCount > 0 || i < 0));
508 	m_ui.deleteButton->setEnabled(i >= 0);
509 	m_ui.resetButton->setEnabled(m_dirtyCount > 0);
510 	m_ui.exportButton->setEnabled(!name.isEmpty() || i >= 0);
511 	m_ui.dialogButtons->button(QDialogButtonBox::Ok)->setEnabled(i >= 0);
512 	if (name == "Wonton Soup" || name == "KXStudio") {
513 		m_ui.saveButton->setEnabled(false);
514 		m_ui.deleteButton->setEnabled(false);
515 		m_ui.exportButton->setEnabled(false);
516 	}
517 }
518 
519 
520 bool PaletteForm::namedPalette ( const QString& name, QPalette& pal )
521 {
522 	return namedPalette(m_settings, name, pal);
523 }
524 
525 
526 bool PaletteForm::namedPalette (
527 	QSettings *settings, const QString& name, QPalette& pal, bool fixup )
528 {
529 	int result = 0;
530 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
531 	uint mask = pal.resolve();
532 #endif
533 
534 	// Custom color themes...
535 	if (name == "Wonton Soup") {
536 		pal.setColor(QPalette::Active,   QPalette::Window, QColor(73, 78, 88));
537 		pal.setColor(QPalette::Inactive, QPalette::Window, QColor(73, 78, 88));
538 		pal.setColor(QPalette::Disabled, QPalette::Window, QColor(64, 68, 77));
539 		pal.setColor(QPalette::Active,   QPalette::WindowText, QColor(182, 193, 208));
540 		pal.setColor(QPalette::Inactive, QPalette::WindowText, QColor(182, 193, 208));
541 		pal.setColor(QPalette::Disabled, QPalette::WindowText, QColor(97, 104, 114));
542 		pal.setColor(QPalette::Active,   QPalette::Base, QColor(60, 64, 72));
543 		pal.setColor(QPalette::Inactive, QPalette::Base, QColor(60, 64, 72));
544 		pal.setColor(QPalette::Disabled, QPalette::Base, QColor(52, 56, 63));
545 		pal.setColor(QPalette::Active,   QPalette::AlternateBase, QColor(67, 71, 80));
546 		pal.setColor(QPalette::Inactive, QPalette::AlternateBase, QColor(67, 71, 80));
547 		pal.setColor(QPalette::Disabled, QPalette::AlternateBase, QColor(59, 62, 70));
548 		pal.setColor(QPalette::Active,   QPalette::ToolTipBase, QColor(182, 193, 208));
549 		pal.setColor(QPalette::Inactive, QPalette::ToolTipBase, QColor(182, 193, 208));
550 		pal.setColor(QPalette::Disabled, QPalette::ToolTipBase, QColor(182, 193, 208));
551 		pal.setColor(QPalette::Active,   QPalette::ToolTipText, QColor(42, 44, 48));
552 		pal.setColor(QPalette::Inactive, QPalette::ToolTipText, QColor(42, 44, 48));
553 		pal.setColor(QPalette::Disabled, QPalette::ToolTipText, QColor(42, 44, 48));
554 		pal.setColor(QPalette::Active,   QPalette::Text, QColor(210, 222, 240));
555 		pal.setColor(QPalette::Inactive, QPalette::Text, QColor(210, 222, 240));
556 		pal.setColor(QPalette::Disabled, QPalette::Text, QColor(99, 105, 115));
557 		pal.setColor(QPalette::Active,   QPalette::Button, QColor(82, 88, 99));
558 		pal.setColor(QPalette::Inactive, QPalette::Button, QColor(82, 88, 99));
559 		pal.setColor(QPalette::Disabled, QPalette::Button, QColor(72, 77, 87));
560 		pal.setColor(QPalette::Active,   QPalette::ButtonText, QColor(210, 222, 240));
561 		pal.setColor(QPalette::Inactive, QPalette::ButtonText, QColor(210, 222, 240));
562 		pal.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(111, 118, 130));
563 		pal.setColor(QPalette::Active,   QPalette::BrightText, QColor(255, 255, 255));
564 		pal.setColor(QPalette::Inactive, QPalette::BrightText, QColor(255, 255, 255));
565 		pal.setColor(QPalette::Disabled, QPalette::BrightText, QColor(255, 255, 255));
566 		pal.setColor(QPalette::Active,   QPalette::Light, QColor(95, 101, 114));
567 		pal.setColor(QPalette::Inactive, QPalette::Light, QColor(95, 101, 114));
568 		pal.setColor(QPalette::Disabled, QPalette::Light, QColor(86, 92, 104));
569 		pal.setColor(QPalette::Active,   QPalette::Midlight, QColor(84, 90, 101));
570 		pal.setColor(QPalette::Inactive, QPalette::Midlight, QColor(84, 90, 101));
571 		pal.setColor(QPalette::Disabled, QPalette::Midlight, QColor(75, 81, 91));
572 		pal.setColor(QPalette::Active,   QPalette::Dark, QColor(40, 43, 49));
573 		pal.setColor(QPalette::Inactive, QPalette::Dark, QColor(40, 43, 49));
574 		pal.setColor(QPalette::Disabled, QPalette::Dark, QColor(35, 38, 43));
575 		pal.setColor(QPalette::Active,   QPalette::Mid, QColor(63, 68, 76));
576 		pal.setColor(QPalette::Inactive, QPalette::Mid, QColor(63, 68, 76));
577 		pal.setColor(QPalette::Disabled, QPalette::Mid, QColor(56, 59, 67));
578 		pal.setColor(QPalette::Active,   QPalette::Shadow, QColor(29, 31, 35));
579 		pal.setColor(QPalette::Inactive, QPalette::Shadow, QColor(29, 31, 35));
580 		pal.setColor(QPalette::Disabled, QPalette::Shadow, QColor(25, 27, 30));
581 		pal.setColor(QPalette::Active,   QPalette::Highlight, QColor(120, 136, 156));
582 		pal.setColor(QPalette::Inactive, QPalette::Highlight, QColor(81, 90, 103));
583 		pal.setColor(QPalette::Disabled, QPalette::Highlight, QColor(64, 68, 77));
584 		pal.setColor(QPalette::Active,   QPalette::HighlightedText, QColor(209, 225, 244));
585 		pal.setColor(QPalette::Inactive, QPalette::HighlightedText, QColor(182, 193, 208));
586 		pal.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(97, 104, 114));
587 		pal.setColor(QPalette::Active,   QPalette::Link, QColor(156, 212, 255));
588 		pal.setColor(QPalette::Inactive, QPalette::Link, QColor(156, 212, 255));
589 		pal.setColor(QPalette::Disabled, QPalette::Link, QColor(82, 102, 119));
590 		pal.setColor(QPalette::Active,   QPalette::LinkVisited, QColor(64, 128, 255));
591 		pal.setColor(QPalette::Inactive, QPalette::LinkVisited, QColor(64, 128, 255));
592 		pal.setColor(QPalette::Disabled, QPalette::LinkVisited, QColor(54, 76, 119));
593 	#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
594 		mask = 0;
595 	#endif
596 		++result;
597 	}
598 	else
599 	if (name == "KXStudio") {
600 		pal.setColor(QPalette::Active,   QPalette::Window, QColor(17, 17, 17));
601 		pal.setColor(QPalette::Inactive, QPalette::Window, QColor(17, 17, 17));
602 		pal.setColor(QPalette::Disabled, QPalette::Window, QColor(14, 14, 14));
603 		pal.setColor(QPalette::Active,   QPalette::WindowText, QColor(240, 240, 240));
604 		pal.setColor(QPalette::Inactive, QPalette::WindowText, QColor(240, 240, 240));
605 		pal.setColor(QPalette::Disabled, QPalette::WindowText, QColor(83, 83, 83));
606 		pal.setColor(QPalette::Active,   QPalette::Base, QColor(7, 7, 7));
607 		pal.setColor(QPalette::Inactive, QPalette::Base, QColor(7, 7, 7));
608 		pal.setColor(QPalette::Disabled, QPalette::Base, QColor(6, 6, 6));
609 		pal.setColor(QPalette::Active,   QPalette::AlternateBase, QColor(14, 14, 14));
610 		pal.setColor(QPalette::Inactive, QPalette::AlternateBase, QColor(14, 14, 14));
611 		pal.setColor(QPalette::Disabled, QPalette::AlternateBase, QColor(12, 12, 12));
612 		pal.setColor(QPalette::Active,   QPalette::ToolTipBase, QColor(4, 4, 4));
613 		pal.setColor(QPalette::Inactive, QPalette::ToolTipBase, QColor(4, 4, 4));
614 		pal.setColor(QPalette::Disabled, QPalette::ToolTipBase, QColor(4, 4, 4));
615 		pal.setColor(QPalette::Active,   QPalette::ToolTipText, QColor(230, 230, 230));
616 		pal.setColor(QPalette::Inactive, QPalette::ToolTipText, QColor(230, 230, 230));
617 		pal.setColor(QPalette::Disabled, QPalette::ToolTipText, QColor(230, 230, 230));
618 		pal.setColor(QPalette::Active,   QPalette::Text, QColor(230, 230, 230));
619 		pal.setColor(QPalette::Inactive, QPalette::Text, QColor(230, 230, 230));
620 		pal.setColor(QPalette::Disabled, QPalette::Text, QColor(74, 74, 74));
621 		pal.setColor(QPalette::Active,   QPalette::Button, QColor(28, 28, 28));
622 		pal.setColor(QPalette::Inactive, QPalette::Button, QColor(28, 28, 28));
623 		pal.setColor(QPalette::Disabled, QPalette::Button, QColor(24, 24, 24));
624 		pal.setColor(QPalette::Active,   QPalette::ButtonText, QColor(240, 240, 240));
625 		pal.setColor(QPalette::Inactive, QPalette::ButtonText, QColor(240, 240, 240));
626 		pal.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(90, 90, 90));
627 		pal.setColor(QPalette::Active,   QPalette::BrightText, QColor(255, 255, 255));
628 		pal.setColor(QPalette::Inactive, QPalette::BrightText, QColor(255, 255, 255));
629 		pal.setColor(QPalette::Disabled, QPalette::BrightText, QColor(255, 255, 255));
630 		pal.setColor(QPalette::Active,   QPalette::Light, QColor(191, 191, 191));
631 		pal.setColor(QPalette::Inactive, QPalette::Light, QColor(191, 191, 191));
632 		pal.setColor(QPalette::Disabled, QPalette::Light, QColor(191, 191, 191));
633 		pal.setColor(QPalette::Active,   QPalette::Midlight, QColor(155, 155, 155));
634 		pal.setColor(QPalette::Inactive, QPalette::Midlight, QColor(155, 155, 155));
635 		pal.setColor(QPalette::Disabled, QPalette::Midlight, QColor(155, 155, 155));
636 		pal.setColor(QPalette::Active,   QPalette::Dark, QColor(129, 129, 129));
637 		pal.setColor(QPalette::Inactive, QPalette::Dark, QColor(129, 129, 129));
638 		pal.setColor(QPalette::Disabled, QPalette::Dark, QColor(129, 129, 129));
639 		pal.setColor(QPalette::Active,   QPalette::Mid, QColor(94, 94, 94));
640 		pal.setColor(QPalette::Inactive, QPalette::Mid, QColor(94, 94, 94));
641 		pal.setColor(QPalette::Disabled, QPalette::Mid, QColor(94, 94, 94));
642 		pal.setColor(QPalette::Active,   QPalette::Shadow, QColor(155, 155, 155));
643 		pal.setColor(QPalette::Inactive, QPalette::Shadow, QColor(155, 155, 155));
644 		pal.setColor(QPalette::Disabled, QPalette::Shadow, QColor(155, 155, 155));
645 		pal.setColor(QPalette::Active,   QPalette::Highlight, QColor(60, 60, 60));
646 		pal.setColor(QPalette::Inactive, QPalette::Highlight, QColor(34, 34, 34));
647 		pal.setColor(QPalette::Disabled, QPalette::Highlight, QColor(14, 14, 14));
648 		pal.setColor(QPalette::Active,   QPalette::HighlightedText, QColor(255, 255, 255));
649 		pal.setColor(QPalette::Inactive, QPalette::HighlightedText, QColor(240, 240, 240));
650 		pal.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(83, 83, 83));
651 		pal.setColor(QPalette::Active,   QPalette::Link, QColor(100, 100, 230));
652 		pal.setColor(QPalette::Inactive, QPalette::Link, QColor(100, 100, 230));
653 		pal.setColor(QPalette::Disabled, QPalette::Link, QColor(34, 34, 74));
654 		pal.setColor(QPalette::Active,   QPalette::LinkVisited, QColor(230, 100, 230));
655 		pal.setColor(QPalette::Inactive, QPalette::LinkVisited, QColor(230, 100, 230));
656 		pal.setColor(QPalette::Disabled, QPalette::LinkVisited, QColor(74, 34, 74));
657 	#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
658 		mask = 0;
659 	#endif
660 		++result;
661 	}
662 	else
663 	if (settings) {
664 		settings->beginGroup(ColorThemesGroup);
665 		settings->beginGroup(name + '/');
666 		QStringListIterator iter(settings->childKeys());
667 		while (iter.hasNext()) {
668 			const QString& key = iter.next();
669 			const QPalette::ColorRole cr
670 				= PaletteForm::colorRole(key);
671 			const QStringList& clist
672 				= settings->value(key).toStringList();
673 			if (clist.count() == 3) {
674 				pal.setColor(QPalette::Active,   cr, QColor(clist.at(0)));
675 				pal.setColor(QPalette::Inactive, cr, QColor(clist.at(1)));
676 				pal.setColor(QPalette::Disabled, cr, QColor(clist.at(2)));
677 			#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
678 				mask &= ~(1 << int(cr));
679 			#endif
680 				++result;
681 			}
682 		}
683 		settings->endGroup();
684 		settings->endGroup();
685 	}
686 
687 	// Dark themes grayed/disabled color group fix...
688 	if (!fixup && pal.base().color().value() < 0x7f) {
689 		const QColor& color = pal.window().color();
690 		const int groups = int(QPalette::Active | QPalette::Inactive) + 1;
691 		for (int i = 0; i < groups; ++i) {
692 			const QPalette::ColorGroup cg = QPalette::ColorGroup(i);
693 			pal.setBrush(cg, QPalette::Light,    color.lighter(140));
694 			pal.setBrush(cg, QPalette::Midlight, color.lighter(100));
695 			pal.setBrush(cg, QPalette::Mid,      color.lighter(90));
696 			pal.setBrush(cg, QPalette::Dark,     color.darker(160));
697 			pal.setBrush(cg, QPalette::Shadow,   color.darker(180));
698 		}
699 		pal.setColorGroup(QPalette::Disabled,
700 			pal.windowText().color().darker(),
701 			pal.button(),
702 			pal.light(),
703 			pal.dark(),
704 			pal.mid(),
705 			pal.text().color().darker(),
706 			pal.text().color().lighter(),
707 			pal.base(),
708 			pal.window());
709 	#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
710 		pal.setColor(QPalette::Disabled,
711 			QPalette::Highlight, pal.mid().color());
712 		pal.setColor(QPalette::Disabled,
713 			QPalette::ButtonText, pal.mid().color());
714 	#endif
715 		++result;
716 	}
717 
718 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
719 	pal.resolve(mask);
720 #endif
721 	return (result > 0);
722 }
723 
724 
725 void PaletteForm::saveNamedPalette (
726 	const QString& name, const QPalette& pal )
727 {
728 	if (m_settings && name != "KXStudio" && name != "Wonton Soup") {
729 		m_settings->beginGroup(ColorThemesGroup);
730 		m_settings->beginGroup(name + '/');
731 		for (int i = 0; g_colorRoles[i].key; ++i) {
732 			const QString& key
733 				= QString::fromLatin1(g_colorRoles[i].key);
734 			const QPalette::ColorRole cr
735 				= g_colorRoles[i].value;
736 			QStringList clist;
737 			clist.append(pal.color(QPalette::Active,   cr).name());
738 			clist.append(pal.color(QPalette::Inactive, cr).name());
739 			clist.append(pal.color(QPalette::Disabled, cr).name());
740 			m_settings->setValue(key, clist);
741 		}
742 		m_settings->endGroup();
743 		m_settings->endGroup();
744 		++m_dirtyTotal;
745 	}
746 }
747 
748 
749 void PaletteForm::deleteNamedPalette ( const QString& name )
750 {
751 	if (m_settings) {
752 		m_settings->beginGroup(ColorThemesGroup);
753 		m_settings->remove(name);
754 		m_settings->endGroup();
755 		++m_dirtyTotal;
756 	}
757 }
758 
759 
760 QStringList PaletteForm::namedPaletteList (void)
761 {
762 	return namedPaletteList(m_settings);
763 }
764 
765 
766 QStringList PaletteForm::namedPaletteList ( QSettings *settings )
767 {
768 	QStringList list;
769 	list.append("Wonton Soup");
770 	list.append("KXStudio");
771 
772 	if (settings) {
773 		settings->beginGroup(ColorThemesGroup);
774 		list.append(settings->childGroups());
775 		settings->endGroup();
776 	}
777 
778 	return list;
779 }
780 
781 
782 QPalette::ColorRole PaletteForm::colorRole ( const QString& name )
783 {
784 	static QHash<QString, QPalette::ColorRole> s_colorRoles;
785 
786 	if (s_colorRoles.isEmpty()) {
787 		for (int i = 0; g_colorRoles[i].key; ++i) {
788 			const QString& key
789 				= QString::fromLatin1(g_colorRoles[i].key);
790 			const QPalette::ColorRole value
791 				= g_colorRoles[i].value;
792 			s_colorRoles.insert(key, value);
793 		}
794 	}
795 
796 	return s_colorRoles.value(name, QPalette::NoRole);
797 }
798 
799 
800 bool PaletteForm::isDirty (void) const
801 {
802 	return (m_dirtyTotal > 0);
803 }
804 
805 
806 void PaletteForm::accept (void)
807 {
808 	setShowDetails(m_ui.detailsCheck->isChecked());
809 
810 	if (m_dirtyCount > 0)
811 		saveButtonClicked();
812 
813 	QDialog::accept();
814 }
815 
816 
817 void PaletteForm::reject (void)
818 {
819 	if (m_dirtyCount > 0) {
820 		const QString& name = paletteName();
821 		if (name.isEmpty()) {
822 			if (QMessageBox::warning(this,
823 				tr("Warning - %1").arg(QDialog::windowTitle()),
824 				tr("Some settings have been changed.\n\n"
825 				"Do you want to discard the changes?"),
826 				QMessageBox::Discard |
827 				QMessageBox::Cancel) == QMessageBox::Cancel)
828 				return;
829 		} else {
830 			switch (QMessageBox::warning(this,
831 				tr("Warning - %1").arg(QDialog::windowTitle()),
832 				tr("Some settings have been changed:\n\n"
833 				"\"%1\".\n\nDo you want to save the changes?")
834 				.arg(name),
835 				QMessageBox::Save |
836 				QMessageBox::Discard |
837 				QMessageBox::Cancel)) {
838 			case QMessageBox::Save:
839 				saveButtonClicked();
840 				// Fall thru...
841 			case QMessageBox::Discard:
842 				break;
843 			default: // Cancel...
844 				return;
845 			}
846 		}
847 	}
848 
849 	QDialog::reject();
850 }
851 
852 
853 void PaletteForm::setDefaultDir ( const QString& dir )
854 {
855 	if (m_settings) {
856 		m_settings->beginGroup(PaletteEditorGroup);
857 		m_settings->setValue(DefaultDirKey, dir);
858 		m_settings->endGroup();
859 	}
860 }
861 
862 
863 QString PaletteForm::defaultDir (void) const
864 {
865 	QString dir;
866 
867 	if (m_settings) {
868 		m_settings->beginGroup(PaletteEditorGroup);
869 		dir = m_settings->value(DefaultDirKey).toString();
870 		m_settings->endGroup();
871 	}
872 
873 	return dir;
874 }
875 
876 
877 void PaletteForm::setShowDetails ( bool on )
878 {
879 	if (m_settings) {
880 		m_settings->beginGroup(PaletteEditorGroup);
881 		m_settings->setValue(ShowDetailsKey, on);
882 		m_settings->endGroup();
883 	}
884 }
885 
886 
887 bool PaletteForm::isShowDetails (void) const
888 {
889 	bool on = false;
890 
891 	if (m_settings) {
892 		m_settings->beginGroup(PaletteEditorGroup);
893 		on = m_settings->value(ShowDetailsKey).toBool();
894 		m_settings->endGroup();
895 	}
896 
897 	return on;
898 }
899 
900 
901 void PaletteForm::showEvent ( QShowEvent *event )
902 {
903 	QDialog::showEvent(event);
904 
905 	detailsCheckClicked();
906 }
907 
908 
909 void PaletteForm::resizeEvent ( QResizeEvent *event )
910 {
911 	QDialog::resizeEvent(event);
912 
913 	detailsCheckClicked();
914 }
915 
916 
917 //-------------------------------------------------------------------------
918 // PaletteForm::PaletteModel
919 
920 PaletteForm::PaletteModel::PaletteModel ( QObject *parent )
921 	: QAbstractTableModel(parent)
922 {
923 	for (m_nrows = 0; g_colorRoles[m_nrows].key; ++m_nrows) {
924 		const QPalette::ColorRole value
925 			= g_colorRoles[m_nrows].value;
926 		const QString& key
927 			= QString::fromLatin1(g_colorRoles[m_nrows].key);
928 		m_roleNames.insert(value, key);
929 	}
930 
931 	m_generate = true;
932 }
933 
934 
935 int PaletteForm::PaletteModel::rowCount ( const QModelIndex& ) const
936 {
937 	return m_nrows;
938 }
939 
940 
941 int PaletteForm::PaletteModel::columnCount ( const QModelIndex& ) const
942 {
943 	return 4;
944 }
945 
946 
947 QVariant PaletteForm::PaletteModel::data ( const QModelIndex& index, int role ) const
948 {
949 	if (!index.isValid())
950 		return QVariant();
951 	if (index.row() < 0 || index.row() >= m_nrows)
952 		return QVariant();
953 	if (index.column() < 0 || index.column() >= 4)
954 		return QVariant();
955 
956 	if (index.column() == 0) {
957 		if (role == Qt::DisplayRole)
958 			return m_roleNames.value(QPalette::ColorRole(index.row()));
959 		if (role == Qt::EditRole) {
960 		#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
961 			const uint mask = m_palette.resolveMask();
962 		#else
963 			const uint mask = m_palette.resolve();
964 		#endif
965 			return bool(mask & (1 << index.row()));
966 		}
967 	}
968 	else
969 	if (role == Qt::BackgroundRole) {
970 		return m_palette.color(
971 			columnToGroup(index.column()),
972 			QPalette::ColorRole(index.row()));
973 	}
974 
975 	return QVariant();
976 }
977 
978 
979 bool PaletteForm::PaletteModel::setData (
980 	const QModelIndex& index, const QVariant& value, int role )
981 {
982 	if (!index.isValid())
983 		return false;
984 
985 	if (index.column() != 0 && role == Qt::BackgroundRole) {
986 		const QColor& color = value.value<QColor>();
987 		const QPalette::ColorRole cr = QPalette::ColorRole(index.row());
988 		const QPalette::ColorGroup cg = columnToGroup(index.column());
989 		m_palette.setBrush(cg, cr, color);
990 		QModelIndex index_begin = PaletteModel::index(cr, 0);
991 		QModelIndex index_end = PaletteModel::index(cr, 3);
992 		if (m_generate) {
993 			m_palette.setBrush(QPalette::Inactive, cr, color);
994 			switch (cr) {
995 				case QPalette::WindowText:
996 				case QPalette::Text:
997 				case QPalette::ButtonText:
998 				case QPalette::Base:
999 					break;
1000 				case QPalette::Dark:
1001 					m_palette.setBrush(QPalette::Disabled, QPalette::WindowText, color);
1002 					m_palette.setBrush(QPalette::Disabled, QPalette::Dark, color);
1003 					m_palette.setBrush(QPalette::Disabled, QPalette::Text, color);
1004 					m_palette.setBrush(QPalette::Disabled, QPalette::ButtonText, color);
1005 					index_begin = PaletteModel::index(0, 0);
1006 					index_end = PaletteModel::index(m_nrows - 1, 3);
1007 					break;
1008 				case QPalette::Window:
1009 					m_palette.setBrush(QPalette::Disabled, QPalette::Base, color);
1010 					m_palette.setBrush(QPalette::Disabled, QPalette::Window, color);
1011 					index_begin = PaletteModel::index(QPalette::Base, 0);
1012 					break;
1013 				case QPalette::Highlight:
1014 					m_palette.setBrush(QPalette::Disabled, QPalette::Highlight, color.darker(120));
1015 					break;
1016 				default:
1017 					m_palette.setBrush(QPalette::Disabled, cr, color);
1018 					break;
1019 			}
1020 		}
1021 		emit paletteChanged(m_palette);
1022 		emit dataChanged(index_begin, index_end);
1023 		return true;
1024 	}
1025 
1026 	if (index.column() == 0 && role == Qt::EditRole) {
1027 	#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1028 		uint mask = m_palette.resolveMask();
1029 	#else
1030 		uint mask = m_palette.resolve();
1031 	#endif
1032 		const bool masked = value.value<bool>();
1033 		const int i = index.row();
1034 		if (masked) {
1035 			mask |= (1 << i);
1036 		} else {
1037 			const QPalette::ColorRole cr = QPalette::ColorRole(i);
1038 			m_palette.setBrush(QPalette::Active, cr,
1039 				m_parentPalette.brush(QPalette::Active, cr));
1040 			m_palette.setBrush(QPalette::Inactive, cr,
1041 				m_parentPalette.brush(QPalette::Inactive, cr));
1042 			m_palette.setBrush(QPalette::Disabled, cr,
1043 				m_parentPalette.brush(QPalette::Disabled, cr));
1044 			mask &= ~(1 << i);
1045 		}
1046 	#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
1047 		m_palette.setResolveMask(mask);
1048 	#else
1049 		m_palette.resolve(mask);
1050 	#endif
1051 		emit paletteChanged(m_palette);
1052 		const QModelIndex& index_end = PaletteModel::index(i, 3);
1053 		emit dataChanged(index, index_end);
1054 		return true;
1055 	}
1056 
1057 	return false;
1058 }
1059 
1060 
1061 Qt::ItemFlags PaletteForm::PaletteModel::flags ( const QModelIndex& index ) const
1062 {
1063 	if (!index.isValid())
1064 		return Qt::ItemIsEnabled;
1065 	else
1066 		return Qt::ItemIsEditable | Qt::ItemIsEnabled;
1067 }
1068 
1069 
1070 QVariant PaletteForm::PaletteModel::headerData (
1071 	int section, Qt::Orientation orientation, int role ) const
1072 {
1073 	if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
1074 		if (section == 0)
1075 			return tr("Color Role");
1076 		else
1077 		if (section == groupToColumn(QPalette::Active))
1078 			return tr("Active");
1079 		else
1080 		if (section == groupToColumn(QPalette::Inactive))
1081 			return tr("Inactive");
1082 		else
1083 		if (section == groupToColumn(QPalette::Disabled))
1084 			return tr("Disabled");
1085 	}
1086 
1087 	return QVariant();
1088 }
1089 
1090 
1091 const QPalette& PaletteForm::PaletteModel::palette(void) const
1092 {
1093 	return m_palette;
1094 }
1095 
1096 
1097 void PaletteForm::PaletteModel::setPalette (
1098 	const QPalette& palette, const QPalette& parentPalette )
1099 {
1100 	m_palette = palette;
1101 	m_parentPalette = parentPalette;
1102 
1103 	const QModelIndex& index_begin = index(0, 0);
1104 	const QModelIndex& index_end = index(m_nrows - 1, 3);
1105 	emit dataChanged(index_begin, index_end);
1106 }
1107 
1108 
1109 QPalette::ColorGroup PaletteForm::PaletteModel::columnToGroup ( int index ) const
1110 {
1111 	if (index == 1)
1112 		return QPalette::Active;
1113 	else
1114 	if (index == 2)
1115 		return QPalette::Inactive;
1116 
1117 	return QPalette::Disabled;
1118 }
1119 
1120 
1121 int PaletteForm::PaletteModel::groupToColumn ( QPalette::ColorGroup group ) const
1122 {
1123 	if (group == QPalette::Active)
1124 		return 1;
1125 	else
1126 	if (group == QPalette::Inactive)
1127 		return 2;
1128 
1129 	return 3;
1130 }
1131 
1132 
1133 //-------------------------------------------------------------------------
1134 // QSampler::PaletteForm::ColorDelegate
1135 
1136 QWidget *PaletteForm::ColorDelegate::createEditor ( QWidget *parent,
1137 	const QStyleOptionViewItem&, const QModelIndex& index ) const
1138 {
1139 	QWidget *editor = nullptr;
1140 
1141 	if (index.column() == 0) {
1142 		RoleEditor *ed = new RoleEditor(parent);
1143 		QObject::connect(ed,
1144 			SIGNAL(changed(QWidget *)),
1145 			SIGNAL(commitData(QWidget *)));
1146 	//	ed->setFocusPolicy(Qt::NoFocus);
1147 	//	ed->installEventFilter(const_cast<ColorDelegate *>(this));
1148 		editor = ed;
1149 	} else {
1150 		ColorEditor *ed = new ColorEditor(parent);
1151 		QObject::connect(ed,
1152 			SIGNAL(changed(QWidget *)),
1153 			SIGNAL(commitData(QWidget *)));
1154 		ed->setFocusPolicy(Qt::NoFocus);
1155 		ed->installEventFilter(const_cast<ColorDelegate *>(this));
1156 		editor = ed;
1157 	}
1158 
1159 	return editor;
1160 }
1161 
1162 
1163 void PaletteForm::ColorDelegate::setEditorData (
1164 	QWidget *editor, const QModelIndex& index ) const
1165 {
1166 	if (index.column() == 0) {
1167 		const bool masked
1168 			= index.model()->data(index, Qt::EditRole).value<bool>();
1169 		RoleEditor *ed = static_cast<RoleEditor *>(editor);
1170 		ed->setEdited(masked);
1171 		const QString& colorName
1172 			= index.model()->data(index, Qt::DisplayRole).value<QString>();
1173 		ed->setLabel(colorName);
1174 	} else {
1175 		const QColor& color
1176 			= index.model()->data(index, Qt::BackgroundRole).value<QColor>();
1177 		ColorEditor *ed = static_cast<ColorEditor *>(editor);
1178 		ed->setColor(color);
1179 	}
1180 }
1181 
1182 
1183 void PaletteForm::ColorDelegate::setModelData ( QWidget *editor,
1184 	QAbstractItemModel *model, const QModelIndex& index ) const
1185 {
1186 	if (index.column() == 0) {
1187 		RoleEditor *ed = static_cast<RoleEditor *>(editor);
1188 		const bool masked = ed->edited();
1189 		model->setData(index, masked, Qt::EditRole);
1190 	} else {
1191 		ColorEditor *ed = static_cast<ColorEditor *>(editor);
1192 		if (ed->changed()) {
1193 			const QColor& color = ed->color();
1194 			model->setData(index, color, Qt::BackgroundRole);
1195 		}
1196 	}
1197 }
1198 
1199 
1200 void PaletteForm::ColorDelegate::updateEditorGeometry ( QWidget *editor,
1201 	const QStyleOptionViewItem& option, const QModelIndex& index ) const
1202 {
1203 	QItemDelegate::updateEditorGeometry(editor, option, index);
1204 	editor->setGeometry(editor->geometry().adjusted(0, 0, -1, -1));
1205 }
1206 
1207 
1208 void PaletteForm::ColorDelegate::paint ( QPainter *painter,
1209 	const QStyleOptionViewItem& option, const QModelIndex& index ) const
1210 {
1211 	QStyleOptionViewItem opt = option;
1212 
1213 	const bool masked
1214 		= index.model()->data(index, Qt::EditRole).value<bool>();
1215 	if (index.column() == 0 && masked)
1216 		opt.font.setBold(true);
1217 
1218 	QItemDelegate::paint(painter, opt, index);
1219 
1220 //	painter->setPen(opt.palette.midlight().color());
1221 	painter->setPen(Qt::darkGray);
1222 	painter->drawLine(opt.rect.right(), opt.rect.y(),
1223 		opt.rect.right(), opt.rect.bottom());
1224 	painter->drawLine(opt.rect.x(), opt.rect.bottom(),
1225 		opt.rect.right(), opt.rect.bottom());
1226 }
1227 
1228 
1229 QSize PaletteForm::ColorDelegate::sizeHint (
1230 	const QStyleOptionViewItem& option, const QModelIndex &index) const
1231 {
1232 	return QItemDelegate::sizeHint(option, index) + QSize(4, 4);
1233 }
1234 
1235 
1236 //-------------------------------------------------------------------------
1237 // QSampler::PaletteForm::ColorButton
1238 
1239 PaletteForm::ColorButton::ColorButton ( QWidget *parent )
1240 	: QPushButton(parent), m_brush(Qt::darkGray)
1241 {
1242 	QPushButton::setMinimumWidth(48);
1243 
1244 	QObject::connect(this,
1245 		SIGNAL(clicked()),
1246 		SLOT(chooseColor()));
1247 }
1248 
1249 
1250 const QBrush& PaletteForm::ColorButton::brush (void) const
1251 {
1252 	return m_brush;
1253 }
1254 
1255 
1256 void PaletteForm::ColorButton::setBrush ( const QBrush& brush )
1257 {
1258 	m_brush = brush;
1259 	update();
1260 }
1261 
1262 
1263 void PaletteForm::ColorButton::paintEvent ( QPaintEvent *event )
1264 {
1265 	QPushButton::paintEvent(event);
1266 
1267 	QStyleOptionButton opt;
1268 	opt.initFrom(this);
1269 
1270 	const QRect& rect
1271 		= style()->subElementRect(QStyle::SE_PushButtonContents, &opt, this);
1272 
1273 	QPainter paint(this);
1274 	paint.setBrush(QBrush(m_brush.color()));
1275 	paint.drawRect(rect.adjusted(+1, +1, -2, -2));
1276 }
1277 
1278 
1279 void PaletteForm::ColorButton::chooseColor (void)
1280 {
1281 	const QColor color
1282 		= QColorDialog::getColor(m_brush.color(), this);
1283 	if (color.isValid()) {
1284 		m_brush.setColor(color);
1285 		emit changed();
1286 	}
1287 }
1288 
1289 
1290 //-------------------------------------------------------------------------
1291 // QSampler::PaletteForm::ColorEditor
1292 
1293 PaletteForm::ColorEditor::ColorEditor ( QWidget *parent )
1294 	: QWidget(parent)
1295 {
1296 	QLayout *layout = new QHBoxLayout(this);
1297 	layout->setContentsMargins(0, 0, 0, 0);
1298 	m_button = new PaletteForm::ColorButton(this);
1299 	layout->addWidget(m_button);
1300 	QObject::connect(m_button,
1301 		SIGNAL(changed()),
1302 		SLOT(colorChanged()));
1303 	setFocusProxy(m_button);
1304 	m_changed = false;
1305 }
1306 
1307 
1308 void PaletteForm::ColorEditor::setColor ( const QColor& color )
1309 {
1310 	m_button->setBrush(color);
1311 	m_changed = false;
1312 }
1313 
1314 
1315 QColor PaletteForm::ColorEditor::color (void) const
1316 {
1317 	return m_button->brush().color();
1318 }
1319 
1320 
1321 void PaletteForm::ColorEditor::colorChanged (void)
1322 {
1323 	m_changed = true;
1324 	emit changed(this);
1325 }
1326 
1327 
1328 bool PaletteForm::ColorEditor::changed (void) const
1329 {
1330 	return m_changed;
1331 }
1332 
1333 
1334 //-------------------------------------------------------------------------
1335 // QSampler::PaletteForm::RoleEditor
1336 
1337 PaletteForm::RoleEditor::RoleEditor ( QWidget *parent )
1338 	: QWidget(parent)
1339 {
1340 	m_edited = false;
1341 
1342 	QHBoxLayout *layout = new QHBoxLayout(this);
1343 	layout->setContentsMargins(0, 0, 0, 0);
1344 	layout->setSpacing(0);
1345 
1346 	m_label = new QLabel(this);
1347 	layout->addWidget(m_label);
1348 	m_label->setAutoFillBackground(true);
1349 	m_label->setIndent(3); // HACK: it should have the same value of textMargin in QItemDelegate
1350 	setFocusProxy(m_label);
1351 
1352 	m_button = new QToolButton(this);
1353 	m_button->setToolButtonStyle(Qt::ToolButtonIconOnly);
1354 	m_button->setIcon(QPixmap(":/images/itemReset.png"));
1355 	m_button->setIconSize(QSize(8, 8));
1356 	m_button->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding));
1357 	layout->addWidget(m_button);
1358 
1359 	QObject::connect(m_button,
1360 		SIGNAL(clicked()),
1361 		SLOT(resetProperty()));
1362 }
1363 
1364 
1365 void PaletteForm::RoleEditor::setLabel ( const QString& label )
1366 {
1367 	m_label->setText(label);
1368 }
1369 
1370 
1371 void PaletteForm::RoleEditor::setEdited ( bool on )
1372 {
1373 	QFont font;
1374 	if (on)
1375 		font.setBold(on);
1376 	m_label->setFont(font);
1377 	m_button->setEnabled(on);
1378 	m_edited = on;
1379 }
1380 
1381 
1382 bool PaletteForm::RoleEditor::edited (void) const
1383 {
1384 	return m_edited;
1385 }
1386 
1387 
1388 void PaletteForm::RoleEditor::resetProperty (void)
1389 {
1390 	setEdited(false);
1391 	emit changed(this);
1392 }
1393 
1394 
1395 } // namespace QSampler
1396 
1397 // end of qsamplerPaletteForm.cpp
1398