6#include "colordialog.h"
8#include "colordialog_p.h"
10#include "absolutecolor.h"
11#include "chromahuediagram.h"
12#include "cielchd50values.h"
13#include "colorpatch.h"
14#include "constpropagatingrawpointer.h"
15#include "constpropagatinguniquepointer.h"
16#include "gradientslider.h"
18#include "helperconstants.h"
19#include "helperconversion.h"
20#include "helperqttypes.h"
21#include "initializetranslation.h"
22#include "lchadouble.h"
24#include "multispinbox.h"
25#include "multispinboxsection.h"
26#include "oklchvalues.h"
28#include "rgbcolorspace.h"
29#include "rgbcolorspacefactory.h"
30#include "screencolorpicker.h"
32#include "swatchbook.h"
33#include "wheelcolorpicker.h"
38#include <qapplication.h>
39#include <qboxlayout.h>
40#include <qbytearray.h>
43#include <qcoreapplication.h>
44#include <qcoreevent.h>
47#include <qdialogbuttonbox.h>
48#include <qfontmetrics.h>
49#include <qformlayout.h>
50#include <qgridlayout.h>
52#include <qguiapplication.h>
54#include <qkeysequence.h>
62#include <qpushbutton.h>
63#include <qregularexpression.h>
64#include <qscopedpointer.h>
66#include <qsharedpointer.h>
69#include <qsizepolicy.h>
71#include <qstackedlayout.h>
72#include <qstringbuilder.h>
73#include <qstringliteral.h>
74#include <qtabwidget.h>
75#include <qtoolbutton.h>
76#include <qvalidator.h>
77#include <qversionnumber.h>
82#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
83#include <qcontainerfwd.h>
84#include <qobjectdefs.h>
86#include <qstringlist.h>
89#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
90#include <qstylehints.h>
103QString ColorDialogPrivate::translateColorModel(cmsColorSpaceSignature model)
118 case cmsSigYCbCrData:
139 case cmsSigNamedData:
140 case cmsSig2colorData:
141 case cmsSig3colorData:
142 case cmsSig4colorData:
143 case cmsSig5colorData:
144 case cmsSig6colorData:
145 case cmsSig7colorData:
146 case cmsSig8colorData:
147 case cmsSig9colorData:
148 case cmsSig10colorData:
149 case cmsSig11colorData:
150 case cmsSig12colorData:
151 case cmsSig13colorData:
152 case cmsSig14colorData:
153 case cmsSig15colorData:
156 case cmsSig1colorData:
209void ColorDialogPrivate::retranslateUi()
212 const QPair<QString, QString> percentageInSpinbox =
213 getPrefixSuffix(
tr(
"%1%"));
216 const QPair<QString, QString> arcDegreeInSpinbox =
217 getPrefixSuffix(
tr(
"%1°"));
221 m_rgbColorSpace->profileName().toHtmlEscaped();
225 profileInfo.
append(tableRow.
arg(
tr(
"Name:"), name));
228 const QString maximumCielchD50Chroma =
229 tr(
"%L1 (estimated)")
230 .
arg(m_rgbColorSpace->profileMaximumCielchD50Chroma(),
237 tableRow.
arg(
tr(
"Maximum CIELCh-D50 chroma:"), maximumCielchD50Chroma));
239 const QString maximumOklchChroma =
240 tr(
"%L1 (estimated)")
241 .
arg(m_rgbColorSpace->profileMaximumOklchChroma(),
248 tableRow.
arg(
tr(
"Maximum Oklch chroma:"), maximumOklchChroma));
250 switch (m_rgbColorSpace->profileClass()) {
251 case cmsSigDisplayClass:
253 profileClass =
tr(
"Display profile");
255 case cmsSigAbstractClass:
260 case cmsSigColorSpaceClass:
261 case cmsSigInputClass:
262 case cmsSigLinkClass:
263 case cmsSigNamedColorClass:
264 case cmsSigOutputClass:
272 tableRow.
arg(
tr(
"Profile class:"), profileClass));
275 translateColorModel(m_rgbColorSpace->profileColorModel());
281 profileInfo.
append(tableRow.
arg(
tr(
"Color model:"), colorModel));
284 m_rgbColorSpace->profileManufacturer().toHtmlEscaped();
290 profileInfo.
append(tableRow.
arg(
tr(
"Manufacturer:"), manufacturer));
293 m_rgbColorSpace->profileModel().toHtmlEscaped();
299 profileInfo.
append(tableRow.
arg(
tr(
"Device model:"), (model)));
302 m_rgbColorSpace->profileCreationDateTime();
303 if (!creationDateTime.
isNull()) {
313 tableRow.
arg(
tr(
"Created:"), (creationDateTimeString)));
315 const QVersionNumber iccVersion = m_rgbColorSpace->profileIccVersion();
321 const bool hasMatrixShaper =
322 m_rgbColorSpace->profileHasMatrixShaper();
324 m_rgbColorSpace->profileHasClut();
325 if (hasMatrixShaper || hasClut) {
326 const QString matrixShaperString = tableRow.
arg(
331 tr(
"Implementation:"));
332 if (hasMatrixShaper && hasClut) {
338 matrixShaperString.
arg(
tr(
"Matrices and color lookup tables")));
339 }
else if (hasMatrixShaper) {
344 profileInfo.
append(matrixShaperString.
arg(
tr(
"Matrices")));
345 }
else if (hasClut) {
351 matrixShaperString.
arg(
tr(
"Color lookup tables")));
354 const QString pcsColorModelText =
355 translateColorModel(m_rgbColorSpace->profilePcsColorModel());
356 if (!pcsColorModelText.
isEmpty()) {
362 tableRow.
arg(
tr(
"PCS color model:"), pcsColorModelText));
364 const QString copyright = m_rgbColorSpace->profileCopyright();
369 profileInfo.
append(tableRow.
arg(
tr(
"Copyright:"), copyright));
371 const qint64 fileSize =
372 m_rgbColorSpace->profileFileSize();
378 QLocale().formattedDataSize(fileSize)));
381 m_rgbColorSpace->profileAbsoluteFilePath();
385 profileInfo.
append(tableRow.
arg(
tr(
"File name:"), fileName));
388 m_rgbGroupBox->setToolTip(
QString());
390 const QString tableString = QStringLiteral(
392 "<table border=\"0\" cellpadding=\"2\" cellspacing=\"0\">"
395 m_rgbGroupBox->setToolTip(richTextMarker
401 tr(
"Color space information"),
407 m_ciehlcD50SpinBoxLabel->setText(
tr(
"CIEHL&C D50:"));
411 m_oklchSpinBoxLabel->setText(
tr(
"O&klch:"));
414 m_rgbSpinBoxLabel->setText(
tr(
"&RGB:"));
417 m_rgbLineEditLabel->setText(
tr(
"He&x:"));
419 const int swatchBookIndex = m_tabWidget->indexOf(m_swatchBookWrapperWidget);
420 if (swatchBookIndex >= 0) {
423 const auto mnemonic =
tr(
"&Swatch book");
424 m_tabWidget->setTabToolTip(
426 richTextMarker + fromMnemonicToRichText(mnemonic));
430 const int hueFirstIndex = m_tabWidget->indexOf(m_hueFirstWrapperWidget);
431 if (hueFirstIndex >= 0) {
435 const auto mnemonic =
tr(
"&Hue-based");
436 m_tabWidget->setTabToolTip(
438 richTextMarker + fromMnemonicToRichText(mnemonic));
441 const int lightnessFirstIndex =
442 m_tabWidget->indexOf(m_lightnessFirstWrapperWidget);
443 if (lightnessFirstIndex >= 0) {
449 const auto mnemonic =
tr(
"&Lightness-based");
450 m_tabWidget->setTabToolTip(
452 richTextMarker + fromMnemonicToRichText(mnemonic));
455 const int numericIndex =
456 m_tabWidget->indexOf(m_numericalWidget);
457 if (numericIndex >= 0) {
461 const auto mnemonic =
tr(
"&Numeric");
462 m_tabWidget->setTabToolTip(
464 richTextMarker + fromMnemonicToRichText(mnemonic));
469 m_hslSpinBoxLabel->setText(
tr(
"HS&L:"));
473 m_hsvSpinBoxLabel->setText(
tr(
"HS&V/HSB:"));
476 m_hwbSpinBoxLabel->setText(
tr(
"H&WB:"));
479 m_buttonOK->setText(
tr(
"&OK"));
482 m_buttonCancel->setText(
tr(
"&Cancel"));
484 m_rgbSpinBox->setToolTip(
486 +
tr(
"<p>Red: 0–255</p>"
487 "<p>Green: 0–255</p>"
488 "<p>Blue: 0–255</p>"));
491 m_rgbLineEdit->setToolTip(
493 +
tr(
"<p>Hexadecimal color code, as used in HTML: #RRGGBB</p>"
494 "<p>RR: two-digit code for red: 00–FF</p>"
495 "<p>GG: two-digit code for green: 00–FF</p>"
496 "<p>BB: two-digit code for blue: 00–FF</p>"));
505 m_hslSpinBox->setToolTip(richTextMarker
506 +
tr(
"<p>Hue: 0°–360°</p>"
507 "<p>HSL-Saturation: 0%–100%</p>"
508 "<p>Lightness: 0%–100%</p>"));
519 m_hwbSpinBox->setToolTip(richTextMarker
520 +
tr(
"<p>Hue: 0°–360°</p>"
521 "<p>Whiteness: 0%–100%</p>"
522 "<p>Blackness: 0%–100%</p>"));
532 m_hsvSpinBox->setToolTip(richTextMarker
533 +
tr(
"<p>Hue: 0°–360°</p>"
534 "<p>HSV/HSB-Saturation: 0%–100%</p>"
535 "<p>Brightness/Value: 0%–100%</p>"));
537 m_alphaSpinBox->setPrefix(percentageInSpinbox.first);
538 m_alphaSpinBox->setSuffix(percentageInSpinbox.second);
543 m_lchLightnessSelector->setAccessibleName(
tr(
"Lightness"));
547 m_ciehlcD50SpinBox->setToolTip(richTextMarker
548 +
tr(
"<p>Hue: 0°–360°</p>"
549 "<p>Lightness: 0%–100%</p>"
550 "<p>Chroma: 0–%L1</p>")
551 .arg(CielchD50Values::maximumChroma));
553 constexpr double maxOklchChroma = OklchValues::maximumChroma;
556 m_oklchSpinBox->setToolTip(richTextMarker
557 +
tr(
"<p>Lightness: %L1–%L2</p>"
558 "<p>Chroma: %L3–%L4</p>"
559 "<p>Hue: 0°–360°</p>"
560 "<p>Whitepoint: D65</p>")
561 .arg(0., 0,
'f', okdecimals)
562 .arg(1., 0,
'f', okdecimals)
563 .arg(0., 0,
'f', okdecimals)
564 .arg(maxOklchChroma, 0,
'f', okdecimals));
570 const QString opacityLabel =
tr(
"Op&acity:");
571 m_alphaGradientSlider->setAccessibleName(opacityLabel);
572 m_alphaLabel->setText(opacityLabel);
576 m_hslSpinBox->sectionConfigurations();
577 if (hslSections.
count() != 3) {
579 <<
"Expected 3 sections in HSV MultiSpinBox, but got"
580 << hslSections.
count()
581 <<
"instead. This is a bug in libperceptualcolor.";
583 hslSections[0].setPrefix(arcDegreeInSpinbox.first);
584 hslSections[0].setSuffix(
585 arcDegreeInSpinbox.second + m_multispinboxSectionSeparator);
586 hslSections[1].setPrefix(
587 m_multispinboxSectionSeparator + percentageInSpinbox.first);
588 hslSections[1].setSuffix(
589 percentageInSpinbox.second + m_multispinboxSectionSeparator);
590 hslSections[2].setPrefix(
591 m_multispinboxSectionSeparator + percentageInSpinbox.first);
592 hslSections[2].setSuffix(percentageInSpinbox.second);
593 m_hslSpinBox->setSectionConfigurations(hslSections);
598 m_hwbSpinBox->sectionConfigurations();
599 if (hwbSections.
count() != 3) {
601 <<
"Expected 3 sections in HSV MultiSpinBox, but got"
602 << hwbSections.
count()
603 <<
"instead. This is a bug in libperceptualcolor.";
605 hwbSections[0].setPrefix(arcDegreeInSpinbox.first);
606 hwbSections[0].setSuffix(
607 arcDegreeInSpinbox.second + m_multispinboxSectionSeparator);
608 hwbSections[1].setPrefix(
609 m_multispinboxSectionSeparator + percentageInSpinbox.first);
610 hwbSections[1].setSuffix(
611 percentageInSpinbox.second + m_multispinboxSectionSeparator);
612 hwbSections[2].setPrefix(
613 m_multispinboxSectionSeparator + percentageInSpinbox.first);
614 hwbSections[2].setSuffix(
615 percentageInSpinbox.second);
616 m_hwbSpinBox->setSectionConfigurations(hwbSections);
621 m_hsvSpinBox->sectionConfigurations();
622 if (hsvSections.
count() != 3) {
624 <<
"Expected 3 sections in HSV MultiSpinBox, but got"
625 << hsvSections.
count()
626 <<
"instead. This is a bug in libperceptualcolor.";
628 hsvSections[0].setPrefix(arcDegreeInSpinbox.first);
629 hsvSections[0].setSuffix(
630 arcDegreeInSpinbox.second + m_multispinboxSectionSeparator);
631 hsvSections[1].setPrefix(
632 m_multispinboxSectionSeparator + percentageInSpinbox.first);
633 hsvSections[1].setSuffix(
634 percentageInSpinbox.second + m_multispinboxSectionSeparator);
635 hsvSections[2].setPrefix(
636 m_multispinboxSectionSeparator + percentageInSpinbox.first);
637 hsvSections[2].setSuffix(percentageInSpinbox.second);
638 m_hsvSpinBox->setSectionConfigurations(hsvSections);
643 m_ciehlcD50SpinBox->sectionConfigurations();
644 if (ciehlcD50Sections.
count() != 3) {
646 <<
"Expected 3 sections in HLC MultiSpinBox, but got"
647 << ciehlcD50Sections.
count()
648 <<
"instead. This is a bug in libperceptualcolor.";
650 ciehlcD50Sections[0].setPrefix(arcDegreeInSpinbox.first);
651 ciehlcD50Sections[0].setSuffix(
652 arcDegreeInSpinbox.second + m_multispinboxSectionSeparator);
653 ciehlcD50Sections[1].setPrefix(
654 m_multispinboxSectionSeparator + percentageInSpinbox.first);
655 ciehlcD50Sections[1].setSuffix(
656 percentageInSpinbox.second + m_multispinboxSectionSeparator);
657 ciehlcD50Sections[2].setPrefix(m_multispinboxSectionSeparator);
658 ciehlcD50Sections[2].setSuffix(
QString());
659 m_ciehlcD50SpinBox->setSectionConfigurations(ciehlcD50Sections);
664 m_oklchSpinBox->sectionConfigurations();
665 if (oklchSections.
count() != 3) {
667 <<
"Expected 3 sections in HLC MultiSpinBox, but got"
668 << oklchSections.
count()
669 <<
"instead. This is a bug in libperceptualcolor.";
671 oklchSections[0].setPrefix(
QString());
672 oklchSections[0].setSuffix(m_multispinboxSectionSeparator);
673 oklchSections[1].setPrefix(m_multispinboxSectionSeparator);
674 oklchSections[1].setSuffix(m_multispinboxSectionSeparator);
675 oklchSections[2].setPrefix(
676 m_multispinboxSectionSeparator + arcDegreeInSpinbox.first);
677 oklchSections[2].setSuffix(arcDegreeInSpinbox.second);
678 m_oklchSpinBox->setSectionConfigurations(oklchSections);
681 if (m_screenColorPickerButton) {
686 const auto mnemonic =
tr(
"&Pick screen color");
687 m_screenColorPickerButton->setToolTip(
688 richTextMarker + fromMnemonicToRichText(mnemonic));
689 m_screenColorPickerButton->setShortcut(
698 const auto gamutMnemonic =
699 tr(
"Click to snap to nearest in-&gamut color");
701 richTextMarker + fromMnemonicToRichText(gamutMnemonic);
703 m_ciehlcD50SpinBoxGamutAction->setToolTip(gamutTooltip);
704 m_ciehlcD50SpinBoxGamutAction->setShortcut(gamutShortcut);
705 m_oklchSpinBoxGamutAction->setToolTip(gamutTooltip);
706 m_oklchSpinBoxGamutAction->setShortcut(gamutShortcut);
711 m_swatchBookSelector->setItemText(0,
tr(
"Basic colors"));
716 m_swatchBookSelector->setItemText(1,
tr(
"History"));
736void ColorDialogPrivate::reloadIcons()
739 label->setText(QStringLiteral(
"abc"));
744 m_currentIconThemeType = newType;
747 {QStringLiteral(
"paint-swatch"),
750 QStringLiteral(
"palette"),
751 QStringLiteral(
"palette-symbolic")};
752 const int swatchBookIndex =
753 m_tabWidget->indexOf(m_swatchBookWrapperWidget);
754 if (swatchBookIndex >= 0) {
755 m_tabWidget->setTabIcon(swatchBookIndex,
756 qIconFromTheme(swatchBookIcons,
757 QStringLiteral(
"color-swatch"),
763 QStringLiteral(
"color-mode-hue-shift-positive"),
765 const int hueFirstIndex =
766 m_tabWidget->indexOf(m_hueFirstWrapperWidget);
767 if (hueFirstIndex >= 0) {
768 m_tabWidget->setTabIcon(hueFirstIndex,
769 qIconFromTheme(hueFirstIcons,
770 QStringLiteral(
"steering-wheel"),
776 QStringLiteral(
"brightness-high"),
778 const int lightnessFirstIndex =
779 m_tabWidget->indexOf(m_lightnessFirstWrapperWidget);
780 if (lightnessFirstIndex >= 0) {
781 m_tabWidget->setTabIcon(lightnessFirstIndex,
782 qIconFromTheme(lightnessFirstIcons,
783 QStringLiteral(
"brightness-2"),
789 QStringLiteral(
"black_sum"),
791 const int numericIndex =
792 m_tabWidget->indexOf(m_numericalWidget);
793 if (numericIndex >= 0) {
794 m_tabWidget->setTabIcon(numericIndex,
795 qIconFromTheme(numericIcons,
796 QStringLiteral(
"123"),
803 QStringLiteral(
"data-warning"),
804 QStringLiteral(
"dialog-warning-symbolic"),
806 const QIcon gamutIcon = qIconFromTheme(gamutIconNames,
807 QStringLiteral(
"eye-exclamation"),
809 m_ciehlcD50SpinBoxGamutAction->setIcon(gamutIcon);
810 m_oklchSpinBoxGamutAction->setIcon(gamutIcon);
814 QStringLiteral(
"color-picker"),
815 QStringLiteral(
"gtk-color-picker"),
816 QStringLiteral(
"tool_color_picker"),
818 if (!m_screenColorPickerButton.
isNull()) {
819 m_screenColorPickerButton->setIcon(
820 qIconFromTheme(candidates,
821 QStringLiteral(
"color-picker"),
847 m_rgbColorSpace = colorSpace;
849 m_wcsBasicDefaultColor = m_wcsBasicColors.value(4, 2);
852 m_swatchBookBasicColors =
new SwatchBook(m_rgbColorSpace,
854 Qt::Orientation::Horizontal);
855 auto swatchBookBasicColorsLayout =
new QGridLayout();
856 auto swatchBookBasicColorsLayoutWidget =
new QWidget();
857 swatchBookBasicColorsLayoutWidget->setLayout(swatchBookBasicColorsLayout);
858 swatchBookBasicColorsLayoutWidget->setContentsMargins(0, 0, 0, 0);
859 swatchBookBasicColorsLayout->setContentsMargins(0, 0, 0, 0);
860 swatchBookBasicColorsLayout->addWidget(m_swatchBookBasicColors);
861 swatchBookBasicColorsLayout->setRowStretch(1, 1);
862 swatchBookBasicColorsLayout->setColumnStretch(1, 1);
863 m_swatchBookHistory =
new SwatchBook(m_rgbColorSpace,
865 Qt::Orientation::Vertical);
867 auto swatchBookHistoryLayoutWidget =
new QWidget();
868 swatchBookHistoryLayoutWidget->setLayout(swatchBookHistoryLayout);
869 swatchBookHistoryLayoutWidget->setContentsMargins(0, 0, 0, 0);
870 swatchBookHistoryLayout->setContentsMargins(0, 0, 0, 0);
871 swatchBookHistoryLayout->addWidget(m_swatchBookHistory);
872 swatchBookHistoryLayout->setRowStretch(1, 1);
873 swatchBookHistoryLayout->setColumnStretch(1, 1);
874 loadHistoryFromSettingsToSwatchBook();
876 m_swatchBookStack->addWidget(swatchBookBasicColorsLayoutWidget);
877 m_swatchBookStack->addWidget(swatchBookHistoryLayoutWidget);
879 swatchBookInnerLayout->
addLayout(m_swatchBookStack);
883 m_swatchBookSelector->addItem(
QString());
884 m_swatchBookSelector->addItem(
QString());
891 m_swatchBookStack->setCurrentIndex(0);
892 m_settings.swatchBookPage.setValue(
893 PerceptualSettings::SwatchBookPage::BasicColors);
896 m_swatchBookStack->setCurrentIndex(1);
897 m_settings.swatchBookPage.setValue(
898 PerceptualSettings::SwatchBookPage::History);
902 swatchBookOuterLayout->
addWidget(m_swatchBookSelector);
903 swatchBookOuterLayout->
addLayout(swatchBookInnerLayout);
905 m_swatchBookWrapperWidget =
new QWidget();
906 m_swatchBookWrapperWidget->setLayout(swatchBookOuterLayout);
908 &Setting<PerceptualSettings::ColorList>::valueChanged,
910 &ColorDialogPrivate::loadHistoryFromSettingsToSwatchBook);
911 m_wheelColorPicker =
new WheelColorPicker(m_rgbColorSpace);
912 m_hueFirstWrapperWidget =
new QWidget;
914 tempHueFirstLayout->
addWidget(m_wheelColorPicker);
915 m_hueFirstWrapperWidget->setLayout(tempHueFirstLayout);
917 m_lchLightnessSelector =
new GradientSlider(m_rgbColorSpace);
928 m_lchLightnessSelector->setColors(black, white);
929 m_chromaHueDiagram =
new ChromaHueDiagram(m_rgbColorSpace);
931 tempLightnesFirstLayout->
addWidget(m_lchLightnessSelector);
932 tempLightnesFirstLayout->
addWidget(m_chromaHueDiagram);
933 m_lightnessFirstWrapperWidget =
new QWidget();
934 m_lightnessFirstWrapperWidget->setLayout(tempLightnesFirstLayout);
936 initializeScreenColorPicker();
950 m_tabWidget->addTab(m_swatchBookWrapperWidget,
QString());
951 m_swatchBookTabShortcut =
new QShortcut(q_pointer);
952 connect(m_swatchBookTabShortcut,
956 m_tabWidget->setCurrentIndex(
957 m_tabWidget->indexOf(m_swatchBookWrapperWidget));
959 connect(m_swatchBookTabShortcut,
963 m_tabWidget->setCurrentIndex(
964 m_tabWidget->indexOf(m_swatchBookWrapperWidget));
967 m_tabWidget->addTab(m_hueFirstWrapperWidget,
QString());
968 m_hueFirstTabShortcut =
new QShortcut(q_pointer);
973 m_tabWidget->setCurrentIndex(
974 m_tabWidget->indexOf(m_hueFirstWrapperWidget));
980 m_tabWidget->setCurrentIndex(
981 m_tabWidget->indexOf(m_hueFirstWrapperWidget));
984 m_tabWidget->addTab(m_lightnessFirstWrapperWidget,
QString());
985 m_lightnessFirstTabShortcut =
new QShortcut(q_pointer);
986 connect(m_lightnessFirstTabShortcut,
990 m_tabWidget->setCurrentIndex(
991 m_tabWidget->indexOf(m_lightnessFirstWrapperWidget));
993 connect(m_lightnessFirstTabShortcut,
997 m_tabWidget->setCurrentIndex(
998 m_tabWidget->indexOf(m_lightnessFirstWrapperWidget));
1001 m_tabTable.
insert(&m_swatchBookWrapperWidget,
1002 QStringLiteral(
"swatch"));
1003 m_tabTable.
insert(&m_hueFirstWrapperWidget,
1004 QStringLiteral(
"hue-based"));
1005 m_tabTable.
insert(&m_lightnessFirstWrapperWidget,
1006 QStringLiteral(
"lightness-based"));
1007 m_tabTable.
insert(&m_numericalWidget,
1008 QStringLiteral(
"numerical"));
1012 &ColorDialogPrivate::saveCurrentTab);
1015 m_colorPatch =
new ColorPatch();
1016 m_colorPatch->setMinimumSize(m_colorPatch->minimumSizeHint() * 1.5);
1019 headerLayout->
addWidget(m_colorPatch, 1);
1022 headerLayout->
addWidget(m_screenColorPickerButton,
1030 m_numericalWidget = initializeNumericPage();
1031 m_numericalTabShortcut =
new QShortcut(q_pointer);
1032 connect(m_numericalTabShortcut,
1036 m_tabWidget->setCurrentIndex(
1037 m_tabWidget->indexOf(m_numericalWidget));
1039 connect(m_numericalTabShortcut,
1043 m_tabWidget->setCurrentIndex(
1044 m_tabWidget->indexOf(m_numericalWidget));
1049 m_selectorLayout->addWidget(m_tabWidget);
1050 m_selectorLayout->addWidget(m_numericalWidget);
1054 m_alphaGradientSlider =
new GradientSlider(m_rgbColorSpace,
1055 Qt::Orientation::Horizontal);
1056 m_alphaGradientSlider->setSingleStep(singleStepAlpha);
1057 m_alphaGradientSlider->setPageStep(pageStepAlpha);
1059 m_alphaSpinBox->setAlignment(Qt::AlignmentFlag::AlignRight);
1060 m_alphaSpinBox->setMinimum(0);
1061 m_alphaSpinBox->setMaximum(100);
1063 m_alphaSpinBox->setDecimals(decimals);
1064 m_alphaSpinBox->setSingleStep(singleStepAlpha * 100);
1067 m_alphaLabel =
new QLabel();
1068 m_alphaLabel->setBuddy(m_alphaSpinBox);
1070 m_alphaLayout->
addWidget(m_alphaGradientSlider);
1071 m_alphaLayout->
addWidget(m_alphaSpinBox);
1100 m_buttonBox->installEventFilter(&m_languageChangeEventFilter);
1101 m_buttonOK->installEventFilter(&m_languageChangeEventFilter);
1102 m_buttonCancel->installEventFilter(&m_languageChangeEventFilter);
1114 tempMainLayout->
addLayout(headerLayout);
1115 tempMainLayout->
addLayout(m_selectorLayout);
1116 tempMainLayout->
addLayout(m_alphaLayout);
1118 q_pointer->setLayout(tempMainLayout);
1124 &ColorDialogPrivate::readColorPatchValue
1126 connect(m_swatchBookBasicColors,
1127 &SwatchBook::currentColorChanged,
1129 &ColorDialogPrivate::readSwatchBookBasicColorsValue
1132 &SwatchBook::currentColorChanged,
1134 &ColorDialogPrivate::readSwatchBookHistoryValue
1139 &ColorDialogPrivate::readRgbNumericValues
1144 &ColorDialogPrivate::readRgbHexValues
1149 &ColorDialogPrivate::updateRgbHexButBlockSignals
1154 &ColorDialogPrivate::readHslNumericValues
1159 &ColorDialogPrivate::readHwbNumericValues
1164 &ColorDialogPrivate::readHsvNumericValues
1169 &ColorDialogPrivate::readHlcNumericValues
1174 &ColorDialogPrivate::updateHlcButBlockSignals
1179 &ColorDialogPrivate::readOklchNumericValues
1184 &ColorDialogPrivate::updateOklchButBlockSignals
1186 connect(m_lchLightnessSelector,
1189 &ColorDialogPrivate::readLightnessValue
1194 &ColorDialogPrivate::readWheelColorPickerValues
1199 &ColorDialogPrivate::readChromaHueDiagramValue
1201 connect(m_alphaGradientSlider,
1204 &ColorDialogPrivate::updateColorPatch
1206 connect(m_alphaGradientSlider,
1209 [
this](
const qreal newFraction) {
1211 m_alphaSpinBox->setValue(newFraction * 100);
1216 [
this](
const double newValue) {
1219 m_alphaGradientSlider->setValue(newValue / 100);
1223 q_pointer->setOptions(QColorDialog::ColorDialogOption::DontUseNativeDialog);
1231 q_pointer->setWindowTitle(
tr(
"Select color"));
1246 q_pointer->setSizeGripEnabled(
true);
1251 m_ciehlcD50SpinBoxGamutAction =
new QAction(q_pointer);
1252 connect(m_ciehlcD50SpinBoxGamutAction,
1255 &ColorDialogPrivate::updateHlcButBlockSignals
1257 m_oklchSpinBoxGamutAction =
new QAction(q_pointer);
1258 connect(m_oklchSpinBoxGamutAction,
1261 &ColorDialogPrivate::updateOklchButBlockSignals
1266 m_ciehlcD50SpinBoxGamutAction->setVisible(
false);
1267 m_ciehlcD50SpinBox->addActionButton(
1268 m_ciehlcD50SpinBoxGamutAction,
1269 QLineEdit::ActionPosition::TrailingPosition);
1270 m_oklchSpinBoxGamutAction->setVisible(
false);
1271 m_oklchSpinBox->addActionButton(
1272 m_oklchSpinBoxGamutAction,
1273 QLineEdit::ActionPosition::TrailingPosition);
1280 std::optional<QStringList>());
1284#if (QT_VERSION >= QT_VERSION_CHECK(6, 5, 0))
1285 connect(qGuiApp->styleHints(),
1288 &ColorDialogPrivate::reloadIcons);
1298 , d_pointer(new ColorDialogPrivate(this))
1316 , d_pointer(new ColorDialogPrivate(this))
1335 , d_pointer(new ColorDialogPrivate(this))
1337 d_pointer->initialize(colorSpace);
1345QColor ColorDialogPrivate::defaultColor()
const
1347 const auto history = m_settings.history.value();
1348 return history.value(0, m_wcsBasicDefaultColor);
1365 , d_pointer(new ColorDialogPrivate(this))
1367 d_pointer->initialize(colorSpace);
1390ColorDialogPrivate::ColorDialogPrivate(
ColorDialog *backLink)
1391 : q_pointer(backLink)
1399 QColor temp = d_pointer->m_currentOpaqueColorRgb.rgbQColor;
1401 static_cast<QColorFloatType
>(
1402 d_pointer->m_alphaGradientSlider->value()));
1424 temp = color.
toRgb();
1429 if (
testOption(ColorDialog::ColorDialogOption::ShowAlphaChannel)) {
1430 d_pointer->m_alphaGradientSlider->setValue(
1431 static_cast<double>(temp.
alphaF()));
1433 d_pointer->m_alphaGradientSlider->setValue(1);
1437 const RgbColor myRgbColor = RgbColor::fromRgbQColor(temp);
1438 d_pointer->setCurrentOpaqueColor(myRgbColor,
nullptr);
1451void ColorDialog::open(
QObject *receiver,
const char *member)
1457 d_pointer->m_receiverToBeDisconnected = receiver;
1458 d_pointer->m_memberToBeDisconnected = member;
1467void ColorDialogPrivate::updateColorPatch()
1469 QColor tempRgbQColor = m_currentOpaqueColorRgb.rgbQColor;
1471 static_cast<QColorFloatType
>(m_alphaGradientSlider->value()));
1472 m_colorPatch->setColor(tempRgbQColor);
1478 const auto cielchD50 =
1480 const auto rgb1 = m_rgbColorSpace->fromCielchD50ToRgb1(cielchD50);
1481 const auto rgb255 = GenericColor(rgb1.first * 255,
1484 const auto rgbColor = RgbColor::fromRgb255(rgb255);
1485 setCurrentOpaqueColor(abs, rgbColor, ignoreWidget);
1489void ColorDialogPrivate::setCurrentOpaqueColor(
const PerceptualColor::RgbColor &rgb,
QWidget *
const ignoreWidget)
1491 const auto temp = rgb.rgb255;
1493 static_cast<QColorFloatType
>(temp.first / 255.),
1494 static_cast<QColorFloatType
>(temp.second / 255.),
1495 static_cast<QColorFloatType
>(temp.third / 255.));
1496 const auto cielchD50 = GenericColor(
1497 m_rgbColorSpace->toCielchD50Double(myQColor.
rgba64()));
1498 setCurrentOpaqueColor(
1522 const PerceptualColor::RgbColor &rgb,
1525 const bool isIdentical =
1526 (abs == m_currentOpaqueColorAbs) && (rgb == m_currentOpaqueColorRgb);
1527 if (m_isColorChangeInProgress || isIdentical) {
1534 m_isColorChangeInProgress =
true;
1538 QColor oldQColor = q_pointer->currentColor();
1541 m_currentOpaqueColorAbs = abs;
1542 m_currentOpaqueColorRgb = rgb;
1545 if (m_swatchBookBasicColors != ignoreWidget) {
1546 m_swatchBookBasicColors->setCurrentColor(
1547 m_currentOpaqueColorRgb.rgbQColor);
1551 if (m_swatchBookHistory != ignoreWidget) {
1552 m_swatchBookHistory->setCurrentColor(m_currentOpaqueColorRgb.rgbQColor);
1556 if (m_rgbSpinBox != ignoreWidget) {
1557 m_rgbSpinBox->setSectionValues(
1558 m_currentOpaqueColorRgb.rgb255.toQList3());
1562 if (m_hslSpinBox != ignoreWidget) {
1563 m_hslSpinBox->setSectionValues(
1564 m_currentOpaqueColorRgb.hsl.toQList3());
1568 if (m_hwbSpinBox != ignoreWidget) {
1569 m_hwbSpinBox->setSectionValues(
1570 m_currentOpaqueColorRgb.hwb.toQList3());
1574 if (m_hsvSpinBox != ignoreWidget) {
1575 m_hsvSpinBox->setSectionValues(
1576 m_currentOpaqueColorRgb.hsv.toQList3());
1584 if (m_ciehlcD50SpinBox != ignoreWidget) {
1585 m_ciehlcD50SpinBox->setSectionValues(ciehlcD50);
1590 if (m_oklchSpinBox != ignoreWidget) {
1591 m_oklchSpinBox->setSectionValues(oklch.toQList3());
1595 if (m_rgbLineEdit != ignoreWidget) {
1596 updateRgbHexButBlockSignals();
1600 if (m_lchLightnessSelector != ignoreWidget) {
1601 m_lchLightnessSelector->setValue(
1602 cielchD50.first /
static_cast<qreal
>(100));
1606 if (m_chromaHueDiagram != ignoreWidget) {
1607 m_chromaHueDiagram->setCurrentColor(
1608 cielchD50.reinterpretAsLchToLchDouble());
1612 if (m_wheelColorPicker != ignoreWidget) {
1613 m_wheelColorPicker->setCurrentColor(
1614 cielchD50.reinterpretAsLchToLchDouble());
1618 if (m_alphaGradientSlider != ignoreWidget) {
1619 LchaDouble tempColor;
1620 tempColor.l = cielchD50.first;
1621 tempColor.c = cielchD50.second;
1622 tempColor.h = cielchD50.third;
1624 m_alphaGradientSlider->setFirstColor(tempColor);
1626 m_alphaGradientSlider->setSecondColor(tempColor);
1630 if (m_colorPatch != ignoreWidget) {
1635 if (q_pointer->currentColor() != oldQColor) {
1636 Q_EMIT q_pointer->currentColorChanged(q_pointer->currentColor());
1641 m_isColorChangeInProgress =
false;
1646void ColorDialogPrivate::readLightnessValue()
1648 if (m_isColorChangeInProgress) {
1653 cielchD50.first = m_lchLightnessSelector->value() * 100;
1654 cielchD50 = GenericColor(
1655 m_rgbColorSpace->reduceCielchD50ChromaToFitIntoGamut(
1656 cielchD50.reinterpretAsLchToLchDouble()));
1657 setCurrentOpaqueColor(
1659 m_lchLightnessSelector);
1664void ColorDialogPrivate::readHslNumericValues()
1666 if (m_isColorChangeInProgress) {
1670 const auto temp = RgbColor::fromHsl(
1671 GenericColor(m_hslSpinBox->sectionValues()));
1672 setCurrentOpaqueColor(temp, m_hslSpinBox);
1677void ColorDialogPrivate::readHwbNumericValues()
1679 if (m_isColorChangeInProgress) {
1683 const auto temp = RgbColor::fromHwb(
1684 GenericColor(m_hwbSpinBox->sectionValues()));
1685 setCurrentOpaqueColor(temp, m_hwbSpinBox);
1690void ColorDialogPrivate::readHsvNumericValues()
1692 if (m_isColorChangeInProgress) {
1696 const auto temp = RgbColor::fromHsv(
1697 GenericColor(m_hsvSpinBox->sectionValues()));
1698 setCurrentOpaqueColor(temp, m_hsvSpinBox);
1703void ColorDialogPrivate::readRgbNumericValues()
1705 if (m_isColorChangeInProgress) {
1709 const auto temp = RgbColor::fromRgb255(
1710 GenericColor(m_rgbSpinBox->sectionValues()));
1711 setCurrentOpaqueColor(temp, m_rgbSpinBox);
1716void ColorDialogPrivate::readColorPatchValue()
1718 if (m_isColorChangeInProgress) {
1722 const QColor temp = m_colorPatch->color();
1727 const auto myRgbColor = RgbColor::fromRgbQColor(temp);
1728 setCurrentOpaqueColor(myRgbColor, m_colorPatch);
1733void ColorDialogPrivate::readSwatchBookBasicColorsValue()
1735 if (m_isColorChangeInProgress) {
1739 const QColor temp = m_swatchBookBasicColors->currentColor();
1744 const auto myRgbColor = RgbColor::fromRgbQColor(temp);
1745 setCurrentOpaqueColor(myRgbColor, m_swatchBookBasicColors);
1750void ColorDialogPrivate::readSwatchBookHistoryValue()
1752 if (m_isColorChangeInProgress) {
1756 const QColor temp = m_swatchBookHistory->currentColor();
1761 const auto myRgbColor = RgbColor::fromRgbQColor(temp);
1762 setCurrentOpaqueColor(myRgbColor, m_swatchBookHistory);
1767void ColorDialogPrivate::readWheelColorPickerValues()
1769 if (m_isColorChangeInProgress) {
1773 const auto cielchD50 = GenericColor(m_wheelColorPicker->currentColor());
1774 setCurrentOpaqueColor(
1776 m_wheelColorPicker);
1781void ColorDialogPrivate::readChromaHueDiagramValue()
1783 if (m_isColorChangeInProgress) {
1787 const auto cielchD50 = GenericColor(m_chromaHueDiagram->currentColor());
1788 setCurrentOpaqueColor(
1790 m_chromaHueDiagram);
1795void ColorDialogPrivate::readRgbHexValues()
1797 if (m_isColorChangeInProgress) {
1801 QString temp = m_rgbLineEdit->text();
1802 if (!temp.
startsWith(QStringLiteral(u
"#"))) {
1803 temp = QStringLiteral(u
"#") + temp;
1808 const auto myRgbColor = RgbColor::fromRgbQColor(rgb);
1809 setCurrentOpaqueColor(myRgbColor, m_rgbLineEdit);
1811 m_isDirtyRgbLineEdit =
true;
1819void ColorDialogPrivate::updateRgbHexButBlockSignals()
1827 const auto &rgbFloat = m_currentOpaqueColorRgb.rgb255;
1840 QStringLiteral(u
"#%1%2%3")
1841 .
arg(qBound(0, qRound(rgbFloat.first), 255),
1845 .
arg(qBound(0, qRound(rgbFloat.second), 255),
1849 .
arg(qBound(0, qRound(rgbFloat.third), 255),
1854 m_rgbLineEdit->setText(hexString);
1862void ColorDialogPrivate::updateHlcButBlockSignals()
1869 m_ciehlcD50SpinBox->setSectionValues(ciehlcD50List);
1870 m_ciehlcD50SpinBoxGamutAction->setVisible(
false);
1878void ColorDialogPrivate::updateOklchButBlockSignals()
1882 m_oklchSpinBox->setSectionValues(oklch.toQList3());
1883 m_oklchSpinBoxGamutAction->setVisible(
false);
1888void ColorDialogPrivate::readHlcNumericValues()
1890 if (m_isColorChangeInProgress) {
1894 QList<double> hlcValues = m_ciehlcD50SpinBox->sectionValues();
1896 lch.h = hlcValues.
at(0);
1897 lch.l = hlcValues.
at(1);
1898 lch.c = hlcValues.
at(2);
1899 if (m_rgbColorSpace->isCielchD50InGamut(lch)) {
1900 m_ciehlcD50SpinBoxGamutAction->setVisible(
false);
1902 m_ciehlcD50SpinBoxGamutAction->setVisible(
true);
1904 const auto myColor = GenericColor(
1905 m_rgbColorSpace->reduceCielchD50ChromaToFitIntoGamut(lch));
1906 setCurrentOpaqueColor(
1909 m_ciehlcD50SpinBox);
1914void ColorDialogPrivate::readOklchNumericValues()
1916 if (m_isColorChangeInProgress) {
1924 LchDouble originalOklch;
1925 originalOklch.l = m_oklchSpinBox->sectionValues().value(0);
1926 originalOklch.c = m_oklchSpinBox->sectionValues().value(1);
1927 originalOklch.h = m_oklchSpinBox->sectionValues().value(2);
1928 if (m_rgbColorSpace->isOklchInGamut(originalOklch)) {
1929 m_oklchSpinBoxGamutAction->setVisible(
false);
1931 m_oklchSpinBoxGamutAction->setVisible(
true);
1933 const auto inGamutOklch = GenericColor(
1934 m_rgbColorSpace->reduceOklchChromaToFitIntoGamut(originalOklch));
1935 const auto inGamutColor =
1937 setCurrentOpaqueColor(inGamutColor,
1946void ColorDialogPrivate::initializeScreenColorPicker()
1948 auto screenPicker =
new ScreenColorPicker(q_pointer);
1949 if (!screenPicker->isAvailable()) {
1953 screenPicker->
setParent(m_screenColorPickerButton);
1954 connect(m_screenColorPickerButton,
1958 [&, screenPicker]() {
1959 const auto myColor = q_pointer->currentColor();
1964 screenPicker->startPicking(
1965 fromFloatingToEightBit(myColor.redF()),
1966 fromFloatingToEightBit(myColor.greenF()),
1967 fromFloatingToEightBit(myColor.blueF()));
1970 &ScreenColorPicker::newColor,
1972 [
this](
const double red,
const double green,
const double blue,
const bool isSRgbGuaranteed) {
1973 Q_UNUSED(isSRgbGuaranteed)
1979 const GenericColor rgb255
1980 {qBound<double>(0, red * 255, 255),
1981 qBound<double>(0, green * 255, 255),
1982 qBound<double>(0, blue * 255, 255)};
1983 setCurrentOpaqueColor(RgbColor::fromRgb255(rgb255),
nullptr);
1990QWidget *ColorDialogPrivate::initializeNumericPage()
1994 m_rgbSpinBox =
new MultiSpinBox();
1996 MultiSpinBoxSection mySection;
1997 mySection.setDecimals(decimals);
1998 mySection.setMinimum(0);
1999 mySection.setMaximum(255);
2001 mySection.setPrefix(
QString());
2002 mySection.setSuffix(m_multispinboxSectionSeparator);
2003 rgbSections.
append(mySection);
2005 mySection.setPrefix(m_multispinboxSectionSeparator);
2006 mySection.setSuffix(m_multispinboxSectionSeparator);
2007 rgbSections.
append(mySection);
2009 mySection.setPrefix(m_multispinboxSectionSeparator);
2010 mySection.setSuffix(
QString());
2011 rgbSections.
append(mySection);
2013 m_rgbSpinBox->setSectionConfigurations(rgbSections);
2019 m_rgbLineEdit->setMaxLength(7);
2021 QStringLiteral(u
"#?[0-9A-Fa-f]{0,6}"));
2023 tempRegularExpression,
2025 m_rgbLineEdit->setValidator(validator);
2030 m_hslSpinBox =
new MultiSpinBox();
2032 MultiSpinBoxSection mySection;
2033 mySection.setDecimals(decimals);
2035 mySection.setMinimum(0);
2036 mySection.setMaximum(360);
2037 mySection.setWrapping(
true);
2038 hslSections.
append(mySection);
2040 mySection.setMinimum(0);
2041 mySection.setMaximum(100);
2042 mySection.setWrapping(
false);
2043 hslSections.
append(mySection);
2045 mySection.setMinimum(0);
2046 mySection.setMaximum(100);
2047 mySection.setWrapping(
false);
2048 hslSections.
append(mySection);
2050 m_hslSpinBox->setSectionConfigurations(hslSections);
2055 m_hwbSpinBox =
new MultiSpinBox();
2057 MultiSpinBoxSection mySection;
2058 mySection.setDecimals(decimals);
2060 mySection.setMinimum(0);
2061 mySection.setMaximum(360);
2062 mySection.setWrapping(
true);
2063 hwbSections.
append(mySection);
2065 mySection.setMinimum(0);
2066 mySection.setMaximum(100);
2067 mySection.setWrapping(
false);
2068 hwbSections.
append(mySection);
2070 mySection.setMinimum(0);
2071 mySection.setMaximum(100);
2072 mySection.setWrapping(
false);
2073 hwbSections.
append(mySection);
2075 m_hwbSpinBox->setSectionConfigurations(hwbSections);
2080 m_hsvSpinBox =
new MultiSpinBox();
2082 MultiSpinBoxSection mySection;
2083 mySection.setDecimals(decimals);
2085 mySection.setMinimum(0);
2086 mySection.setMaximum(360);
2087 mySection.setWrapping(
true);
2088 hsvSections.
append(mySection);
2090 mySection.setMinimum(0);
2091 mySection.setMaximum(100);
2092 mySection.setWrapping(
false);
2093 hsvSections.
append(mySection);
2095 mySection.setMinimum(0);
2096 mySection.setMaximum(100);
2097 mySection.setWrapping(
false);
2098 hsvSections.
append(mySection);
2100 m_hsvSpinBox->setSectionConfigurations(hsvSections);
2106 m_rgbSpinBoxLabel =
new QLabel();
2107 m_rgbSpinBoxLabel->setBuddy(m_rgbSpinBox);
2108 tempRgbFormLayout->
addRow(m_rgbSpinBoxLabel, m_rgbSpinBox);
2109 m_rgbLineEditLabel =
new QLabel();
2110 m_rgbLineEditLabel->setBuddy(m_rgbLineEdit);
2111 tempRgbFormLayout->
addRow(m_rgbLineEditLabel, m_rgbLineEdit);
2112 m_hslSpinBoxLabel =
new QLabel();
2113 m_hslSpinBoxLabel->setBuddy(m_hslSpinBox);
2114 tempRgbFormLayout->
addRow(m_hslSpinBoxLabel, m_hslSpinBox);
2115 m_hwbSpinBoxLabel =
new QLabel();
2116 m_hwbSpinBoxLabel->setBuddy(m_hwbSpinBox);
2117 tempRgbFormLayout->
addRow(m_hwbSpinBoxLabel, m_hwbSpinBox);
2118 m_hsvSpinBoxLabel =
new QLabel();
2119 m_hsvSpinBoxLabel->setBuddy(m_hsvSpinBox);
2120 tempRgbFormLayout->
addRow(m_hsvSpinBoxLabel, m_hsvSpinBox);
2122 m_rgbGroupBox->setLayout(tempRgbFormLayout);
2129 const auto elidedProfileName = fontMetrics.elidedText(
2130 m_rgbColorSpace->profileName(),
2131 Qt::TextElideMode::ElideRight,
2134 m_rgbGroupBox->setTitle(elidedProfileName);
2140 m_ciehlcD50SpinBox =
new MultiSpinBox;
2141 MultiSpinBoxSection mySection;
2142 mySection.setDecimals(decimals);
2144 mySection.setMinimum(0);
2145 mySection.setMaximum(360);
2146 mySection.setWrapping(
true);
2147 ciehlcD50Sections.
append(mySection);
2149 mySection.setMinimum(0);
2150 mySection.setMaximum(100);
2151 mySection.setWrapping(
false);
2152 ciehlcD50Sections.
append(mySection);
2154 mySection.setMinimum(0);
2155 mySection.setMaximum(CielchD50Values::maximumChroma);
2156 mySection.setWrapping(
false);
2157 ciehlcD50Sections.
append(mySection);
2159 m_ciehlcD50SpinBox->setSectionConfigurations(ciehlcD50Sections);
2165 MultiSpinBoxSection mySection;
2166 m_oklchSpinBox =
new MultiSpinBox;
2168 mySection.setMinimum(0);
2169 mySection.setMaximum(1);
2170 mySection.setSingleStep(singleStepOklabc);
2171 mySection.setWrapping(
false);
2172 mySection.setDecimals(okdecimals);
2173 oklchSections.
append(mySection);
2175 mySection.setMinimum(0);
2176 mySection.setMaximum(OklchValues::maximumChroma);
2177 mySection.setSingleStep(singleStepOklabc);
2178 mySection.setWrapping(
false);
2179 mySection.setDecimals(okdecimals);
2180 oklchSections.
append(mySection);
2182 mySection.setMinimum(0);
2183 mySection.setMaximum(360);
2184 mySection.setSingleStep(1);
2185 mySection.setWrapping(
true);
2186 mySection.setDecimals(decimals);
2187 oklchSections.
append(mySection);
2189 m_oklchSpinBox->setSectionConfigurations(oklchSections);
2198 m_ciehlcD50SpinBoxLabel =
new QLabel();
2199 m_ciehlcD50SpinBoxLabel->setBuddy(m_ciehlcD50SpinBox);
2200 cielabFormLayout->
addRow(m_ciehlcD50SpinBoxLabel, m_ciehlcD50SpinBox);
2201 m_oklchSpinBoxLabel =
new QLabel();
2202 m_oklchSpinBoxLabel->setBuddy(m_oklchSpinBox);
2203 cielabFormLayout->
addRow(m_oklchSpinBoxLabel, m_oklchSpinBox);
2204 tempMainLayout->
addLayout(cielabFormLayout);
2205 tempMainLayout->
addWidget(m_rgbGroupBox);
2216 return d_pointer->m_options;
2227 temp.setFlag(option, on);
2237 if (newOptions == d_pointer->m_options) {
2242 d_pointer->m_options = newOptions;
2245 d_pointer->m_options.setFlag(
2246 QColorDialog::ColorDialogOption::DontUseNativeDialog,
2250 const bool alphaVisibility = d_pointer->m_options.testFlag(
2251 QColorDialog::ColorDialogOption::ShowAlphaChannel);
2252 d_pointer->m_alphaLabel->setVisible(alphaVisibility);
2253 d_pointer->m_alphaGradientSlider->setVisible(alphaVisibility);
2254 d_pointer->m_alphaSpinBox->setVisible(alphaVisibility);
2257 d_pointer->m_buttonBox->setVisible(!d_pointer->m_options.testFlag(
2258 QColorDialog::ColorDialogOption::NoButtons));
2273 return d_pointer->m_options.testFlag(option);
2345 return d_pointer->m_selectedColor;
2361 d_pointer->m_selectedColor =
QColor();
2362 d_pointer->applyLayoutDimensions();
2370 d_pointer->m_buttonOK->setDefault(
true);
2379 if (
result == QDialog::DialogCode::Accepted) {
2381 auto history = d_pointer->m_settings.history.value();
2382 const auto maxHistoryLenght = std::max(d_pointer->historySwatchCount,
2385 history.removeAll(d_pointer->m_selectedColor);
2387 history.prepend(d_pointer->m_selectedColor);
2389 while (history.count() > maxHistoryLenght) {
2390 history.removeLast();
2392 d_pointer->m_settings.history.setValue(history);
2395 d_pointer->m_selectedColor =
QColor();
2398 if (d_pointer->m_receiverToBeDisconnected) {
2407 d_pointer->m_receiverToBeDisconnected,
2408 d_pointer->m_memberToBeDisconnected.
constData()
2410 d_pointer->m_receiverToBeDisconnected =
nullptr;
2418 return d_pointer->m_layoutDimensions;
2425 if (newLayoutDimensions == d_pointer->m_layoutDimensions) {
2428 d_pointer->m_layoutDimensions = newLayoutDimensions;
2429 d_pointer->applyLayoutDimensions();
2438void ColorDialogPrivate::applyLayoutDimensions()
2443 constexpr auto screenSizeDependent =
2445 int effectivelyAvailableScreenWidth;
2446 int widthThreeshold;
2447 switch (m_layoutDimensions) {
2449 m_layoutDimensionsEffective = collapsed;
2452 m_layoutDimensionsEffective = expanded;
2454 case screenSizeDependent:
2461 effectivelyAvailableScreenWidth = qRound(
2468 widthThreeshold = qMax(
2469 m_wheelColorPicker->sizeHint().width(),
2470 m_lightnessFirstWrapperWidget->sizeHint().width());
2472 widthThreeshold += m_numericalWidget->sizeHint().width();
2474 widthThreeshold = qRound(widthThreeshold * 1.2);
2477 if (effectivelyAvailableScreenWidth < widthThreeshold) {
2478 m_layoutDimensionsEffective = collapsed;
2480 m_layoutDimensionsEffective = expanded;
2489 if (m_layoutDimensionsEffective == collapsed) {
2490 if (m_selectorLayout->indexOf(m_numericalWidget) >= 0) {
2493 const bool oldUpdatesEnabled = m_tabWidget->updatesEnabled();
2494 m_tabWidget->setUpdatesEnabled(
false);
2498 m_tabWidget->addTab(m_numericalWidget,
QString());
2499 m_tabWidget->setUpdatesEnabled(oldUpdatesEnabled);
2505 q_pointer->adjustSize();
2508 if (m_selectorLayout->indexOf(m_numericalWidget) < 0) {
2511 m_selectorLayout->addWidget(m_numericalWidget);
2514 m_numericalWidget->show();
2516 q_pointer->adjustSize();
2530 const auto type =
event->type();
2539 d_pointer->retranslateUi();
2544 &eventForSwatchBookBasicColors);
2549 &eventForSwatchBookHistory);
2559 &eventForButtonCancel);
2564 d_pointer->reloadIcons();
2582 if (!d_pointer->everShown) {
2584 const bool exp = d_pointer->m_layoutDimensionsEffective == expValue;
2585 const auto tabString = exp
2586 ? d_pointer->m_settings.tabExpanded.value()
2587 : d_pointer->m_settings.tab.value();
2588 const auto key = d_pointer->m_tabTable.
key(tabString,
nullptr);
2589 if (key !=
nullptr) {
2590 d_pointer->m_tabWidget->setCurrentWidget(*key);
2597 d_pointer->saveCurrentTab();
2599 switch (d_pointer->m_settings.swatchBookPage.value()) {
2600 case PerceptualSettings::SwatchBookPage::History:
2601 d_pointer->m_settings.swatchBookPage.setValue(
2602 PerceptualSettings::SwatchBookPage::History);
2603 d_pointer->m_swatchBookSelector->setCurrentIndex(1);
2604 d_pointer->m_swatchBookStack->setCurrentIndex(1);
2606 case PerceptualSettings::SwatchBookPage::BasicColors:
2608 d_pointer->m_settings.swatchBookPage.setValue(
2609 PerceptualSettings::SwatchBookPage::BasicColors);
2610 d_pointer->m_swatchBookSelector->setCurrentIndex(0);
2611 d_pointer->m_swatchBookStack->setCurrentIndex(0);
2615 d_pointer->everShown =
true;
2621void ColorDialogPrivate::saveCurrentTab()
2623 const auto currentIndex = m_tabWidget->currentIndex();
2624 QWidget const *
const widget = m_tabWidget->widget(currentIndex);
2625 const auto keyList = m_tabTable.
keys();
2626 auto it = std::find_if(
2629 [widget](
const auto &key) {
2630 return ((*key) == widget);
2633 if (it != keyList.end()) {
2634 const auto tabString = m_tabTable.
value(*it);
2636 if (m_layoutDimensionsEffective == expValue) {
2637 m_settings.tabExpanded.setValue(tabString);
2639 m_settings.tab.setValue(tabString);
2646void ColorDialogPrivate::loadHistoryFromSettingsToSwatchBook()
2648 Swatches historyArray(historyHSwatchCount,
2649 historyVSwatchCount,
2650 m_settings.history.value());
2651 m_swatchBookHistory->setSwatchGrid(historyArray);
void currentColorChanged(const PerceptualColor::LchDouble &newCurrentColor)
Notify signal for property currentColor.
A perceptually uniform color picker dialog.
void colorSelected(const QColor &color)
This signal is emitted just after the user has clicked OK to select a color to use.
static QColor getColor(const QColor &initial=Qt::white, QWidget *parent=nullptr, const QString &title=QString(), ColorDialogOptions options=ColorDialogOptions())
Pops up a modal color dialog, lets the user choose a color, and returns that color.
virtual void showEvent(QShowEvent *event) override
Handle show events.
virtual void setVisible(bool visible) override
Setter for property visible
Q_INVOKABLE ColorDialog(QWidget *parent=nullptr)
Constructor.
ColorDialogOptions options
Various options that affect the look and feel of the dialog.
Q_INVOKABLE bool testOption(PerceptualColor::ColorDialog::ColorDialogOption option) const
Getter for KConfig Entry Options.
Q_INVOKABLE void setOption(PerceptualColor::ColorDialog::ColorDialogOption option, bool on=true)
Setter for KConfig Entry Options.
QColor currentColor
Currently selected color in the dialog.
void setCurrentColor(const QColor &color)
Setter for currentColor property.
virtual void done(int result) override
Various updates when closing the dialog.
virtual ~ColorDialog() noexcept override
Destructor.
void optionsChanged(const PerceptualColor::ColorDialog::ColorDialogOptions newOptions)
Notify signal for property KConfig Entry Options.
void setOptions(PerceptualColor::ColorDialog::ColorDialogOptions newOptions)
Setter for KConfig Entry Options.
void setLayoutDimensions(const PerceptualColor::ColorDialog::DialogLayoutDimensions newLayoutDimensions)
Setter for property layoutDimensions.
DialogLayoutDimensions
Layout dimensions.
@ Expanded
Use the large, “expanded” layout of this dialog.
@ Collapsed
Use the small, “collapsed“ layout of this dialog.
@ ScreenSizeDependent
Decide automatically between collapsed and expanded layout: collapsed is used on small screens,...
QColorDialog::ColorDialogOptions ColorDialogOptions
Local alias for QColorDialog::ColorDialogOptions.
virtual void changeEvent(QEvent *event) override
Handle state changes.
void layoutDimensionsChanged(const PerceptualColor::ColorDialog::DialogLayoutDimensions newLayoutDimensions)
Notify signal for property layoutDimensions.
Q_INVOKABLE QColor selectedColor() const
The color that was actually selected by the user.
DialogLayoutDimensions layoutDimensions
Layout dimensions.
void colorChanged(const QColor &color)
Notify signal for property color.
void valueChanged(const qreal newValue)
Signal for value property.
void sectionValuesChanged(const QList< double > &newSectionValues)
Notify signal for property sectionValues.
static QSharedPointer< PerceptualColor::RgbColorSpace > createSrgb()
Create an sRGB color space object.
void currentColorChanged(const PerceptualColor::LchDouble &newCurrentColor)
Notify signal for property currentColor.
QString name(StandardAction id)
QString label(StandardShortcut id)
The namespace of this library.
Array2D< QColor > Swatches
Swatches organized in a grid.
ColorSchemeType
Represents the appearance of a theme.
Swatches wcsBasicColors(const QSharedPointer< PerceptualColor::RgbColorSpace > &colorSpace)
Swatch grid derived from the basic colors as by WCS (World color survey).
@ OklchD65
The Oklch color space, which by definition always and exclusively uses a D65 illuminant.
@ CielchD50
The Cielch color space using a D50 illuminant.
void triggered(bool checked)
void addLayout(QLayout *layout, int stretch)
void addStretch(int stretch)
const char * constData() const const
void setNamedColor(QLatin1StringView name)
float alphaF() const const
QColor fromRgbF(float r, float g, float b, float a)
bool isValid() const const
QRgba64 rgba64() const const
void setAlphaF(float alpha)
QColor toRgb() const const
void currentIndexChanged(int index)
QCoreApplication * instance()
bool sendEvent(QObject *receiver, QEvent *event)
bool isNull() const const
virtual void setVisible(bool visible) override
virtual void showEvent(QShowEvent *event) override
void valueChanged(double d)
iterator insert(const Key &key, const T &value)
Key key(const T &value) const const
QList< Key > keys() const const
T value(const Key &key) const const
QKeySequence mnemonic(const QString &text)
void textChanged(const QString &text)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
qsizetype count() const const
bool isEmpty() const const
QString toString(QDate date, FormatType format) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
QObject * parent() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isNull() const const
void activatedAmbiguously()
QString arg(Args &&... args) const const
bool isEmpty() const const
void resize(qsizetype newSize, QChar fillChar)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QString toUpper() const const
QString join(QChar separator) const const
void colorSchemeChanged(Qt::ColorScheme colorScheme)
WindowContextHelpButtonHint
QString toString() const const