diff --git a/core/dplugins/editor/colors/profileconversion/profileconversiontoolplugin.cpp b/core/dplugins/editor/colors/profileconversion/profileconversiontoolplugin.cpp index 4c02ddd415..aef41e7d30 100644 --- a/core/dplugins/editor/colors/profileconversion/profileconversiontoolplugin.cpp +++ b/core/dplugins/editor/colors/profileconversion/profileconversiontoolplugin.cpp @@ -1,220 +1,218 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2018-07-30 * Description : image editor plugin to convert to color space * * Copyright (C) 2018-2019 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "profileconversiontoolplugin.h" // Qt includes #include #include #include // KDE includes #include // Local includes #include "editorwindow.h" #include "profileconversiontool.h" #include "iccsettings.h" #include "iccsettingscontainer.h" #include "icctransform.h" #include "imageiface.h" namespace DigikamEditorProfileConversionToolPlugin { ProfileConversionToolPlugin::ProfileConversionToolPlugin(QObject* const parent) : DPluginEditor(parent) { - m_parent = 0; m_profileMenuAction = 0; m_colorSpaceConverter = 0; } ProfileConversionToolPlugin::~ProfileConversionToolPlugin() { } QString ProfileConversionToolPlugin::name() const { return i18n("Color Profile Conversion"); } QString ProfileConversionToolPlugin::iid() const { return QLatin1String(DPLUGIN_IID); } QIcon ProfileConversionToolPlugin::icon() const { return QIcon::fromTheme(QLatin1String("preferences-desktop-display-color")); } QString ProfileConversionToolPlugin::description() const { return i18n("A tool to convert image to a color space"); } QString ProfileConversionToolPlugin::details() const { return i18n("

This Image Editor tool can can convert image to a different color space.

