1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date        : 2006-05-15
7  * Description : a dialog to see preview ICC color correction
8  *               before to apply color profile.
9  *
10  * Copyright (C) 2006-2021 by Gilles Caulier <caulier dot gilles at gmail dot com>
11  *
12  * This program is free software; you can redistribute it
13  * and/or modify it under the terms of the GNU General
14  * Public License as published by the Free Software Foundation;
15  * either version 2, or (at your option)
16  * any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * ============================================================ */
24 
25 #include "colorcorrectiondlg.h"
26 
27 // Qt includes
28 
29 #include <QCheckBox>
30 #include <QFrame>
31 #include <QFileInfo>
32 #include <QGridLayout>
33 #include <QGroupBox>
34 #include <QHBoxLayout>
35 #include <QLabel>
36 #include <QRadioButton>
37 #include <QStandardPaths>
38 #include <QIcon>
39 #include <QDialogButtonBox>
40 #include <QVBoxLayout>
41 #include <QPushButton>
42 
43 // KDE includes
44 
45 #include <klocalizedstring.h>
46 
47 // Local includes
48 
49 #include "dlayoutbox.h"
50 #include "dimg.h"
51 #include "iccmanager.h"
52 #include "iccsettings.h"
53 #include "icctransform.h"
54 #include "iccprofileinfodlg.h"
55 #include "iccprofilescombobox.h"
56 #include "dxmlguiwindow.h"
57 #include "dexpanderbox.h"
58 
59 namespace Digikam
60 {
61 
62 class Q_DECL_HIDDEN ColorCorrectionDlg::Private
63 {
64 public:
65 
Private()66     explicit Private()
67       : imageProfileTitle    (nullptr),
68         imageProfileDesc     (nullptr),
69         previewTarget        (nullptr),
70         keepProfile          (nullptr),
71         convertToWorkingSpace(nullptr),
72         thirdOption          (nullptr),
73         thirdCheckBox        (nullptr),
74         imageSRGB            (nullptr),
75         imageWorkingSpace    (nullptr),
76         imageOtherSpace      (nullptr),
77         buttons              (nullptr),
78         otherProfileBox      (nullptr),
79         imageProfileBox      (nullptr),
80         mode                 (ColorCorrectionDlg::ProfileMismatch)
81     {
82     }
83 
84     DImg                     preview;
85     QString                  filePath;
86 
87     QLabel*                  imageProfileTitle;
88     QLabel*                  imageProfileDesc;
89     QLabel*                  previewTarget;
90 
91     QRadioButton*            keepProfile;
92     QRadioButton*            convertToWorkingSpace;
93     QRadioButton*            thirdOption;
94     QCheckBox*               thirdCheckBox;
95 
96     QRadioButton*            imageSRGB;
97     QRadioButton*            imageWorkingSpace;
98     QRadioButton*            imageOtherSpace;
99 
100     QDialogButtonBox*        buttons;
101 
102     IccProfilesComboBox*     otherProfileBox;
103     IccProfilesComboBox*     imageProfileBox;
104 
105     ColorCorrectionDlg::Mode mode;
106 
107     IccProfile               workspaceProfile;
108     IccProfile               imageProfile;
109     IccProfile               outputProfile;
110 };
111 
ColorCorrectionDlg(Mode mode,const DImg & preview,const QString & file,QWidget * const parent)112 ColorCorrectionDlg::ColorCorrectionDlg(Mode mode,
113                                        const DImg& preview,
114                                        const QString& file,
115                                        QWidget* const parent)
116     : QDialog(parent),
117       d      (new Private)
118 {
119     setModal(true);
120 
121     d->buttons = new QDialogButtonBox(QDialogButtonBox::Help | QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
122     d->buttons->button(QDialogButtonBox::Ok)->setDefault(true);
123     d->buttons->button(QDialogButtonBox::Cancel)->setText(i18n("Do not know"));
124     d->buttons->button(QDialogButtonBox::Cancel)->setToolTip(i18n("Take the safest and most appropriate action"));
125 
126     d->mode                          = mode;
127     d->preview                       = preview;
128     d->filePath                      = file;
129     ICCSettingsContainer iccSettings = IccSettings::instance()->settings();
130     d->workspaceProfile              = IccProfile(iccSettings.workspaceProfile);
131 
132     QString caption;
133 
134     if      (d->mode == ProfileMismatch)
135     {
136         caption = i18n("Color Profile Mismatch");
137     }
138     else if (d->mode == MissingProfile)
139     {
140         caption = i18n("Missing Color Profile");
141     }
142     else if (d->mode == UncalibratedColor)
143     {
144         caption = i18n("Image with Uncalibrated Color");
145     }
146 
147     if (!file.isNull())
148     {
149         QFileInfo fi(file);
150         caption = i18nc("<Problem> - <b>", "%1 - %2", caption, fi.fileName());
151     }
152 
153     setWindowTitle(caption);
154 
155     QWidget* const page     = new QWidget(this);
156     QGridLayout* const grid = new QGridLayout(page);
157 
158     if      (d->mode == ProfileMismatch)
159     {
160         grid->addLayout(createHeading(),       0, 0, 1, 2);
161         grid->addLayout(createProfilesInfo(),  1, 0);
162         grid->addLayout(createPreviews(),      1, 1, 2, 1);
163         grid->addWidget(createOptions(),       3, 0, 1, 2);
164     }
165     else if (d->mode == MissingProfile)
166     {
167         QVBoxLayout* vbox = new QVBoxLayout;
168         vbox->addWidget(createAssumeOptions());
169         vbox->addLayout(createProfilesInfo());
170         vbox->addStretch(1);
171 
172         grid->addLayout(createHeading(),       0, 0, 1, 2);
173         grid->addLayout(vbox,                  1, 0);
174         grid->addLayout(createPreviews(),      1, 1, 2, 1);
175         grid->addWidget(createOptions(),       3, 0, 1, 2);
176         grid->setRowStretch(1, 1);
177         grid->setRowStretch(3, 1);
178     }
179     else if (d->mode == UncalibratedColor)
180     {
181         grid->addLayout(createHeading(),       0, 0, 1, 2);
182         grid->addLayout(createProfilesInfo(),  1, 0,       Qt::AlignTop);
183         grid->addLayout(createPreviews(),      1, 1, 2, 1);
184         grid->addWidget(createAssumeOptions(), 3, 0, 1, 2);
185     }
186 
187     page->setLayout(grid);
188 
189     QVBoxLayout* const vbx = new QVBoxLayout(this);
190     vbx->addWidget(page);
191     vbx->addWidget(d->buttons);
192     setLayout(vbx);
193 
194     connect(d->buttons->button(QDialogButtonBox::Ok), SIGNAL(clicked()),
195             this, SLOT(slotOk()));
196 
197     connect(d->buttons->button(QDialogButtonBox::Cancel), SIGNAL(clicked()),
198             this, SLOT(reject()));
199 
200     connect(d->buttons->button(QDialogButtonBox::Help), SIGNAL(clicked()),
201             this, SLOT(slotHelp()));
202 
203     readSettings();
204     updateImageProfileUI();
205     updateUsedProfileUI();
206     updateInfo();
207 }
208 
~ColorCorrectionDlg()209 ColorCorrectionDlg::~ColorCorrectionDlg()
210 {
211     delete d;
212 }
213 
slotOk()214 void ColorCorrectionDlg::slotOk()
215 {
216     accept();
217     setSettings();
218 }
219 
createHeading() const220 QLayout* ColorCorrectionDlg::createHeading() const
221 {
222     QLabel* const icon    = new QLabel;
223     icon->setPixmap(QIcon::fromTheme(QLatin1String("fill-color")).pixmap(32));
224 
225     QLabel* const message = new QLabel;
226 
227     if      (d->mode == ProfileMismatch)
228     {
229         message->setText(i18n("<p>This image has an <b>embedded color profile</b><br/> "
230                               "which does not match your working space color profile.<br/>"
231                               "How do you want to proceed?</p>"));
232     }
233     else if (d->mode == MissingProfile)
234     {
235         message->setText(i18n("<p>This image has <b>no information about the color space</b><br/>"
236                               "that was used when creating the image. <br/>"
237                               "How do you want to proceed?</p>"));
238 
239     }
240     else if (d->mode == UncalibratedColor)
241     {
242         message->setText(i18n("<p>The color information of this image is uncalibrated.<br/>"
243                               "How do you want to proceed?</p>"));
244     }
245 
246     message->setWordWrap(true);
247 
248     QLabel* const logo      = new QLabel;
249     logo->setPixmap(QIcon::fromTheme(QLatin1String("digikam")).pixmap(QSize(48,48)));
250 
251     DLineWidget* const line = new DLineWidget(Qt::Horizontal);
252 
253     QGridLayout* const grid = new QGridLayout;
254     grid->addWidget(icon,    0, 0);
255     grid->addWidget(message, 0, 1);
256     grid->addWidget(logo,    0, 2);
257     grid->addWidget(line,    1, 0, 1, 3);
258     grid->setColumnStretch(1, 1);
259 
260     return grid;
261 }
262 
createProfilesInfo() const263 QLayout* ColorCorrectionDlg::createProfilesInfo() const
264 {
265     QVBoxLayout* const vbox = new QVBoxLayout;
266 
267     if ((d->mode == ProfileMismatch) || (d->mode == UncalibratedColor))
268     {
269         d->imageProfileTitle = new QLabel;
270 
271         if      (d->mode == ProfileMismatch)
272         {
273             d->imageProfileTitle->setText(i18n("Embedded Color Profile:"));
274         }
275 /*
276         else if (d->mode == MissingProfile)
277         {
278             d->imageProfileTitle->setText(i18n("Image Color Profile:"));
279         }
280 */
281         else if (d->mode == UncalibratedColor)
282         {
283             d->imageProfileTitle->setText(i18n("Input Color Profile:"));
284         }
285 
286         d->imageProfileDesc              = new QLabel;
287         QPushButton* const imageProfInfo = new QPushButton(i18n("Info..."));
288 /*
289         d->imageProfileTitle->setWordWrap(true);
290 */
291         d->imageProfileDesc->setWordWrap(true);
292 
293         vbox->addWidget(d->imageProfileTitle);
294         vbox->addWidget(d->imageProfileDesc);
295         vbox->addWidget(imageProfInfo, 0, Qt::AlignLeft);
296 
297         connect(imageProfInfo, SIGNAL(clicked()),
298                 this, SLOT(slotImageProfInfo()));
299     }
300 
301     QLabel* const workspaceProfileTitle  = new QLabel(i18n("Working Color Space:"));
302     QLabel* const workspaceProfileDesc   = new QLabel(QString::fromUtf8("<b>%1</b>").arg(d->workspaceProfile.description()));
303     QPushButton* const workspaceProfInfo = new QPushButton(i18n("Info..."));
304 /*
305     workspaceProfileTitle->setWordWrap(true);
306 */
307     workspaceProfileDesc->setWordWrap(true);
308 
309     vbox->addWidget(workspaceProfileTitle);
310     vbox->addWidget(workspaceProfileDesc);
311     vbox->addWidget(workspaceProfInfo, 0, Qt::AlignLeft);
312 
313     connect(workspaceProfInfo, SIGNAL(clicked()),
314             this, SLOT(slotWorkspaceProfInfo()));
315 
316     return vbox;
317 }
318 
createPreviews() const319 QLayout* ColorCorrectionDlg::createPreviews() const
320 {
321     QGridLayout* const grid     = new QGridLayout;
322     QLabel* const originalTitle = new QLabel;
323 
324     if      (d->mode == ProfileMismatch)
325     {
326         originalTitle->setText(i18n("Original Colors:"));
327     }
328     else if (d->mode == MissingProfile)
329     {
330         originalTitle->setText(i18n("Uncorrected Colors:"));
331     }
332     else if (d->mode == UncalibratedColor)
333     {
334         originalTitle->setText(i18n("Raw Colors:"));
335     }
336 
337     originalTitle->setWordWrap(true);
338 
339     QLabel* const previewOriginal = new QLabel;
340     DImg copyOriginal             = d->preview.copy();
341     IccManager manager(copyOriginal);
342     manager.transformForDisplay();
343     previewOriginal->setPixmap(copyOriginal.convertToPixmap());
344 
345     QLabel* const targetTitle = new QLabel;
346 
347     if      (d->mode == ProfileMismatch)
348     {
349         targetTitle->setText(i18n("Resulting Colors:"));
350     }
351     else if (d->mode == MissingProfile)
352     {
353         targetTitle->setText(i18n("Correction Applied:"));
354     }
355     else if (d->mode == UncalibratedColor)
356     {
357         targetTitle->setText(i18n("Corrected Colors:"));
358     }
359 
360     targetTitle->setWordWrap(true);
361 
362     d->previewTarget = new QLabel;
363 
364     if (d->preview.width() > d->preview.height())
365     {
366         grid->addWidget(originalTitle,    0, 0, Qt::AlignTop);
367         grid->addWidget(previewOriginal,  1, 0);
368         grid->addWidget(targetTitle,      2, 0, Qt::AlignTop);
369         grid->addWidget(d->previewTarget, 3, 0);
370     }
371     else
372     {
373         grid->addWidget(originalTitle,    0, 0, Qt::AlignTop);
374         grid->addWidget(previewOriginal,  1, 0);
375         grid->addWidget(targetTitle,      0, 1, Qt::AlignTop);
376         grid->addWidget(d->previewTarget, 1, 1);
377     }
378 
379     return grid;
380 }
381 
createOptions() const382 QWidget* ColorCorrectionDlg::createOptions() const
383 {
384     QGroupBox* const box = new QGroupBox;
385 
386     if (d->mode == ProfileMismatch)
387     {
388         QVBoxLayout* const vbox  = new QVBoxLayout(box);
389         d->keepProfile           = new QRadioButton(i18n("Keep the embedded profile, do not convert"));
390         d->convertToWorkingSpace = new QRadioButton(i18n("Convert to working color space"));
391         d->thirdOption           = new QRadioButton(i18n("Ignore embedded profile, assign this profile:"));
392         d->otherProfileBox       = new IccProfilesComboBox;
393         d->otherProfileBox->addProfilesSqueezed(IccSettings::instance()->workspaceProfiles());
394         d->thirdCheckBox         = new QCheckBox(i18n("and then convert to working space"));
395 
396         d->keepProfile->setChecked(true);
397         d->otherProfileBox->setCurrentProfile(IccProfile::adobeRGB());
398         d->otherProfileBox->setNoProfileIfEmpty(i18n("No Profile Available"));
399 
400         if (d->otherProfileBox->count() == 0) // disable if empty
401         {
402             d->thirdOption->setEnabled(false);
403             d->otherProfileBox->setEnabled(false);
404         }
405 
406         QHBoxLayout* const hboxAssign = new QHBoxLayout;
407         hboxAssign->addSpacing(10);
408         hboxAssign->addWidget(d->otherProfileBox);
409         hboxAssign->addWidget(d->thirdCheckBox);
410         hboxAssign->setSpacing(0);
411 
412         vbox->addWidget(d->keepProfile);
413         vbox->addWidget(d->convertToWorkingSpace);
414         vbox->addWidget(d->thirdOption);
415         vbox->addLayout(hboxAssign);
416 
417         connect(d->keepProfile, SIGNAL(toggled(bool)),
418                 this, SLOT(imageProfileToggled(bool)));
419 
420         connect(d->convertToWorkingSpace, SIGNAL(toggled(bool)),
421                 this, SLOT(imageProfileToggled(bool)));
422 
423         connect(d->thirdOption, SIGNAL(toggled(bool)),
424                 this, SLOT(imageProfileToggled(bool)));
425 
426         connect(d->thirdCheckBox, SIGNAL(toggled(bool)),
427                 this, SLOT(imageProfileToggled(bool)));
428 
429         connect(d->otherProfileBox, SIGNAL(currentIndexChanged(int)),
430                 this, SLOT(imageProfileChanged()));
431     }
432     else if (d->mode == MissingProfile)
433     {
434         QVBoxLayout* const vbox  = new QVBoxLayout(box);
435         d->convertToWorkingSpace = new QRadioButton(i18n("Assign profile and convert to working color space"));
436         d->keepProfile           = new QRadioButton(i18n("Assign and keep color profile"));
437         d->thirdOption           = new QRadioButton(i18n("Leave the file untagged, do not color manage"));
438 
439         d->convertToWorkingSpace->setChecked(true);
440 
441         vbox->addWidget(d->convertToWorkingSpace);
442         vbox->addWidget(d->keepProfile);
443         vbox->addWidget(d->thirdOption);
444 
445         connect(d->keepProfile, SIGNAL(toggled(bool)),
446                 this, SLOT(missingProfileToggled(bool)));
447 
448         connect(d->convertToWorkingSpace, SIGNAL(toggled(bool)),
449                 this, SLOT(missingProfileToggled(bool)));
450 
451         connect(d->thirdOption, SIGNAL(toggled(bool)),
452                 this, SLOT(missingProfileToggled(bool)));
453     }
454     else if (d->mode == UncalibratedColor)
455     {
456         // empty
457 /*
458         QVBoxLayout* const vbox  = new QVBoxLayout(box);
459         d->convertToWorkingSpace = new QRadioButton(i18n("Convert to working color space"));
460         d->thirdOption           = new QRadioButton(i18n("Convert to this profile:"));
461         d->otherProfileBox       = new IccProfilesComboBox;
462         d->otherProfileBox->addProfilesSqueezed(IccSettings::instance()->workspaceProfiles());
463 
464         vbox->addWidget(d->convertToWorkingSpace);
465         vbox->addWidget(d->thirdOption);
466         vbox->addWidget(d->otherProfileBox);
467 */
468     }
469 
470     return box;
471 }
472 
createAssumeOptions() const473 QWidget* ColorCorrectionDlg::createAssumeOptions() const
474 {
475     QGroupBox* const box = new QGroupBox;
476 
477     if (d->mode == ProfileMismatch)
478     {
479         // unused
480     }
481     else if (d->mode == MissingProfile)
482     {
483         QGridLayout* const grid = new QGridLayout(box);
484         QLabel* const label     = new QLabel(i18n("Which color space shall be used to interpret the colors of this image?"));
485         label->setWordWrap(true);
486 
487         d->imageSRGB         = new QRadioButton(i18n("sRGB (Internet standard)"));
488         d->imageWorkingSpace = new QRadioButton(i18n("Current working color space"));
489         d->imageOtherSpace   = new QRadioButton(i18n("This profile:"));
490         d->imageProfileBox   = new IccProfilesComboBox;
491         d->imageProfileBox->addProfilesSqueezed(IccSettings::instance()->workspaceProfiles()
492                                                 << IccSettings::instance()->inputProfiles());
493         QPushButton* const usedProfInfo = new QPushButton(i18n("Info..."));
494 
495         d->imageSRGB->setChecked(true);
496         d->imageProfileBox->setCurrentProfile(IccProfile::adobeRGB());
497         d->imageProfileBox->setNoProfileIfEmpty(i18n("No Profile Available"));
498 
499         if (d->imageProfileBox->count() == 0) // disable if empty
500         {
501             d->imageOtherSpace->setEnabled(false);
502             d->imageProfileBox->setEnabled(false);
503         }
504 
505         grid->addWidget(label,                0, 0, 1, 2);
506         grid->addWidget(d->imageSRGB,         1, 0, 1, 2);
507         grid->addWidget(d->imageWorkingSpace, 2, 0, 1, 2);
508         grid->addWidget(d->imageOtherSpace,   3, 0, 1, 2);
509         grid->addWidget(d->imageProfileBox,   4, 1);
510         grid->addWidget(usedProfInfo,         5, 0, 1, 2, Qt::AlignLeft);
511         grid->setColumnMinimumWidth(0, 10);
512         grid->setColumnStretch(1, 1);
513 
514         connect(d->imageProfileBox, SIGNAL(currentIndexChanged(int)),
515                 this, SLOT(usedProfileChanged()));
516 
517         connect(d->imageSRGB, SIGNAL(toggled(bool)),
518                 this, SLOT(usedProfileToggled(bool)));
519 
520         connect(d->imageWorkingSpace, SIGNAL(toggled(bool)),
521                 this, SLOT(usedProfileToggled(bool)));
522 
523         connect(d->imageOtherSpace, SIGNAL(toggled(bool)),
524                 this, SLOT(usedProfileToggled(bool)));
525 
526         connect(usedProfInfo, SIGNAL(clicked()),
527                 this, SLOT(slotImageProfInfo()));
528     }
529     else if (d->mode == UncalibratedColor)
530     {
531         QGridLayout* const grid = new QGridLayout(box);
532         QLabel* const label     = new QLabel(i18n("Please select the input color profile of the device (camera) "
533                                                   "used to create this image:"));
534         label->setWordWrap(true);
535 
536         d->imageProfileBox = new IccProfilesComboBox;
537         d->imageProfileBox->addProfilesSqueezed(IccSettings::instance()->inputProfiles());
538         d->imageProfileBox->setCurrentProfile(IccProfile(IccSettings::instance()->settings().defaultInputProfile));
539         d->imageProfileBox->setNoProfileIfEmpty(i18n("No Input Profile Available"));
540 
541         grid->addWidget(label);
542         grid->addWidget(d->imageProfileBox);
543 
544         connect(d->imageProfileBox, SIGNAL(currentIndexChanged(int)),
545                 this, SLOT(inputProfileChanged()));
546     }
547 
548     return box;
549 }
550 
imageProfileToggled(bool on)551 void ColorCorrectionDlg::imageProfileToggled(bool on)
552 {
553     if (!on)
554     {
555         return;
556     }
557 
558     imageProfileChanged();
559 }
560 
imageProfileChanged()561 void ColorCorrectionDlg::imageProfileChanged()
562 {
563     updateImageProfileUI();
564     updateInfo();
565 }
566 
updateImageProfileUI()567 void ColorCorrectionDlg::updateImageProfileUI()
568 {
569     if (d->otherProfileBox)
570     {
571         d->otherProfileBox->setEnabled(d->thirdOption->isChecked());
572     }
573 
574     if (d->thirdCheckBox)
575     {
576         d->thirdCheckBox->setEnabled(d->thirdOption->isChecked());
577     }
578 }
579 
missingProfileToggled(bool on)580 void ColorCorrectionDlg::missingProfileToggled(bool on)
581 {
582     if (!on)
583     {
584         return;
585     }
586 
587     missingProfileChanged();
588 }
589 
missingProfileChanged()590 void ColorCorrectionDlg::missingProfileChanged()
591 {
592     updateInfo();
593 }
594 
usedProfileToggled(bool on)595 void ColorCorrectionDlg::usedProfileToggled(bool on)
596 {
597     if (!on)
598     {
599         return;
600     }
601 
602     usedProfileChanged();
603 }
604 
usedProfileChanged()605 void ColorCorrectionDlg::usedProfileChanged()
606 {
607     updateUsedProfileUI();
608     updateInfo();
609 }
610 
updateUsedProfileUI()611 void ColorCorrectionDlg::updateUsedProfileUI()
612 {
613     if (d->imageProfileBox && d->imageOtherSpace)
614     {
615         d->imageProfileBox->setEnabled(d->imageOtherSpace->isChecked());
616     }
617 }
618 
inputProfileChanged()619 void ColorCorrectionDlg::inputProfileChanged()
620 {
621     updateInfo();
622 }
623 
updateInfo()624 void ColorCorrectionDlg::updateInfo()
625 {
626     setCursor(Qt::WaitCursor);
627 
628     DImg colorPreview                = d->preview.copy();
629     IccManager manager(colorPreview);
630     ICCSettingsContainer::Behavior b = currentBehavior();
631     d->imageProfile                  = manager.imageProfile(b, specifiedProfile());
632 
633     if (d->mode == ProfileMismatch)
634     {
635         if (b & ICCSettingsContainer::UseSpecifiedProfile)
636         {
637             d->imageProfileTitle->setText(i18n("Assigned Color Profile:"));
638         }
639         else
640         {
641             d->imageProfileTitle->setText(i18n("Embedded Color Profile:"));
642         }
643     }
644 
645     if ((d->mode == ProfileMismatch) || (d->mode == UncalibratedColor))
646     {
647         QString description = d->imageProfile.description();
648 
649         if (description.isEmpty())
650         {
651             d->imageProfileDesc->setText(i18n("<b>No Profile</b>"));
652         }
653         else
654         {
655             d->imageProfileDesc->setText(QString::fromUtf8("<b>%1</b>").arg(description));
656         }
657     }
658 
659     manager.transform(currentBehavior(), specifiedProfile());
660     manager.transformForDisplay(this);
661     d->previewTarget->setPixmap(colorPreview.convertToPixmap());
662 
663     unsetCursor();
664 }
665 
slotWorkspaceProfInfo()666 void ColorCorrectionDlg::slotWorkspaceProfInfo()
667 {
668     ICCProfileInfoDlg infoDlg(parentWidget(), QString(), d->workspaceProfile);
669     infoDlg.exec();
670 }
671 
slotImageProfInfo()672 void ColorCorrectionDlg::slotImageProfInfo()
673 {
674     if (d->imageProfile.isNull())
675     {
676         return;
677     }
678 
679     ICCProfileInfoDlg infoDlg(parentWidget(), QString(), d->imageProfile);
680     infoDlg.exec();
681 }
682 
behavior() const683 ICCSettingsContainer::Behavior ColorCorrectionDlg::behavior() const
684 {
685     if (result() == QDialog::Rejected)
686     {
687         return ICCSettingsContainer::SafestBestAction;
688     }
689 
690     return currentBehavior();
691 }
692 
currentBehavior() const693 ICCSettingsContainer::Behavior ColorCorrectionDlg::currentBehavior() const
694 {
695     if      (d->mode == ProfileMismatch)
696     {
697         if      (d->keepProfile->isChecked())
698         {
699             return ICCSettingsContainer::PreserveEmbeddedProfile;
700         }
701         else if (d->convertToWorkingSpace->isChecked())
702         {
703             return ICCSettingsContainer::EmbeddedToWorkspace;
704         }
705         else if (d->thirdOption->isChecked())
706         {
707             if (d->thirdCheckBox->isChecked())
708             {
709                 return ICCSettingsContainer::UseSpecifiedProfile | ICCSettingsContainer::ConvertToWorkspace;
710             }
711             else
712             {
713                 return ICCSettingsContainer::UseSpecifiedProfile | ICCSettingsContainer::KeepProfile;
714             }
715         }
716     }
717     else if (d->mode == MissingProfile)
718     {
719         if (d->thirdOption->isChecked())
720         {
721             return ICCSettingsContainer::NoColorManagement;
722         }
723 
724         ICCSettingsContainer::Behavior behavior;
725 
726         if      (d->keepProfile->isChecked())
727         {
728             behavior |= ICCSettingsContainer::KeepProfile;
729         }
730         else if (d->convertToWorkingSpace->isChecked())
731         {
732             behavior |= ICCSettingsContainer::ConvertToWorkspace;
733         }
734 
735         if      (d->imageSRGB->isChecked())
736         {
737             behavior |= ICCSettingsContainer::UseSRGB;
738         }
739         else if (d->imageWorkingSpace->isChecked())
740         {
741             behavior |= ICCSettingsContainer::UseWorkspace;
742         }
743         else if (d->imageOtherSpace->isChecked())
744         {
745             behavior |= ICCSettingsContainer::UseSpecifiedProfile;
746         }
747 
748         return behavior;
749     }
750     else if (d->mode == UncalibratedColor)
751     {
752         return (ICCSettingsContainer::ConvertToWorkspace | ICCSettingsContainer::UseSpecifiedProfile);
753     }
754 
755     return ICCSettingsContainer::SafestBestAction;
756 }
757 
specifiedProfile() const758 IccProfile ColorCorrectionDlg::specifiedProfile() const
759 {
760     if      (d->mode == ProfileMismatch)
761     {
762         return d->otherProfileBox->currentProfile();
763     }
764     else if ((d->mode == MissingProfile) || (d->mode == UncalibratedColor))
765     {
766         return d->imageProfileBox->currentProfile();
767     }
768 
769     return IccProfile();
770 }
771 
readSettings()772 void ColorCorrectionDlg::readSettings()
773 {
774     ICCSettingsContainer settings = IccSettings::instance()->settings();
775 
776     if      (d->mode == ProfileMismatch)
777     {
778         if ((settings.lastMismatchBehavior & ICCSettingsContainer::UseSpecifiedProfile) &&
779             d->otherProfileBox->count() > 0)
780         {
781             d->thirdOption->setChecked(true);
782             d->thirdCheckBox->setChecked(settings.lastMismatchBehavior & ICCSettingsContainer::ConvertToWorkspace);
783             d->thirdOption->setFocus();
784         }
785         else
786         {
787             if      (settings.lastMismatchBehavior & ICCSettingsContainer::KeepProfile)
788             {
789                 d->keepProfile->setChecked(true);
790                 d->keepProfile->setFocus();
791             }
792             else if (settings.lastMismatchBehavior & ICCSettingsContainer::ConvertToWorkspace)
793             {
794                 d->convertToWorkingSpace->setChecked(true);
795                 d->convertToWorkingSpace->setFocus();
796             }
797         }
798 
799         if (!settings.lastSpecifiedAssignProfile.isEmpty())
800         {
801             d->otherProfileBox->setCurrentProfile(IccProfile(settings.lastSpecifiedAssignProfile));
802         }
803     }
804     else if (d->mode == MissingProfile)
805     {
806         if (settings.lastMissingProfileBehavior == ICCSettingsContainer::NoColorManagement)
807         {
808             d->imageSRGB->setChecked(true); // ?
809             d->thirdOption->setChecked(true);
810             d->thirdOption->setFocus();
811         }
812         else
813         {
814             if      (settings.lastMissingProfileBehavior & ICCSettingsContainer::KeepProfile)
815             {
816                 d->keepProfile->setChecked(true);
817                 d->keepProfile->setFocus();
818             }
819             else if (settings.lastMissingProfileBehavior & ICCSettingsContainer::ConvertToWorkspace)
820             {
821                 d->convertToWorkingSpace->setChecked(true);
822                 d->convertToWorkingSpace->setFocus();
823             }
824 
825             if (settings.lastMissingProfileBehavior & ICCSettingsContainer::UseSRGB)
826             {
827                 d->imageSRGB->setChecked(true);
828             }
829 
830             if (settings.lastMissingProfileBehavior & ICCSettingsContainer::UseWorkspace)
831             {
832                 d->imageWorkingSpace->setChecked(true);
833             }
834 
835             if ((settings.lastMissingProfileBehavior & ICCSettingsContainer::UseSpecifiedProfile) &&
836                 (d->imageProfileBox->count() > 0))
837             {
838                 d->imageOtherSpace->setChecked(true);
839             }
840         }
841 
842         if (!settings.lastSpecifiedInputProfile.isEmpty())
843         {
844             d->imageProfileBox->setCurrentProfile(IccProfile(settings.lastSpecifiedInputProfile));
845         }
846     }
847     else if (d->mode == UncalibratedColor)
848     {
849         d->imageProfileBox->setCurrentProfile(IccProfile(settings.lastSpecifiedInputProfile));
850         d->imageProfileBox->setFocus();
851     }
852 }
853 
setSettings()854 void ColorCorrectionDlg::setSettings()
855 {
856     ICCSettingsContainer settings = IccSettings::instance()->settings();
857 
858     if      (d->mode == ProfileMismatch)
859     {
860         settings.lastMismatchBehavior       = currentBehavior();
861         settings.lastSpecifiedAssignProfile = specifiedProfile().filePath();
862     }
863     else if (d->mode == MissingProfile)
864     {
865         settings.lastMissingProfileBehavior = currentBehavior();
866         settings.lastSpecifiedInputProfile  = specifiedProfile().filePath();
867     }
868     else if (d->mode == UncalibratedColor)
869     {
870         settings.lastUncalibratedBehavior  = currentBehavior();
871         settings.lastSpecifiedInputProfile = specifiedProfile().filePath();
872     }
873 
874     IccSettings::instance()->setSettings(settings);
875 }
876 
slotHelp()877 void ColorCorrectionDlg::slotHelp()
878 {
879     DXmlGuiWindow::openHandbook();
880 }
881 
882 } // namespace Digikam
883