"); } QList ProfileConversionToolPlugin::authors() const { return QList() << DPluginAuthor(QString::fromUtf8("Marcel Wiesweg"), QString::fromUtf8("marcel dot wiesweg at gmx dot de"), QString::fromUtf8("(C) 2009-2012")) << DPluginAuthor(QString::fromUtf8("Gilles Caulier"), QString::fromUtf8("caulier dot gilles at gmail dot com"), QString::fromUtf8("(C) 2009-2019")) ; } void ProfileConversionToolPlugin::setup(QObject* const parent) { - m_parent = parent; DPluginAction* const ac = new DPluginAction(parent); m_profileMenuAction = new IccProfilesMenuAction(icon(), QString(), parent); connect(m_profileMenuAction, SIGNAL(triggered(IccProfile)), this, SLOT(slotConvertToColorSpace(IccProfile))); connect(IccSettings::instance(), SIGNAL(settingsChanged()), this, SLOT(slotUpdateColorSpaceMenu())); ac->setMenu(m_profileMenuAction); ac->setText(i18n("Color Spaces")); ac->setObjectName(QLatin1String("editorwindow_colormanagement")); ac->setActionCategory(DPluginAction::EditorColors); addAction(ac); DPluginAction* const ac2 = new DPluginAction(parent); ac2->setIcon(icon()); ac2->setText(i18nc("@action", "Color Space Converter...")); ac2->setObjectName(QLatin1String("editorwindow_color_spaceconverter")); ac2->setActionCategory(DPluginAction::EditorColors); connect(ac2, SIGNAL(triggered(bool)), this, SLOT(slotProfileConversionTool())); m_colorSpaceConverter = ac2; addAction(ac2); slotUpdateColorSpaceMenu(); } void ProfileConversionToolPlugin::slotConvertToColorSpace(const IccProfile& profile) { ImageIface iface; if (iface.originalIccProfile().isNull()) { QMessageBox::critical(qApp->activeWindow(), qApp->applicationName(), i18n("This image is not color managed.")); return; } qApp->setOverrideCursor(Qt::WaitCursor); ProfileConversionTool::fastConversion(profile); qApp->restoreOverrideCursor(); } void ProfileConversionToolPlugin::slotUpdateColorSpaceMenu() { m_profileMenuAction->clear(); - EditorWindow* const editor = dynamic_cast(m_parent); + EditorWindow* const editor = dynamic_cast(m_profileMenuAction->parentObject()); if (!IccSettings::instance()->isEnabled()) { QAction* const action = new QAction(i18n("Color Management is disabled..."), this); m_profileMenuAction->addAction(action); if (editor) { connect(action, SIGNAL(triggered()), editor, SLOT(slotSetupICC())); } } else { ICCSettingsContainer settings = IccSettings::instance()->settings(); QList standardProfiles, favoriteProfiles; QSet standardProfilePaths, favoriteProfilePaths; standardProfiles << IccProfile::sRGB() << IccProfile::adobeRGB() << IccProfile::wideGamutRGB() << IccProfile::proPhotoRGB(); foreach (IccProfile profile, standardProfiles) // krazy:exclude=foreach { m_profileMenuAction->addProfile(profile, profile.description()); standardProfilePaths << profile.filePath(); } m_profileMenuAction->addSeparator(); favoriteProfilePaths = QSet::fromList(ProfileConversionTool::favoriteProfiles()); favoriteProfilePaths -= standardProfilePaths; foreach (const QString& path, favoriteProfilePaths) { favoriteProfiles << IccProfile(path); } m_profileMenuAction->addProfiles(favoriteProfiles); } m_profileMenuAction->addSeparator(); m_profileMenuAction->addAction(m_colorSpaceConverter); if (editor) { m_colorSpaceConverter->setEnabled(editor->actionEnabledState() && IccSettings::instance()->isEnabled()); } } void ProfileConversionToolPlugin::slotProfileConversionTool() { EditorWindow* const editor = dynamic_cast(sender()->parent()); if (editor) { ProfileConversionTool* const tool = new ProfileConversionTool(this); tool->setPlugin(this); connect(tool, SIGNAL(okClicked()), this, SLOT(slotUpdateColorSpaceMenu())); editor->loadTool(tool); } } } // namespace DigikamEditorProfileConversionToolPlugin diff --git a/core/dplugins/editor/colors/profileconversion/profileconversiontoolplugin.h b/core/dplugins/editor/colors/profileconversion/profileconversiontoolplugin.h index 2e33edd97c..38c231b736 100644 --- a/core/dplugins/editor/colors/profileconversion/profileconversiontoolplugin.h +++ b/core/dplugins/editor/colors/profileconversion/profileconversiontoolplugin.h @@ -1,73 +1,72 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2018-07-30 * Description : image editor plugin to convert to color space * * Copyright (C) 2018-2019 by Gilles Caulier * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_PROFILECONVERSIONTOOL_PLUGIN_H #define DIGIKAM_PROFILECONVERSIONTOOL_PLUGIN_H // Local includes #include "dplugineditor.h" #include "iccprofilescombobox.h" #define DPLUGIN_IID "org.kde.digikam.plugin.editor.ProfileConversionTool" using namespace Digikam; namespace DigikamEditorProfileConversionToolPlugin { class ProfileConversionToolPlugin : public DPluginEditor { Q_OBJECT Q_PLUGIN_METADATA(IID DPLUGIN_IID) Q_INTERFACES(Digikam::DPluginEditor) public: explicit ProfileConversionToolPlugin(QObject* const parent = 0); ~ProfileConversionToolPlugin(); QString name() const override; QString iid() const override; QIcon icon() const override; QString details() const override; QString description() const override; QList authors() const override; void setup(QObject* const) override; private Q_SLOTS: void slotConvertToColorSpace(const IccProfile& profile); void slotUpdateColorSpaceMenu(); void slotProfileConversionTool(); private: IccProfilesMenuAction* m_profileMenuAction; QAction* m_colorSpaceConverter; - QObject* m_parent; }; } // namespace DigikamEditorProfileConversionToolPlugin #endif // DIGIKAM_PROFILECONVERSIONTOOL_PLUGIN_H diff --git a/core/libs/widgets/iccprofiles/iccprofilescombobox.cpp b/core/libs/widgets/iccprofiles/iccprofilescombobox.cpp index 4709891c23..c32efedc48 100644 --- a/core/libs/widgets/iccprofiles/iccprofilescombobox.cpp +++ b/core/libs/widgets/iccprofiles/iccprofilescombobox.cpp @@ -1,318 +1,323 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2009-08-11 * Description : a combo box containing ICC profiles * * Copyright (C) 2009-2010 by Marcel Wiesweg * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #include "iccprofilescombobox.h" // Qt includes #include #include #include #include #include #include // KDE includes #include // Local includes #include "icctransform.h" namespace Digikam { IccProfilesComboBox::IccProfilesComboBox(QWidget* const parent) : SqueezedComboBox( parent ) { } IccProfilesComboBox::~IccProfilesComboBox() { } bool iccProfileLessThan(IccProfile a, IccProfile b) { return a.description() < b.description(); } // if needed outside this class, make it a public static method in a namespace static QString profileUserString(const IccProfile& p) { IccProfile profile(p); QFileInfo info(profile.filePath()); QString fileName = info.fileName(); QString description = profile.description(); if (!description.isEmpty() && !fileName.isEmpty()) { return i18nc(" ()", "%1 (%2)", description, fileName); } else if (!fileName.isEmpty()) { return fileName; } else { return QString(); } } // if needed outside this class, make it a public static method in a namespace static void formatProfiles(const QList& givenProfiles, QList* const returnedProfiles, QStringList* const userText) { QList profiles; QSet filePaths; foreach (IccProfile profile, givenProfiles) // krazy:exclude=foreach { QString filePath = profile.filePath(); if (!profile.description().isNull() && (filePath.isNull() || !filePaths.contains(filePath)) ) { profiles << profile; filePaths << filePath; } } std::sort(profiles.begin(), profiles.end(), iccProfileLessThan); foreach (IccProfile profile, profiles) // krazy:exclude=foreach { QString description = profileUserString(profile); if (description.isNull()) { continue; } *returnedProfiles << profile; *userText << description; } } void IccProfilesComboBox::addProfilesSqueezed(const QList& givenProfiles) { QList profiles; QStringList userDescription; formatProfiles(givenProfiles, &profiles, &userDescription); for (int i = 0 ; i < profiles.size() ; ++i) { addSqueezedItem(userDescription.at(i), QVariant::fromValue(profiles.at(i))); } } void IccProfilesComboBox::addProfileSqueezed(const IccProfile& profile, const QString& d) { QString description = d; if (description.isNull()) { description = profileUserString(profile); } addSqueezedItem(description, QVariant::fromValue(profile)); } void IccProfilesComboBox::replaceProfilesSqueezed(const QList& profiles) { IccProfile current = currentProfile(); clear(); addProfilesSqueezed(profiles); setCurrentProfile(current); } void IccProfilesComboBox::setNoProfileIfEmpty(const QString& message) { if (count() == 0) { setEnabled(false); addSqueezedItem(message); setCurrentIndex(0); } } IccProfile IccProfilesComboBox::currentProfile() const { return itemData(currentIndex()).value(); } void IccProfilesComboBox::setCurrentProfile(const IccProfile& profile) { if (profile.isNull()) { setCurrentIndex(-1); return; } const int size = count(); for (int i = 0 ; i < size ; ++i) { if (itemData(i).value() == profile) { setCurrentIndex(i); return; } } setCurrentIndex(-1); } // ------------------------------------------------------------------------------------------ IccProfilesMenuAction::IccProfilesMenuAction(const QIcon& icon, const QString& text, QObject* const parent) : QMenu(text), m_parent(parent) { setIcon(icon); m_mapper = new QSignalMapper(this); connect(m_mapper, SIGNAL(mapped(QObject*)), this, SLOT(slotTriggered(QObject*))); } IccProfilesMenuAction::IccProfilesMenuAction(const QString& text, QObject* const parent) : QMenu(text), m_parent(parent) { m_mapper = new QSignalMapper(this); connect(m_mapper, SIGNAL(mapped(QObject*)), this, SLOT(slotTriggered(QObject*))); } void IccProfilesMenuAction::replaceProfiles(const QList& profiles) { clear(); addProfiles(profiles); } void IccProfilesMenuAction::addProfiles(const QList& givenProfiles) { QList profiles; QStringList userDescription; formatProfiles(givenProfiles, &profiles, &userDescription); for (int i = 0 ; i < profiles.size() ; ++i) { addProfile(profiles.at(i), userDescription.at(i)); } } void IccProfilesMenuAction::addProfile(const IccProfile& profile, const QString& d) { QString description = d; if (description.isNull()) { description = profileUserString(profile); } QAction* const action = new QAction(d.left(50), m_parent); action->setData(QVariant::fromValue(profile)); addAction(action); connect(action, SIGNAL(triggered()), m_mapper, SLOT(map())); m_mapper->setMapping(action, action); } void IccProfilesMenuAction::disableIfEmpty() { if (isEmpty()) { setEnabled(false); } } void IccProfilesMenuAction::slotTriggered(QObject* obj) { QAction* const action = static_cast(obj); IccProfile profile = action->data().value(); if (!profile.isNull()) { emit triggered(profile); } } +QObject* IccProfilesMenuAction::parentObject() const +{ + return m_parent; +} + // ------------------------------------------------------------------------------------------ IccRenderingIntentComboBox::IccRenderingIntentComboBox(QWidget* const parent) : QComboBox(parent) { addItem(QLatin1String("Perceptual"), IccTransform::Perceptual); addItem(QLatin1String("Relative Colorimetric"), IccTransform::RelativeColorimetric); addItem(QLatin1String("Absolute Colorimetric"), IccTransform::AbsoluteColorimetric); addItem(QLatin1String("Saturation"), IccTransform::Saturation); setWhatsThis( i18n("
  • Perceptual intent causes the full gamut of the image to be " "compressed or expanded to fill the gamut of the destination device, so that gray balance is " "preserved but colorimetric accuracy may not be preserved.

    " "

    In other words, if certain colors in an image fall outside of the range of colors that the output " "device can render, the image intent will cause all the colors in the image to be adjusted so that " "the every color in the image falls within the range that can be rendered and so that the relationship " "between colors is preserved as much as possible.

    " "

    This intent is most suitable for display of photographs and images, and is the default intent.

  • " "
  • Absolute Colorimetric intent causes any colors that fall outside the range that the output device " "can render to be adjusted to the closest color that can be rendered, while all other colors are " "left unchanged.

    " "

    This intent preserves the white point and is most suitable for spot colors (Pantone, TruMatch, " "logo colors, ....)

  • " "
  • Relative Colorimetric intent is defined such that any colors that fall outside the range that the " "output device can render are adjusted to the closest color that can be rendered, while all other colors " "are left unchanged. Proof intent does not preserve the white point.

  • " "
  • Saturation intent preserves the saturation of colors in the image at the possible expense of " "hue and lightness.

    " "

    Implementation of this intent remains somewhat problematic, and the ICC is still working on methods to " "achieve the desired effects.

    " "

    This intent is most suitable for business graphics such as charts, where it is more important that the " "colors be vivid and contrast well with each other rather than a specific color.

")); } void IccRenderingIntentComboBox::setIntent(int intent) { const int size = count(); for (int i = 0 ; i < size ; ++i) { if (itemData(i).toInt() == intent) { setCurrentIndex(i); return; } } setCurrentIndex(-1); } int IccRenderingIntentComboBox::intent() const { return itemData(currentIndex()).toInt(); } } // namespace Digikam diff --git a/core/libs/widgets/iccprofiles/iccprofilescombobox.h b/core/libs/widgets/iccprofiles/iccprofilescombobox.h index 0476f0d3b6..8a4897d175 100644 --- a/core/libs/widgets/iccprofiles/iccprofilescombobox.h +++ b/core/libs/widgets/iccprofiles/iccprofilescombobox.h @@ -1,145 +1,150 @@ /* ============================================================ * * This file is a part of digiKam project * https://www.digikam.org * * Date : 2009-08-11 * Description : a combo box containing ICC profiles * * Copyright (C) 2009-2010 by Marcel Wiesweg * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software Foundation; * either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * ============================================================ */ #ifndef DIGIKAM_ICC_PROFILES_COMBOBOX_H #define DIGIKAM_ICC_PROFILES_COMBOBOX_H // Qt includes #include #include #include // Local includes #include "squeezedcombobox.h" #include "digikam_export.h" #include "iccprofile.h" class QSignalMapper; namespace Digikam { class DIGIKAM_EXPORT IccProfilesComboBox : public SqueezedComboBox { Q_OBJECT public: explicit IccProfilesComboBox(QWidget* const parent = 0); ~IccProfilesComboBox(); /** * Checks the given profiles for validity, creates a suitable description (ICC profile description, file path), * removes duplicates by file path, sorts them and adds them in sorted order. */ void addProfilesSqueezed(const QList& profiles); /** * Add the given profile with the given description, or, if null, a standard description. * Does not test for duplicity, does not sort into existing profiles. */ void addProfileSqueezed(const IccProfile& profile, const QString& description = QString()); /** * Clears, does the same as addProfilesSqueezed, and restores the current entry if possible. */ void replaceProfilesSqueezed(const QList& profiles); /** * Sets a message the is displayed in the combo box and disables the combo box, * if the combo box is currently empty */ void setNoProfileIfEmpty(const QString& message); /** Retrieves the current profile, or a null profile if none is selected. */ IccProfile currentProfile() const; /** Sets the current profile. If profile is not in the list, sets no current item (-1) */ void setCurrentProfile(const IccProfile& profile); /// Use the signal currentIndexChanged(int) for change notification }; // ---------------------------------------------------------------------------- class DIGIKAM_EXPORT IccRenderingIntentComboBox : public QComboBox { public: explicit IccRenderingIntentComboBox(QWidget* const parent = 0); void setIntent(int intent); int intent() const; }; // ---------------------------------------------------------------------------- class DIGIKAM_EXPORT IccProfilesMenuAction : public QMenu { Q_OBJECT public: IccProfilesMenuAction(const QIcon& icon, const QString& text, QObject* const parent); IccProfilesMenuAction(const QString& text, QObject* const parent); /** * Checks the given profiles for validity, creates a suitable description (ICC profile description, file path), * removes duplicates (in newly added list) by file path, sorts them and adds them in sorted order. */ void addProfiles(const QList& profile); /** * Add the given profile with the given description, or, if null, a standard description. * Does not test for duplicity, does not sort into existing profiles. */ void addProfile(const IccProfile& profile, const QString& description = QString()); /** * Equivalent to calling clear() and addProfiles(). */ void replaceProfiles(const QList& profile); /** * Disables if the menu is currently empty. */ void disableIfEmpty(); + /** + * Return the parent QObject. + */ + QObject* parentObject() const; + Q_SIGNALS: void triggered(const IccProfile& profile); protected Q_SLOTS: void slotTriggered(QObject*); protected: QObject* m_parent; QSignalMapper* m_mapper; }; } // namespace Digikam #endif // DIGIKAM_ICC_PROFILES_COMBOBOX_H