gmic/krita5.patch
Christophe Marin 390726d1ec - switch all the Qt gui implementations to Qt6 except for the krita
one, as this also still pulls KF5 libraries, not sure how well
  mixing KF5 and QT6 would work. (boo#1218653#c14)

OBS-URL: https://build.opensuse.org/package/show/graphics/gmic?expand=0&rev=109
2025-01-10 20:44:43 +00:00

1443 lines
53 KiB
Diff

From c4b6796080d5c0f76b64fee06a38d285ab462a75 Mon Sep 17 00:00:00 2001
From: Christophe Marin <christophe@krop.fr>
Date: Fri, 28 Jun 2024 09:46:58 +0200
Subject: [PATCH] Krita 5 plugin support
Origin: https://github.com/amyspark/gmic
Rebased for gmic 3.4.0
---
gmic-qt/CMakeLists.txt | 68 ++++-
gmic-qt/gmic_krita_qt.desktop | 9 +
gmic-qt/src/DialogSettings.cpp | 33 ++-
.../src/FilterParameters/BoolParameter.cpp | 2 +
.../src/FilterParameters/FloatParameter.cpp | 3 +-
gmic-qt/src/FilterParameters/IntParameter.cpp | 2 +
.../src/FilterParameters/NoteParameter.cpp | 2 +
.../FilterParameters/SeparatorParameter.cpp | 2 +
.../src/FilterSelector/FiltersPresenter.cpp | 2 +-
gmic-qt/src/Globals.h | 19 ++
gmic-qt/src/GmicProcessor.cpp | 5 +
gmic-qt/src/GmicProcessor.h | 1 +
gmic-qt/src/GmicQt.cpp | 6 +-
gmic-qt/src/HeadlessProcessor.cpp | 5 +-
.../src/Host/KritaPlugin/gmicqttoolplugin.cpp | 233 ++++++++++++++++++
.../src/Host/KritaPlugin/gmicqttoolplugin.h | 55 +++++
.../Host/KritaPlugin/gmicqttoolplugin.json | 9 +
gmic-qt/src/Host/KritaPlugin/host.cpp | 195 +++++++++++++++
gmic-qt/src/Host/None/JpegQualityDialog.cpp | 6 +-
gmic-qt/src/LanguageSettings.cpp | 9 +-
gmic-qt/src/MainWindow.cpp | 52 +++-
gmic-qt/src/MainWindow.h | 2 +
gmic-qt/src/Settings.cpp | 10 +-
gmic-qt/src/Tags.cpp | 6 +-
gmic-qt/src/Widgets/InOutPanel.cpp | 2 +
gmic-qt/src/Widgets/InOutPanel.h | 2 +
gmic-qt/src/Widgets/ProgressInfoWindow.cpp | 4 +
gmic-qt/src/Widgets/ProgressInfoWindow.h | 2 +
gmic-qt/ui/dialogsettings.ui | 2 +-
29 files changed, 716 insertions(+), 32 deletions(-)
create mode 100644 gmic-qt/gmic_krita_qt.desktop
create mode 100644 gmic-qt/src/Host/KritaPlugin/gmicqttoolplugin.cpp
create mode 100644 gmic-qt/src/Host/KritaPlugin/gmicqttoolplugin.h
create mode 100644 gmic-qt/src/Host/KritaPlugin/gmicqttoolplugin.json
create mode 100644 gmic-qt/src/Host/KritaPlugin/host.cpp
diff --git a/gmic-qt/CMakeLists.txt b/gmic-qt/CMakeLists.txt
index 47face8..0641f4c 100644
--- a/gmic-qt/CMakeLists.txt
+++ b/gmic-qt/CMakeLists.txt
@@ -30,7 +30,7 @@ endif()
message("Build type is " ${CMAKE_BUILD_TYPE})
-set (GMIC_QT_HOST "gimp" CACHE STRING "Define for which host gmic-qt will be built: gimp, gimp3 (experimental), none, paintdotnet or 8bf.")
+set (GMIC_QT_HOST "gimp" CACHE STRING "Define for which host gmic-qt will be built: gimp, gimp3 (experimental), krita-plugin, none, paintdotnet or 8bf.")
if (${GMIC_QT_HOST} STREQUAL "none")
message("Building standalone version.")
else()
@@ -701,6 +701,70 @@ if (${GMIC_QT_HOST} STREQUAL "gimp" OR ${GMIC_QT_HOST} STREQUAL "gimp3")
)
install(TARGETS gmic_gimp_qt RUNTIME DESTINATION "${GIMP_PKGLIBDIR}/plug-ins/gmic_gimp_qt")
+elseif (${GMIC_QT_HOST} STREQUAL "krita-plugin")
+ set(MIN_FRAMEWORKS_VERSION 5.44.0)
+
+ find_package(ECM 5.22 REQUIRED NOMODULE)
+ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
+
+ include(KDEInstallDirs)
+ include(KDECMakeSettings)
+
+ if (ANDROID)
+ set (KRITA_PLUGIN_INSTALL_DIR ${LIB_INSTALL_DIR})
+ else()
+ set (KRITA_PLUGIN_INSTALL_DIR ${LIB_INSTALL_DIR}/kritaplugins)
+ endif()
+
+ find_package(KF5 ${MIN_FRAMEWORKS_VERSION} REQUIRED COMPONENTS
+ CoreAddons
+ )
+
+ message(STATUS "Looking for Krita QMic libraries in: ${CMAKE_PREFIX_PATH}")
+
+ find_library(KIS_IMAGE_INTERFACE_LIBRARY
+ NAMES kritaqmicinterface
+ REQUIRED)
+
+ find_path(KIS_IMAGE_INTERFACE_DIR
+ NAMES kis_qmic_plugin_interface.h
+ REQUIRED)
+
+ set_package_properties(kritaqmicinterface PROPERTIES
+ URL "http://www.krita.org"
+ DESCRIPTION "Krita GMic core library"
+ )
+
+ set (gmic_qt_SRCS ${gmic_qt_SRCS} src/Host/KritaPlugin/host.cpp src/Host/KritaPlugin/gmicqttoolplugin.cpp)
+ set (gmic_qt_SRCS ${gmic_qt_SRCS} )
+ qt5_wrap_ui(gmic_qt_SRCS ${gmic_qt_FORMS})
+ add_definitions(-DGMIC_HOST=krita-plugin)
+ add_definitions(-D_GMIC_QT_DISABLE_THEMING_)
+ add_definitions(-D_GMIC_QT_CONSENT_TO_UPDATE_FIRST_)
+ add_definitions(-D_GMIC_QT_DISABLE_TRANSLATION_)
+ add_definitions(-D_GMIC_USE_HOSTED_SETTINGS_)
+ add_library(krita_gmic_qt MODULE ${gmic_qt_SRCS} ${gmic_qt_QRC} ${qmic_qt_QM})
+ target_include_directories(
+ krita_gmic_qt
+ PUBLIC
+ ${KIS_IMAGE_INTERFACE_DIR}
+ )
+ target_link_libraries(
+ krita_gmic_qt
+ PRIVATE
+ ${gmic_qt_LIBRARIES}
+ ${KIS_IMAGE_INTERFACE_LIBRARY}
+ KF5::CoreAddons
+ )
+ if (ANDROID)
+ target_link_libraries(
+ krita_gmic_qt
+ PRIVATE
+ log
+ )
+ endif()
+ install(TARGETS krita_gmic_qt DESTINATION ${KRITA_PLUGIN_INSTALL_DIR}) # plugin
+
elseif (${GMIC_QT_HOST} STREQUAL "none")
set (gmic_qt_SRCS ${gmic_qt_SRCS}
@@ -783,7 +847,7 @@ elseif (${GMIC_QT_HOST} STREQUAL "8bf")
else()
- message(FATAL_ERROR "GMIC_QT_HOST is not defined as gimp, gimp3, none, paintdotnet or 8bf")
+ message(FATAL_ERROR "GMIC_QT_HOST is not defined as gimp, gimp3, krita-plugin, none, paintdotnet or 8bf")
endif()
diff --git a/gmic-qt/gmic_krita_qt.desktop b/gmic-qt/gmic_krita_qt.desktop
new file mode 100644
index 0000000..579d427
--- /dev/null
+++ b/gmic-qt/gmic_krita_qt.desktop
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Name=gmic_krita_qt
+Exec=gmic_krita_qt
+GenericName=G'Mic plugin for Krita
+Comment=G'Mic plugin for Krita
+Type=Application
+Icon=gmic_krita_qt
+Categories=Qt;KDE;Graphics;
+StartupNotify=false
diff --git a/gmic-qt/src/DialogSettings.cpp b/gmic-qt/src/DialogSettings.cpp
index 6c1e6b9..29328c4 100644
--- a/gmic-qt/src/DialogSettings.cpp
+++ b/gmic-qt/src/DialogSettings.cpp
@@ -56,11 +56,7 @@ DialogSettings::DialogSettings(QWidget * parent) : QDialog(parent), ui(new Ui::D
#ifdef _GMIC_QT_DEBUG_
ui->cbUpdatePeriodicity->addItem(tr("At launch (debug)"), QVariant(0));
#endif
- for (int i = 0; i < ui->cbUpdatePeriodicity->count(); ++i) {
- if (Settings::updatePeriodicity() == ui->cbUpdatePeriodicity->itemData(i).toInt()) {
- ui->cbUpdatePeriodicity->setCurrentIndex(i);
- }
- }
+ ui->cbUpdatePeriodicity->setCurrentIndex(ui->cbUpdatePeriodicity->findData(Settings::updatePeriodicity()));
ui->outputMessages->setToolTip(tr("Output messages"));
ui->outputMessages->addItem(tr("Quiet (default)"), (int)OutputMessageMode::Quiet);
@@ -81,9 +77,12 @@ DialogSettings::DialogSettings(QWidget * parent) : QDialog(parent), ui(new Ui::D
ui->rbLeftPreview->setChecked(Settings::previewPosition() == MainWindow::PreviewPosition::Left);
ui->rbRightPreview->setChecked(Settings::previewPosition() == MainWindow::PreviewPosition::Right);
- const bool savedDarkTheme = QSettings().value(DARK_THEME_KEY, GmicQtHost::DarkThemeIsDefault).toBool();
+ const bool savedDarkTheme = GMIC_SETTINGS_INLINE.value(DARK_THEME_KEY, GmicQtHost::DarkThemeIsDefault).toBool();
ui->rbDarkTheme->setChecked(savedDarkTheme);
ui->rbDefaultTheme->setChecked(!savedDarkTheme);
+#ifdef _GMIC_QT_DISABLE_THEMING_
+ ui->groupBoxTheme->setEnabled(false);
+#endif
ui->cbNativeColorDialogs->setChecked(Settings::nativeColorDialogs());
ui->cbNativeColorDialogs->setToolTip(tr("Check to use Native/OS color dialog, uncheck to use Qt's"));
ui->cbNativeFileDialogs->setChecked(Settings::nativeFileDialogs());
@@ -95,19 +94,33 @@ DialogSettings::DialogSettings(QWidget * parent) : QDialog(parent), ui(new Ui::D
connect(ui->pbOk, &QPushButton::clicked, this, &DialogSettings::onOk);
connect(ui->rbLeftPreview, &QRadioButton::toggled, this, &DialogSettings::onRadioLeftPreviewToggled);
+#ifdef _GMIC_QT_DISABLE_UPDATES_
+ ui->pbUpdate->setEnabled(false);
+#else
connect(ui->pbUpdate, &QPushButton::clicked, this, &DialogSettings::onUpdateClicked);
+#endif
+#ifdef _GMIC_QT_DISABLE_UPDATES_
+ ui->cbUpdatePeriodicity->setEnabled(false);
+#else
connect(ui->cbUpdatePeriodicity, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &DialogSettings::onUpdatePeriodicityChanged);
+#endif
connect(ui->labelPreviewLeft, &ClickableLabel::clicked, ui->rbLeftPreview, &QRadioButton::click);
connect(ui->labelPreviewRight, &ClickableLabel::clicked, ui->rbRightPreview, &QRadioButton::click);
connect(ui->cbNativeColorDialogs, &QCheckBox::toggled, this, &DialogSettings::onColorDialogsToggled);
connect(ui->cbNativeFileDialogs, &QCheckBox::toggled, this, &DialogSettings::onFileDialogsToggled);
connect(Updater::getInstance(), &Updater::updateIsDone, this, &DialogSettings::enableUpdateButton);
+#ifndef _GMIC_QT_DISABLE_THEMING_
connect(ui->rbDarkTheme, &QRadioButton::toggled, this, &DialogSettings::onDarkThemeToggled);
+#endif
connect(ui->cbShowLogos, &QCheckBox::toggled, this, &DialogSettings::onVisibleLogosToggled);
connect(ui->cbPreviewZoom, &QCheckBox::toggled, this, &DialogSettings::onPreviewZoomToggled);
connect(ui->sbPreviewTimeout, QOverload<int>::of(&QSpinBox::valueChanged), this, &DialogSettings::onPreviewTimeoutChange);
connect(ui->outputMessages, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &DialogSettings::onOutputMessageModeChanged);
+#ifdef _GMIC_QT_DISABLE_UPDATES_
+ ui->cbNotifyFailedUpdate->setEnabled(false);
+#else
connect(ui->cbNotifyFailedUpdate, &QCheckBox::toggled, this, &DialogSettings::onNotifyStartupUpdateFailedToggle);
+#endif
#if QT_VERSION_GTE(6, 0, 0)
ui->cbHighDPI->hide();
@@ -117,9 +130,14 @@ DialogSettings::DialogSettings(QWidget * parent) : QDialog(parent), ui(new Ui::D
connect(ui->cbHighDPI, &QCheckBox::toggled, this, &DialogSettings::onHighDPIToggled);
#endif
+#ifdef _GMIC_QT_DISABLE_TRANSLATION_
+ ui->languageSelector->setEnabled(false);
+#else
ui->languageSelector->selectLanguage(Settings::languageCode());
ui->languageSelector->enableFilterTranslation(Settings::filterTranslationEnabled());
+#endif
+#ifndef _GMIC_QT_DISABLE_THEMING_
if (Settings::darkThemeEnabled()) {
QPalette p = ui->cbNativeColorDialogs->palette();
p.setColor(QPalette::Text, Settings::CheckBoxTextColor);
@@ -136,6 +154,7 @@ DialogSettings::DialogSettings(QWidget * parent) : QDialog(parent), ui(new Ui::D
ui->cbNotifyFailedUpdate->setPalette(p);
ui->cbHighDPI->setPalette(p);
}
+#endif
ui->pbOk->setFocus();
ui->tabWidget->setCurrentIndex(0);
}
@@ -157,7 +176,7 @@ void DialogSettings::onOk()
void DialogSettings::done(int r)
{
- QSettings settings;
+ GMIC_SETTINGS(settings);
ui->sources->saveSettings();
Settings::save(settings);
QDialog::done(r);
diff --git a/gmic-qt/src/FilterParameters/BoolParameter.cpp b/gmic-qt/src/FilterParameters/BoolParameter.cpp
index ffa324e..a9dfb04 100644
--- a/gmic-qt/src/FilterParameters/BoolParameter.cpp
+++ b/gmic-qt/src/FilterParameters/BoolParameter.cpp
@@ -64,12 +64,14 @@ bool BoolParameter::addTo(QWidget * widget, int row)
_checkBox = new QCheckBox(widget);
_checkBox->setChecked(_value);
_label = new QLabel(_name, widget);
+#ifndef _GMIC_QT_DISABLE_THEMING_
if (Settings::darkThemeEnabled()) {
QPalette p = _checkBox->palette();
p.setColor(QPalette::Text, Settings::CheckBoxTextColor);
p.setColor(QPalette::Base, Settings::CheckBoxBaseColor);
_checkBox->setPalette(p);
}
+#endif
_grid->addWidget(_label, row, 0, 1, 1);
_grid->addWidget(_checkBox, row, 1, 1, 2);
connectCheckBox();
diff --git a/gmic-qt/src/FilterParameters/FloatParameter.cpp b/gmic-qt/src/FilterParameters/FloatParameter.cpp
index fb271f0..c8aa32b 100644
--- a/gmic-qt/src/FilterParameters/FloatParameter.cpp
+++ b/gmic-qt/src/FilterParameters/FloatParameter.cpp
@@ -73,13 +73,14 @@ bool FloatParameter::addTo(QWidget * widget, int row)
_slider->setMinimumWidth(SLIDER_MIN_WIDTH);
_slider->setRange(0, SLIDER_MAX_RANGE);
_slider->setValue(static_cast<int>(SLIDER_MAX_RANGE * (_value - _min) / (_max - _min)));
+#ifndef _GMIC_QT_DISABLE_THEMING_
if (Settings::darkThemeEnabled()) {
QPalette p = _slider->palette();
p.setColor(QPalette::Button, QColor(100, 100, 100));
p.setColor(QPalette::Highlight, QColor(130, 130, 130));
_slider->setPalette(p);
}
-
+#endif
_spinBox = new CustomDoubleSpinBox(widget, _min, _max);
_spinBox->setSingleStep(double(_max - _min) / 100.0);
_spinBox->setValue((double)_value);
diff --git a/gmic-qt/src/FilterParameters/IntParameter.cpp b/gmic-qt/src/FilterParameters/IntParameter.cpp
index 2af87cb..bc0f77c 100644
--- a/gmic-qt/src/FilterParameters/IntParameter.cpp
+++ b/gmic-qt/src/FilterParameters/IntParameter.cpp
@@ -81,12 +81,14 @@ bool IntParameter::addTo(QWidget * widget, int row)
_spinBox = new CustomSpinBox(widget, _min, _max);
_spinBox->setValue(_value);
+#ifndef _GMIC_QT_DISABLE_THEMING_
if (Settings::darkThemeEnabled()) {
QPalette p = _slider->palette();
p.setColor(QPalette::Button, QColor(100, 100, 100));
p.setColor(QPalette::Highlight, QColor(130, 130, 130));
_slider->setPalette(p);
}
+#endif
_grid->addWidget(_label = new QLabel(_name, widget), row, 0, 1, 1);
setTextSelectable(_label);
_grid->addWidget(_slider, row, 1, 1, 1);
diff --git a/gmic-qt/src/FilterParameters/NoteParameter.cpp b/gmic-qt/src/FilterParameters/NoteParameter.cpp
index e576b0f..be469de 100644
--- a/gmic-qt/src/FilterParameters/NoteParameter.cpp
+++ b/gmic-qt/src/FilterParameters/NoteParameter.cpp
@@ -88,12 +88,14 @@ bool NoteParameter::initFromText(const QString & /* filterName */, const char *
_text.remove(QRegularExpression("^\"")).remove(QRegularExpression("\"$")).replace(QString("\\\""), "\"");
_text.replace(QString("\\n"), "<br/>");
+#ifndef _GMIC_QT_DISABLE_THEMING_
if (Settings::darkThemeEnabled()) {
_text.replace(QRegularExpression("color\\s*=\\s*\"purple\""), QString("color=\"#ff00ff\""));
_text.replace(QRegularExpression("foreground\\s*=\\s*\"purple\""), QString("foreground=\"#ff00ff\""));
_text.replace(QRegularExpression("color\\s*=\\s*\"blue\""), QString("color=\"#9b9bff\""));
_text.replace(QRegularExpression("foreground\\s*=\\s*\"blue\""), QString("foreground=\"#9b9bff\""));
}
+#endif
_text.replace(QRegularExpression("color\\s*=\\s*\""), QString("style=\"color:"));
_text.replace(QRegularExpression("foreground\\s*=\\s*\""), QString("style=\"color:"));
diff --git a/gmic-qt/src/FilterParameters/SeparatorParameter.cpp b/gmic-qt/src/FilterParameters/SeparatorParameter.cpp
index fad7b0a..7f6d317 100644
--- a/gmic-qt/src/FilterParameters/SeparatorParameter.cpp
+++ b/gmic-qt/src/FilterParameters/SeparatorParameter.cpp
@@ -58,9 +58,11 @@ bool SeparatorParameter::addTo(QWidget * widget, int row)
_frame->setSizePolicy(sizePolicy);
_frame->setFrameShape(QFrame::HLine);
_frame->setFrameShadow(QFrame::Sunken);
+#ifndef _GMIC_QT_DISABLE_THEMING_
if (Settings::darkThemeEnabled()) {
_frame->setStyleSheet("QFrame{ border-top: 0px none #a0a0a0; border-bottom: 2px solid rgb(160,160,160);}");
}
+#endif
_grid->addWidget(_frame, row, 0, 1, 3);
return true;
}
diff --git a/gmic-qt/src/FilterSelector/FiltersPresenter.cpp b/gmic-qt/src/FilterSelector/FiltersPresenter.cpp
index 3d2991c..3df386d 100644
--- a/gmic-qt/src/FilterSelector/FiltersPresenter.cpp
+++ b/gmic-qt/src/FilterSelector/FiltersPresenter.cpp
@@ -431,7 +431,7 @@ void FiltersPresenter::expandFaveFolder()
void FiltersPresenter::expandPreviousSessionExpandedFolders()
{
if (_filtersView) {
- QList<QString> expandedFolderPaths = QSettings().value("Config/ExpandedFolders", QStringList()).toStringList();
+ QList<QString> expandedFolderPaths = GMIC_SETTINGS_INLINE.value("Config/ExpandedFolders", QStringList()).toStringList();
_filtersView->expandFolders(expandedFolderPaths);
}
}
diff --git a/gmic-qt/src/Globals.h b/gmic-qt/src/Globals.h
index b19a38d..9ab3e3b 100644
--- a/gmic-qt/src/Globals.h
+++ b/gmic-qt/src/Globals.h
@@ -59,7 +59,13 @@ const char WarningPrefix = '!';
#define ONE_WEEK_HOURS (7 * 24)
#define TWO_WEEKS_HOURS (14 * 24)
#define ONE_MONTH_HOURS (30 * 24)
+#ifdef _GMIC_QT_CONSENT_TO_UPDATE_FIRST_
+#define INTERNET_DEFAULT_PERIODICITY INTERNET_NEVER_UPDATE_PERIODICITY
+#define INTERNET_DEFAULT_REFRESH_UPDATE 0
+#else
#define INTERNET_DEFAULT_PERIODICITY ONE_MONTH_HOURS
+#define INTERNET_DEFAULT_REFRESH_UPDATE 1
+#endif
#define PREVIEW_MAX_ZOOM_FACTOR 40.0
@@ -68,4 +74,17 @@ const char WarningPrefix = '!';
#define KEYPOINTS_INTERACTIVE_MIDDLE_DELAY_MS ((KEYPOINTS_INTERACTIVE_LOWER_DELAY_MS + KEYPOINTS_INTERACTIVE_UPPER_DELAY_MS) / 2)
#define KEYPOINTS_INTERACTIVE_AVERAGING_COUNT 6
+#ifdef _GMIC_USE_HOSTED_SETTINGS_
+#ifdef Q_OS_MACOS
+#define GMIC_SETTINGS(x) QSettings x(GMIC_QT_ORGANISATION_DOMAIN, GMIC_QT_APPLICATION_NAME)
+#define GMIC_SETTINGS_INLINE QSettings(GMIC_QT_ORGANISATION_DOMAIN, GMIC_QT_APPLICATION_NAME)
+#else
+#define GMIC_SETTINGS(x) QSettings x(GMIC_QT_ORGANISATION_NAME, GMIC_QT_APPLICATION_NAME)
+#define GMIC_SETTINGS_INLINE QSettings(GMIC_QT_ORGANISATION_NAME, GMIC_QT_APPLICATION_NAME)
+#endif
+#else
+#define GMIC_SETTINGS(x) QSettings x
+#define GMIC_SETTINGS_INLINE QSettings()
+#endif
+
#endif // GMIC_QT_GLOBALS_H
diff --git a/gmic-qt/src/GmicProcessor.cpp b/gmic-qt/src/GmicProcessor.cpp
index 80c93c1..0019a1f 100644
--- a/gmic-qt/src/GmicProcessor.cpp
+++ b/gmic-qt/src/GmicProcessor.cpp
@@ -209,6 +209,11 @@ bool GmicProcessor::isIdle() const
return !_filterThread;
}
+bool GmicProcessor::isInputImagesEmpty() const
+{
+ return _gmicImages->is_empty();
+}
+
int GmicProcessor::duration() const
{
if (_filterThread) {
diff --git a/gmic-qt/src/GmicProcessor.h b/gmic-qt/src/GmicProcessor.h
index cecdd1a..e85cb57 100644
--- a/gmic-qt/src/GmicProcessor.h
+++ b/gmic-qt/src/GmicProcessor.h
@@ -94,6 +94,7 @@ public:
bool isProcessingFullImage() const;
bool isProcessing() const;
bool isIdle() const;
+ bool isInputImagesEmpty() const;
bool hasUnfinishedAbortedThreads() const;
const gmic_library::gmic_image<float> & previewImage() const;
diff --git a/gmic-qt/src/GmicQt.cpp b/gmic-qt/src/GmicQt.cpp
index 3af90b3..17b98c3 100644
--- a/gmic-qt/src/GmicQt.cpp
+++ b/gmic-qt/src/GmicQt.cpp
@@ -87,7 +87,7 @@ RunParameters lastAppliedFilterRunParameters(ReturnedRunParametersFlag flag)
{
configureApplication();
RunParameters parameters;
- QSettings settings;
+ GMIC_SETTINGS(settings);
const QString path = settings.value(QString("LastExecution/host_%1/FilterPath").arg(GmicQtHost::ApplicationShortname)).toString();
parameters.filterPath = path.toStdString();
QString args = settings.value(QString("LastExecution/host_%1/Arguments").arg(GmicQtHost::ApplicationShortname)).toString();
@@ -197,7 +197,7 @@ int run(UserInterfaceMode interfaceMode, //
LanguageSettings::installTranslators();
MainWindow mainWindow;
mainWindow.setPluginParameters(parameters);
- if (QSettings().value("Config/MainWindowMaximized", false).toBool()) {
+ if (GMIC_SETTINGS_INLINE.value("Config/MainWindowMaximized", false).toBool()) {
mainWindow.showMaximized();
} else {
mainWindow.show();
@@ -545,9 +545,11 @@ namespace
void configureApplication()
{
+#ifndef _GMIC_USE_HOSTED_SETTINGS_
QCoreApplication::setOrganizationName(GMIC_QT_ORGANISATION_NAME);
QCoreApplication::setOrganizationDomain(GMIC_QT_ORGANISATION_DOMAIN);
QCoreApplication::setApplicationName(GMIC_QT_APPLICATION_NAME);
+#endif
QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar);
#if !QT_VERSION_GTE(6, 0, 0)
if (QSettings().value(HIGHDPI_KEY, false).toBool()) {
diff --git a/gmic-qt/src/HeadlessProcessor.cpp b/gmic-qt/src/HeadlessProcessor.cpp
index f10efc3..a595ec1 100644
--- a/gmic-qt/src/HeadlessProcessor.cpp
+++ b/gmic-qt/src/HeadlessProcessor.cpp
@@ -27,6 +27,7 @@
#include <QMessageBox>
#include <QSettings>
#include <QStringList>
+#include "Globals.h"
#include "Common.h"
#include "FilterParameters/FilterParametersWidget.h"
#include "FilterSelector/FiltersPresenter.h"
@@ -234,7 +235,7 @@ void HeadlessProcessor::onProcessingFinished()
GmicQtHost::outputImages(images, _filterThread->imageNames(), _outputMode);
_processingCompletedProperly = true;
}
- QSettings settings;
+ GMIC_SETTINGS(settings);
if (!status.isEmpty() && !_hash.isEmpty()) {
ParametersCache::setValues(_hash, status);
ParametersCache::save();
@@ -267,7 +268,9 @@ void HeadlessProcessor::endApplication(const QString & errorMessage)
if (!errorMessage.isEmpty()) {
Logger::error(errorMessage);
}
+#ifndef _GMIC_USE_HOSTED_SETTINGS_
QCoreApplication::exit(!errorMessage.isEmpty());
+#endif
}
} // namespace GmicQt
diff --git a/gmic-qt/src/Host/KritaPlugin/gmicqttoolplugin.cpp b/gmic-qt/src/Host/KritaPlugin/gmicqttoolplugin.cpp
new file mode 100644
index 0000000..849ca44
--- /dev/null
+++ b/gmic-qt/src/Host/KritaPlugin/gmicqttoolplugin.cpp
@@ -0,0 +1,233 @@
+/*
+ * This file is part of G'MIC-Qt, a generic plug-in for raster graphics
+ * editors, offering hundreds of filters thanks to the underlying G'MIC
+ * image processing framework.
+ *
+ * Copyright (C) 2020-2022 L. E. Segovia <amy@amyspark.me>
+ *
+ * Description: Krita painting suite plugin for G'Mic-Qt.
+ *
+ * G'MIC-Qt 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * G'MIC-Qt 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QApplication>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QEventLoop>
+#include <QPointer>
+#include <QSettings>
+#include <QTranslator>
+#include <list>
+
+#ifdef Q_OS_ANDROID
+#include <android/log.h>
+#include <array>
+#include <iostream>
+#include <thread>
+#include <unistd.h>
+#endif
+
+#include "Settings.h"
+#include "GmicQt.h"
+#include "Globals.h"
+#include "HeadlessProcessor.h"
+#include "Host/GmicQtHost.h"
+#include "LanguageSettings.h"
+#include "Logger.h"
+#include "MainWindow.h"
+#include "Widgets/InOutPanel.h"
+#include "Widgets/ProgressInfoWindow.h"
+#include "Utils.h"
+#include "gmicqttoolplugin.h"
+
+#include "kpluginfactory.h"
+
+K_PLUGIN_FACTORY_WITH_JSON(KritaGmicPluginFactory,
+ "gmicqttoolplugin.json",
+ registerPlugin<KritaGmicPlugin>();)
+
+KritaGmicPlugin::KritaGmicPlugin(QObject *parent, const QVariantList &)
+ : QObject(parent)
+{
+#ifdef Q_OS_WIN
+ // Workaround for deploying basic CLUTs
+ // See https://krita-artists.org/t/unknown-filename-gmic-qt/37813
+ {
+ const auto srcPath = QDir(QCoreApplication::applicationDirPath().append(QStringLiteral("/../share/gmic/"))).absolutePath();
+ const auto dstPath = GmicQt::gmicConfigPath(true);
+ const std::list<QString> files = {"/gmic_cluts.gmz", "/gmic_denoise_cnn.gmz"};
+
+ for (const auto file: files) {
+ const auto src = srcPath + file;
+ const auto dst = dstPath + file;
+ if (QFileInfo(src).exists() && !QFileInfo(dst).exists()) {
+ qWarning() << src << dst;
+ QFile::copy(src, dst);
+ }
+ }
+
+ if (!qEnvironmentVariableIsSet("GMIC_SYSTEM_PATH")) {
+ qputenv("GMIC_SYSTEM_PATH", QString(srcPath).replace(L'/', L'\\').toLocal8Bit());
+ }
+ }
+#endif
+}
+
+int KritaGmicPlugin::launch(std::shared_ptr<KisImageInterface> i, bool headless)
+{
+#ifdef Q_OS_ANDROID
+ /* Since on Android stdout and stderr redirect to null, un-redirect them */
+ /* based on https://stackoverflow.com/a/gmic-qt/31777050 */
+
+ std::array<int, 2> oldFd;
+ std::array<int, 2> newStdout, newStderr;
+
+ auto redir_worker = [](std::array<int, 2> &fd, android_LogPriority lvl) {
+ ssize_t rdsz;
+ std::array<char, 1024> buf{};
+ while ((rdsz = read(fd[0], buf.data(), buf.size() - 1)) > 0) {
+ if (buf[rdsz - 1] == '\n')
+ --rdsz;
+ buf[rdsz] = 0; /* add null-terminator */
+ __android_log_write(
+ lvl, qPrintable(GmicQtHost::ApplicationName), buf.data());
+ }
+ };
+
+ /* make stdout line-buffered and stderr unbuffered */
+ setvbuf(stdout, 0, _IOLBF, 0);
+ setvbuf(stderr, 0, _IOLBF, 0);
+
+ /* create the pipe and redirect stdout and stderr */
+ dup2(1, oldFd[0]);
+ dup2(2, oldFd[1]);
+ pipe(newStdout.data());
+ pipe(newStderr.data());
+ dup2(newStdout[1], 1);
+ dup2(newStderr[1], 2);
+
+ /* spawn the logging thread */
+ auto newStdoutRedir =
+ std::thread(redir_worker, std::ref(newStdout), ANDROID_LOG_DEBUG);
+ auto newStderrRedir =
+ std::thread(redir_worker, std::ref(newStderr), ANDROID_LOG_WARN);
+ newStdoutRedir.detach();
+ newStderrRedir.detach();
+#endif
+
+ using namespace GmicQt;
+
+ std::list<GmicQt::InputMode> disabledInputModes;
+ disabledInputModes.push_back(GmicQt::InputMode::NoInput);
+ // disabledInputModes.push_back(GmicQt::Active);
+ // disabledInputModes.push_back(GmicQt::All);
+ // disabledInputModes.push_back(GmicQt::ActiveAndBelow);
+ // disabledInputModes.push_back(GmicQt::ActiveAndAbove);
+ disabledInputModes.push_back(GmicQt::InputMode::AllVisible);
+ disabledInputModes.push_back(GmicQt::InputMode::AllInvisible);
+
+ std::list<GmicQt::OutputMode> disabledOutputModes;
+ // disabledOutputModes.push_back(GmicQt::OutputMode::InPlace);
+ disabledOutputModes.push_back(GmicQt::OutputMode::NewImage);
+ disabledOutputModes.push_back(GmicQt::OutputMode::NewLayers);
+ disabledOutputModes.push_back(GmicQt::OutputMode::NewActiveLayers);
+
+ int status = 0;
+ GmicQtHost::iface = i;
+ if (headless) {
+ GmicQt::RunParameters parameters = GmicQt::lastAppliedFilterRunParameters(
+ GmicQt::ReturnedRunParametersFlag::AfterFilterExecution);
+ {
+ for (const GmicQt::InputMode & mode : disabledInputModes) {
+ GmicQt::InOutPanel::disableInputMode(mode);
+ }
+ for (const GmicQt::OutputMode & mode : disabledOutputModes) {
+ GmicQt::InOutPanel::disableOutputMode(mode);
+ }
+ }
+ Settings::load(GmicQt::UserInterfaceMode::ProgressDialog);
+ Logger::setMode(Settings::outputMessageMode());
+ LanguageSettings::installTranslators();
+
+ HeadlessProcessor processor(nullptr);
+ if (!processor.setPluginParameters(parameters)) {
+ Logger::error(processor.error());
+ return 1;
+ }
+
+ QPointer<ProgressInfoWindow> progressWindow(new ProgressInfoWindow(&processor));
+ // We want a non modal dialog here.
+ progressWindow->setWindowFlags(Qt::Tool | Qt::Dialog);
+ progressWindow->setWindowModality(Qt::ApplicationModal);
+ // Make it destroy itself on close (signaling the event loop)
+ progressWindow->setAttribute(Qt::WA_DeleteOnClose);
+
+ processor.startProcessing();
+
+ QEventLoop loop;
+ connect(progressWindow, SIGNAL(destroyed()), &loop, SLOT(quit()));
+ status = loop.exec();
+ } else {
+ GmicQt::RunParameters parameters = GmicQt::lastAppliedFilterRunParameters(
+ GmicQt::ReturnedRunParametersFlag::AfterFilterExecution);
+ {
+ for (const GmicQt::InputMode & mode : disabledInputModes) {
+ GmicQt::InOutPanel::disableInputMode(mode);
+ }
+ for (const GmicQt::OutputMode & mode : disabledOutputModes) {
+ GmicQt::InOutPanel::disableOutputMode(mode);
+ }
+ }
+ Settings::load(GmicQt::UserInterfaceMode::Full);
+ Logger::setMode(Settings::outputMessageMode());
+ LanguageSettings::installTranslators();
+
+ QPointer<MainWindow> mainWindow(new MainWindow(qApp->activeWindow()));
+ mainWindow->setPluginParameters(parameters);
+#ifdef Q_OS_MACOS
+ mainWindow->setWindowFlags(Qt::Tool | Qt::Dialog);
+#else
+ mainWindow->setWindowFlags(Qt::Dialog);
+#endif
+ mainWindow->setWindowModality(Qt::ApplicationModal);
+ // Make it destroy itself on close (signaling the event loop)
+ mainWindow->setAttribute(Qt::WA_DeleteOnClose);
+
+ if (GMIC_SETTINGS_INLINE.value("Config/MainWindowMaximized", false).toBool()) {
+ mainWindow->showMaximized();
+ } else {
+ mainWindow->show();
+ }
+
+ // Wait than main widget is closed.
+ QEventLoop loop;
+ connect(mainWindow, SIGNAL(destroyed()), &loop, SLOT(quit()));
+ status = loop.exec();
+ }
+
+ GmicQtHost::sharedMemorySegments.clear();
+ GmicQtHost::iface.reset();
+
+#ifdef Q_OS_ANDROID
+ /* un-redirect stdout and stderr */
+ dup2(oldFd[0], 1);
+ dup2(oldFd[1], 2);
+#endif
+
+ return status;
+}
+
+#include "gmicqttoolplugin.moc"
diff --git a/gmic-qt/src/Host/KritaPlugin/gmicqttoolplugin.h b/gmic-qt/src/Host/KritaPlugin/gmicqttoolplugin.h
new file mode 100644
index 0000000..bea9056
--- /dev/null
+++ b/gmic-qt/src/Host/KritaPlugin/gmicqttoolplugin.h
@@ -0,0 +1,55 @@
+/*
+ * This file is part of G'MIC-Qt, a generic plug-in for raster graphics
+ * editors, offering hundreds of filters thanks to the underlying G'MIC
+ * image processing framework.
+ *
+ * Copyright (C) 2020-2021 L. E. Segovia <amy@amyspark.me>
+ *
+ * Description: Krita painting suite plugin for G'Mic-Qt.
+ *
+ * G'MIC-Qt 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * G'MIC-Qt 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GMICQT_TOOL_PLUGIN_H
+#define GMICQT_TOOL_PLUGIN_H
+
+#include <QObject>
+#include <QSharedMemory>
+#include <QVector>
+#include <QtPlugin>
+#include <memory>
+
+#include <kis_qmic_interface.h>
+#include <kis_qmic_plugin_interface.h>
+
+namespace GmicQtHost
+{
+extern QVector<KisQMicImageSP> sharedMemorySegments;
+extern std::shared_ptr<KisImageInterface> iface;
+} // namespace GmicQtHost
+
+class KritaGmicPlugin : public QObject, public KisQmicPluginInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(KisQmicPluginInterface)
+
+public:
+ KritaGmicPlugin(QObject *parent, const QVariantList &);
+
+ int launch(std::shared_ptr<KisImageInterface> iface,
+ bool headless = false) override;
+};
+
+#endif
diff --git a/gmic-qt/src/Host/KritaPlugin/gmicqttoolplugin.json b/gmic-qt/src/Host/KritaPlugin/gmicqttoolplugin.json
new file mode 100644
index 0000000..4639d5e
--- /dev/null
+++ b/gmic-qt/src/Host/KritaPlugin/gmicqttoolplugin.json
@@ -0,0 +1,9 @@
+{
+ "Id": "GMic-Qt Krita Plugin",
+ "Type": "Service",
+ "X-KDE-Library": "gmic_krita_qt",
+ "X-KDE-ServiceTypes": [
+ "Krita/GMic"
+ ],
+ "X-Krita-Version": "28"
+}
diff --git a/gmic-qt/src/Host/KritaPlugin/host.cpp b/gmic-qt/src/Host/KritaPlugin/host.cpp
new file mode 100644
index 0000000..fcfa12b
--- /dev/null
+++ b/gmic-qt/src/Host/KritaPlugin/host.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2017 Boudewijn Rempt <boud@valdyas.org>
+ * Copyright (C) 2020-2022 L. E. Segovia <amy@amyspark.me>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <QByteArray>
+#include <QDebug>
+#include <QDesktopWidget>
+#include <QFileDialog>
+#include <QFileInfo>
+#include <QSharedMemory>
+#include <QStandardPaths>
+#include <QStringLiteral>
+#include <QUuid>
+#include <QVector>
+#include <algorithm>
+#include <memory>
+
+#include "GmicQt.h"
+#include "Host/GmicQtHost.h"
+#ifndef gmic_core
+#include "CImg.h"
+#endif
+#include "gmic.h"
+#include "kis_qmic_interface.h"
+
+/*
+ * No messages are sent in the plugin version of GMic.
+ * Instead, a list of KisQMicImageSP (shared pointers to KisQMic instances)
+ * are sent. These have:
+ *
+ * layer name
+ * shared pointer to data
+ * width
+ * height
+ * a mutex to control access.
+ *
+ * For the sake of debuggability, the overall control flow has been maintained.
+ */
+
+namespace GmicQtHost
+{
+const QString ApplicationName = QStringLiteral("Krita");
+const char *const ApplicationShortname = GMIC_QT_XSTRINGIFY(GMIC_HOST);
+const bool DarkThemeIsDefault = false;
+
+QVector<KisQMicImageSP> sharedMemorySegments;
+std::shared_ptr<KisImageInterface> iface;
+
+void getLayersExtent(int *width, int *height, GmicQt::InputMode mode)
+{
+#if defined(KRITA_QMIC_INTERFACE_VERSION) && KRITA_QMIC_INTERFACE_VERSION >= 0x05010001
+ const auto size = iface->gmic_qt_get_image_size(static_cast<int>(mode));
+#else
+ const auto size = iface->gmic_qt_get_image_size();
+#endif
+ *width = size.width();
+ *height = size.height();
+
+ // qDebug() << "gmic-qt: layers extent:" << *width << *height;
+}
+
+void getCroppedImages(gmic_list<float> &images,
+ gmic_list<char> &imageNames,
+ double x,
+ double y,
+ double width,
+ double height,
+ GmicQt::InputMode mode)
+{
+ // qDebug() << "gmic-qt: get_cropped_images:" << x << y << width << height;
+
+ const bool entireImage = x < 0 && y < 0 && width < 0 && height < 0;
+ if (entireImage) {
+ x = 0.0;
+ y = 0.0;
+ width = 1.0;
+ height = 1.0;
+ }
+
+ // Create a message for Krita
+ QRectF cropRect = {x, y, width, height};
+ auto imagesList =
+ iface->gmic_qt_get_cropped_images(static_cast<int>(mode), cropRect);
+
+ if (imagesList.isEmpty()) {
+ qWarning() << "\tgmic-qt: empty answer!";
+ return;
+ }
+
+ // qDebug() << "\tgmic-qt: " << answer;
+
+ images.assign(imagesList.size());
+ imageNames.assign(imagesList.size());
+
+ // qDebug() << "\tgmic-qt: imagelist size" << imagesList.size();
+
+ // Get the layers as prepared by Krita in G'Mic format
+ for (int i = 0; i < imagesList.length(); ++i) {
+ const auto &layer = imagesList[i];
+ const auto ba = layer->m_layerName.toUtf8();
+ gmic_image<char>::string(ba.data()).move_to(imageNames[i]);
+
+ // Fill images from the shared memory areas
+
+ {
+ QMutexLocker lock(&layer->m_mutex);
+
+ // qDebug() << "Memory segment" << (quintptr)image.data() << image->size()
+ // << (quintptr)&image->m_data << (quintptr)image->m_data.get();
+
+ // convert the data to the list of float
+ gmic_image<float> gimg;
+ gimg.assign(layer->m_width, layer->m_height, 1, 4);
+ const size_t length =
+ layer->m_width * layer->m_height * 4U * sizeof(float);
+ std::memcpy(gimg._data, layer->constData(), length);
+ gimg.move_to(images[i]);
+ }
+ }
+
+ iface->gmic_qt_detach();
+
+ // qDebug() << "\tgmic-qt: Images size" << images.size() << ", names size" <<
+ // imageNames.size();
+}
+
+void outputImages(gmic_list<float> &images,
+ const gmic_list<char> &imageNames,
+ GmicQt::OutputMode mode)
+{
+ // qDebug() << "qmic-qt-output-images";
+
+ sharedMemorySegments.clear();
+
+ // qDebug() << "\tqmic-qt: shared memory" << sharedMemorySegments.count();
+
+ // Create qsharedmemory segments for each image
+ // Create a message for Krita based on mode, the keys of the qsharedmemory
+ // segments and the imageNames
+ QVector<KisQMicImageSP> layers;
+
+ for (uint i = 0; i < images.size(); ++i) {
+ // qDebug() << "\tgmic-qt: image number" << i;
+
+ gmic_image<float> gimg = images.at(i);
+
+ const auto layerName = QString::fromUtf8(imageNames[i].data());
+
+ KisQMicImageSP m = KisQMicImageSP::create(
+ layerName, gimg._width, gimg._height, gimg._spectrum);
+ sharedMemorySegments << m;
+
+ {
+ QMutexLocker lock(&m->m_mutex);
+
+ const auto slice = gimg.get_slice(0);
+
+ const auto length = slice._width * slice._height * slice._spectrum * sizeof(float);
+ std::memcpy(m->m_data, slice._data, length);
+ }
+
+ layers << m;
+ }
+
+ iface->gmic_qt_output_images(static_cast<int>(mode), layers);
+}
+
+void showMessage(const char *)
+{
+ // May be left empty for Krita.
+ // Only used by launchPluginHeadless(), called in the non-interactive
+ // script mode of GIMP.
+}
+
+void applyColorProfile(cimg_library::CImg<gmic_pixel_type> &)
+{
+}
+
+} // namespace GmicQtHost
diff --git a/gmic-qt/src/Host/None/JpegQualityDialog.cpp b/gmic-qt/src/Host/None/JpegQualityDialog.cpp
index 69635c6..00a7f95 100644
--- a/gmic-qt/src/Host/None/JpegQualityDialog.cpp
+++ b/gmic-qt/src/Host/None/JpegQualityDialog.cpp
@@ -2,6 +2,8 @@
#include <QSettings>
#include "Settings.h"
#include "ui_jpegqualitydialog.h"
+#include "Globals.h"
+
int JpegQualityDialog::_permanentQuality = -1;
int JpegQualityDialog::_selectedQuality = -1;
@@ -15,7 +17,7 @@ JpegQualityDialog::JpegQualityDialog(QWidget * parent) : QDialog(parent), ui(new
ui->spinBox->setRange(0, 100);
if (_selectedQuality == -1) {
- _selectedQuality = QSettings().value(JPEG_QUALITY_KEY, 85).toInt();
+ _selectedQuality = GMIC_SETTINGS_INLINE.value(JPEG_QUALITY_KEY, 85).toInt();
}
ui->slider->setValue(_selectedQuality);
@@ -25,7 +27,7 @@ JpegQualityDialog::JpegQualityDialog(QWidget * parent) : QDialog(parent), ui(new
connect(ui->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), ui->slider, &QSlider::setValue);
connect(ui->pbOk, &QPushButton::clicked, [this]() {
_selectedQuality = ui->spinBox->value();
- QSettings().setValue(JPEG_QUALITY_KEY, _selectedQuality);
+ GMIC_SETTINGS_INLINE.setValue(JPEG_QUALITY_KEY, _selectedQuality);
});
connect(ui->pbOk, &QPushButton::clicked, this, &QDialog::accept);
connect(ui->pbCancel, &QPushButton::clicked, this, &QDialog::reject);
diff --git a/gmic-qt/src/LanguageSettings.cpp b/gmic-qt/src/LanguageSettings.cpp
index 7e74667..0c92a47 100644
--- a/gmic-qt/src/LanguageSettings.cpp
+++ b/gmic-qt/src/LanguageSettings.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "Globals.h"
#include "LanguageSettings.h"
#include <QApplication>
#include <QDebug>
@@ -66,7 +67,11 @@ const QMap<QString, QString> & LanguageSettings::availableLanguages()
QString LanguageSettings::configuredTranslator()
{
- QString code = QSettings().value(LANGUAGE_CODE_KEY, QString()).toString();
+#ifndef _GMIC_QT_DISABLE_TRANSLATION_
+ QString code = GMIC_SETTINGS_INLINE.value(LANGUAGE_CODE_KEY, QString()).toString();
+#else
+ QString code;
+#endif
if (code.isEmpty()) {
code = systemDefaultAndAvailableLanguageCode();
if (code.isEmpty()) {
@@ -105,7 +110,7 @@ void LanguageSettings::installTranslators()
if (!lang.isEmpty() && (lang != "en")) {
installQtTranslator(lang);
installTranslator(QString(":/translations/%1.qm").arg(lang));
- if (QSettings().value(ENABLE_FILTER_TRANSLATION, false).toBool()) {
+ if (GMIC_SETTINGS_INLINE.value(ENABLE_FILTER_TRANSLATION, false).toBool()) {
installTranslator(QString(":/translations/filters/%1.qm").arg(lang));
}
}
diff --git a/gmic-qt/src/MainWindow.cpp b/gmic-qt/src/MainWindow.cpp
index d48e095..008d955 100644
--- a/gmic-qt/src/MainWindow.cpp
+++ b/gmic-qt/src/MainWindow.cpp
@@ -187,8 +187,12 @@ MainWindow::MainWindow(QWidget * parent) : QMainWindow(parent), ui(new Ui::MainW
updateShortcutF5->setContext(Qt::ApplicationShortcut);
QShortcut * updateShortcutCtrlR = new QShortcut(QKeySequence("Ctrl+R"), this);
updateShortcutCtrlR->setContext(Qt::ApplicationShortcut);
+#ifdef _GMIC_QT_DISABLE_UPDATES_
+ ui->tbUpdateFilters->setEnabled(false);
+#else
connect(updateShortcutF5, &QShortcut::activated, [this]() { ui->tbUpdateFilters->animateClick(); });
connect(updateShortcutCtrlR, &QShortcut::activated, [this]() { ui->tbUpdateFilters->animateClick(); });
+#endif
ui->tbUpdateFilters->setToolTip(updateText);
}
@@ -275,6 +279,7 @@ void MainWindow::setIcons()
ui->tbExpandCollapse->setIcon(_expandIcon);
}
+#ifndef _GMIC_QT_DISABLE_THEMING_
void MainWindow::setDarkTheme()
{
// SHOW(QStyleFactory::keys());
@@ -328,6 +333,7 @@ void MainWindow::setDarkTheme()
ui->vSplitterLine->setStyleSheet("QFrame{ border-top: 0px none #a0a0a0; border-bottom: 1px solid rgb(160,160,160);}");
Settings::UnselectedFilterTextColor = Settings::UnselectedFilterTextColor.darker(150);
}
+#endif
void MainWindow::setPluginParameters(const RunParameters & parameters)
{
@@ -363,7 +369,9 @@ void MainWindow::onUpdateDownloadsFinished(int status)
showMessage(tr("No download was needed."), 3000);
}
+#ifndef _GMIC_QT_DISABLE_UPDATES_
ui->tbUpdateFilters->setEnabled(true);
+#endif
if (_filtersPresenter->currentFilter().hash.isEmpty()) {
setNoFilter();
} else {
@@ -385,7 +393,7 @@ void MainWindow::buildFiltersTree()
_filtersPresenter->importGmicGTKFaves();
_filtersPresenter->saveFaves();
_gtkFavesShouldBeImported = false;
- QSettings().setValue(FAVES_IMPORT_KEY, true);
+ GMIC_SETTINGS_INLINE.setValue(FAVES_IMPORT_KEY, true);
}
_filtersPresenter->toggleSelectionMode(withVisibility);
}
@@ -493,7 +501,7 @@ void MainWindow::onStartupFiltersUpdateFinished(int status)
} else if (status == (int)Updater::UpdateStatus::NotNecessary) {
}
- if (QSettings().value(FAVES_IMPORT_KEY, false).toBool() || !FavesModelReader::gmicGTKFaveFileAvailable()) {
+ if (GMIC_SETTINGS_INLINE.value(FAVES_IMPORT_KEY, false).toBool() || !FavesModelReader::gmicGTKFaveFileAvailable()) {
_gtkFavesShouldBeImported = false;
} else {
_gtkFavesShouldBeImported = askUserForGTKFavesImport();
@@ -511,7 +519,7 @@ void MainWindow::onStartupFiltersUpdateFinished(int status)
}
// Retrieve and select previously selected filter
- QString hash = QSettings().value("SelectedFilter", QString()).toString();
+ QString hash = GMIC_SETTINGS_INLINE.value("SelectedFilter", QString()).toString();
if (_newSession || !_lastExecutionOK) {
hash.clear();
}
@@ -576,7 +584,9 @@ void MainWindow::onEscapeKeyPressed()
} else {
_processor.cancel();
ui->previewWidget->displayOriginalImage();
+#ifndef _GMIC_QT_DISABLE_UPDATES_
ui->tbUpdateFilters->setEnabled(true);
+#endif
}
}
}
@@ -696,7 +706,9 @@ void MainWindow::onPreviewUpdateRequested(bool synchronous, bool randomized)
ui->previewWidget->invalidateSavedPreview();
return;
}
+#ifndef _GMIC_QT_DISABLE_UPDATES_
ui->tbUpdateFilters->setEnabled(false);
+#endif
_processor.init();
GmicProcessor::FilterContext context;
if (!ui->cbPreview->isChecked()) {
@@ -764,7 +776,9 @@ void MainWindow::onPreviewImageAvailable()
}
ui->previewWidget->setPreviewImage(_processor.previewImage());
ui->previewWidget->enableRightClick();
+#ifndef _GMIC_QT_DISABLE_UPDATES_
ui->tbUpdateFilters->setEnabled(true);
+#endif
}
void MainWindow::onGUIDynamismRunDone()
@@ -779,9 +793,19 @@ void MainWindow::onGUIDynamismRunDone()
void MainWindow::onPreviewError(const QString & message)
{
+ // if Krita is too busy generating the images, restart the
+ // the preview process
+ if (_processor.isInputImagesEmpty()) {
+ CroppedImageListProxy::clear();
+ QTimer::singleShot(1000, ui->previewWidget, SLOT(sendUpdateRequest()));
+ return;
+ }
+
ui->previewWidget->setPreviewErrorMessage(message);
ui->previewWidget->enableRightClick();
+#ifndef _GMIC_QT_DISABLE_UPDATES_
ui->tbUpdateFilters->setEnabled(true);
+#endif
}
void MainWindow::onParametersChanged()
@@ -864,12 +888,16 @@ void MainWindow::onVeryFirstShowEvent()
Updater::setOutputMessageMode(Settings::outputMessageMode());
int ageLimit;
{
- QSettings settings;
+ GMIC_SETTINGS(settings);
ageLimit = settings.value(INTERNET_UPDATE_PERIODICITY_KEY, INTERNET_DEFAULT_PERIODICITY).toInt();
}
+#ifndef _GMIC_QT_DISABLE_UPDATES_
const bool useNetwork = (ageLimit != INTERNET_NEVER_UPDATE_PERIODICITY);
+#else
+ const bool useNetwork = false;
+#endif
ui->progressInfoWidget->startFiltersUpdateAnimationAndShow();
- Updater::getInstance()->startUpdate(ageLimit, 4, useNetwork);
+ Updater::getInstance()->startUpdate(ageLimit, 60, useNetwork);
}
void MainWindow::setZoomConstraint()
@@ -1019,7 +1047,7 @@ void MainWindow::saveCurrentParameters()
void MainWindow::saveSettings()
{
- QSettings settings;
+ GMIC_SETTINGS(settings);
_filtersPresenter->saveSettings(settings);
@@ -1061,7 +1089,7 @@ void MainWindow::saveSettings()
void MainWindow::loadSettings()
{
- QSettings settings;
+ GMIC_SETTINGS(settings);
_filtersPresenter->loadSettings(settings);
_lastExecutionOK = settings.value("LastExecution/ExitedNormally", true).toBool();
_newSession = host_app_pid() != settings.value("LastExecution/HostApplicationID", 0).toUInt();
@@ -1076,9 +1104,11 @@ void MainWindow::loadSettings()
if (settings.value("Config/PreviewPosition", "Left").toString() == "Left") {
setPreviewPosition(PreviewPosition::Left);
}
+#ifndef _GMIC_QT_DISABLE_THEMING_
if (Settings::darkThemeEnabled()) {
setDarkTheme();
}
+#endif
if (!Settings::visibleLogos()) {
ui->logosLabel->hide();
}
@@ -1122,7 +1152,7 @@ void MainWindow::loadSettings()
ui->splitter->setSizes(sizes);
}
- ui->cbInternetUpdate->setChecked(settings.value("Config/RefreshInternetUpdate", true).toBool());
+ ui->cbInternetUpdate->setChecked(settings.value(REFRESH_USING_INTERNET_KEY, INTERNET_DEFAULT_REFRESH_UPDATE).toBool());
}
void MainWindow::setPreviewPosition(MainWindow::PreviewPosition position)
@@ -1184,7 +1214,7 @@ void MainWindow::setPreviewPosition(MainWindow::PreviewPosition position)
void MainWindow::adjustVerticalSplitter()
{
QList<int> sizes;
- QSettings settings;
+ GMIC_SETTINGS(settings);
sizes.push_back(settings.value(QString("Config/ParamsVerticalSplitterSizeTop"), -1).toInt());
sizes.push_back(settings.value(QString("Config/ParamsVerticalSplitterSizeBottom"), -1).toInt());
const int splitterHeight = ui->verticalSplitter->height();
@@ -1315,17 +1345,19 @@ bool MainWindow::askUserForGTKFavesImport()
QMessageBox::Yes | QMessageBox::No, this);
messageBox.setDefaultButton(QMessageBox::Yes);
QCheckBox * cb = new QCheckBox(tr("Don't ask again"));
+#ifndef _GMIC_QT_DISABLE_THEMING_
if (Settings::darkThemeEnabled()) {
QPalette p = cb->palette();
p.setColor(QPalette::Text, Settings::CheckBoxTextColor);
p.setColor(QPalette::Base, Settings::CheckBoxBaseColor);
cb->setPalette(p);
}
+#endif
messageBox.setCheckBox(cb);
int choice = messageBox.exec();
if (choice != QMessageBox::Yes) {
if (cb->isChecked()) {
- QSettings().setValue(FAVES_IMPORT_KEY, true);
+ GMIC_SETTINGS_INLINE.setValue(FAVES_IMPORT_KEY, true);
}
return false;
}
diff --git a/gmic-qt/src/MainWindow.h b/gmic-qt/src/MainWindow.h
index e7ed69d..ea16e23 100644
--- a/gmic-qt/src/MainWindow.h
+++ b/gmic-qt/src/MainWindow.h
@@ -70,7 +70,9 @@ public:
explicit MainWindow(QWidget * parent = nullptr);
~MainWindow() override;
void updateFiltersFromSources(int ageLimit, bool useNetwork);
+#ifndef _GMIC_QT_DISABLE_THEMING_
void setDarkTheme();
+#endif
void setPluginParameters(const RunParameters & parameters);
public slots:
diff --git a/gmic-qt/src/Settings.cpp b/gmic-qt/src/Settings.cpp
index 4764218..6e91e78 100644
--- a/gmic-qt/src/Settings.cpp
+++ b/gmic-qt/src/Settings.cpp
@@ -77,7 +77,7 @@ QString Settings::NegativeSign('-');
void Settings::load(UserInterfaceMode userInterfaceMode)
{
- QSettings settings;
+ GMIC_SETTINGS(settings);
_visibleLogos = settings.value("LogosAreVisible", true).toBool();
_darkThemeEnabled = settings.value(DARK_THEME_KEY, GmicQtHost::DarkThemeIsDefault).toBool();
_languageCode = settings.value(LANGUAGE_CODE_KEY, QString()).toString();
@@ -131,7 +131,11 @@ void Settings::setVisibleLogos(bool on)
bool Settings::darkThemeEnabled()
{
- return _darkThemeEnabled;
+#ifdef _GMIC_QT_DISABLE_THEMING_
+ return GmicQtHost::DarkThemeIsDefault;
+#else
+ return _darkThemeEnabled;
+#endif
}
void Settings::setDarkThemeEnabled(bool on)
@@ -273,8 +277,10 @@ void Settings::save(QSettings & settings)
{
removeObsoleteKeys(settings);
settings.setValue("LogosAreVisible", _visibleLogos);
+#ifndef _GMIC_QT_DISABLE_TRANSLATION_
settings.setValue(LANGUAGE_CODE_KEY, _languageCode);
settings.setValue(ENABLE_FILTER_TRANSLATION, _filterTranslationEnabled);
+#endif
settings.setValue("Config/PreviewPosition", (_previewPosition == MainWindow::PreviewPosition::Left) ? "Left" : "Right");
settings.setValue("Config/NativeColorDialogs", _nativeColorDialogs);
diff --git a/gmic-qt/src/Tags.cpp b/gmic-qt/src/Tags.cpp
index fae4d99..d3140e0 100644
--- a/gmic-qt/src/Tags.cpp
+++ b/gmic-qt/src/Tags.cpp
@@ -26,6 +26,7 @@
#include <QAction>
#include <QBuffer>
#include <QByteArray>
+#include <QCoreApplication>
#include <QDebug>
#include <QIcon>
#include <QImage>
@@ -148,7 +149,10 @@ QAction * TagAssets::action(QObject * parent, TagColor color, IconMark mark)
if ((color == TagColor::None) || (color == TagColor::Count)) {
return nullptr;
}
- return new QAction(menuIcon(color, mark), QObject::tr("%1 Tag").arg(colorName(color)), parent);
+ QAction *action = new QAction(menuIcon(color, mark), QObject::tr("%1 Tag").arg(colorName(color)), parent);
+ if (qApp->testAttribute(Qt::AA_DontShowIconsInMenus))
+ action->setIconVisibleInMenu(true);
+ return action;
}
QString TagAssets::colorName(TagColor color)
diff --git a/gmic-qt/src/Widgets/InOutPanel.cpp b/gmic-qt/src/Widgets/InOutPanel.cpp
index 2a30f99..535ba84 100644
--- a/gmic-qt/src/Widgets/InOutPanel.cpp
+++ b/gmic-qt/src/Widgets/InOutPanel.cpp
@@ -157,10 +157,12 @@ void InOutPanel::onResetButtonClicked()
setState(InputOutputState::Default, true);
}
+#ifndef _GMIC_QT_DISABLE_THEMING_
void InOutPanel::setDarkTheme()
{
ui->tbReset->setIcon(IconLoader::load("view-refresh"));
}
+#endif
void InOutPanel::setDefaultInputMode()
{
diff --git a/gmic-qt/src/Widgets/InOutPanel.h b/gmic-qt/src/Widgets/InOutPanel.h
index 381bc64..7939d3a 100644
--- a/gmic-qt/src/Widgets/InOutPanel.h
+++ b/gmic-qt/src/Widgets/InOutPanel.h
@@ -79,7 +79,9 @@ public slots:
void onInputModeSelected(int);
void onOutputModeSelected(int);
void onResetButtonClicked();
+#ifndef _GMIC_QT_DISABLE_THEMING_
void setDarkTheme();
+#endif
private:
static void setDefaultInputMode();
diff --git a/gmic-qt/src/Widgets/ProgressInfoWindow.cpp b/gmic-qt/src/Widgets/ProgressInfoWindow.cpp
index 533d257..604cf47 100644
--- a/gmic-qt/src/Widgets/ProgressInfoWindow.cpp
+++ b/gmic-qt/src/Widgets/ProgressInfoWindow.cpp
@@ -59,9 +59,11 @@ ProgressInfoWindow::ProgressInfoWindow(HeadlessProcessor * processor) : QMainWin
connect(processor, &HeadlessProcessor::done, this, &ProgressInfoWindow::onProcessingFinished);
_isShown = false;
+#ifndef _GMIC_QT_DISABLE_THEMING_
if (Settings::darkThemeEnabled()) {
setDarkTheme();
}
+#endif
}
ProgressInfoWindow::~ProgressInfoWindow()
@@ -85,6 +87,7 @@ void ProgressInfoWindow::closeEvent(QCloseEvent * event)
event->accept();
}
+#ifndef _GMIC_QT_DISABLE_THEMING_
void ProgressInfoWindow::setDarkTheme()
{
qApp->setStyle(QStyleFactory::create("Fusion"));
@@ -107,6 +110,7 @@ void ProgressInfoWindow::setDarkTheme()
p.setColor(QPalette::Disabled, QPalette::WindowText, QColor(110, 110, 110));
qApp->setPalette(p);
}
+#endif
void ProgressInfoWindow::onCancelClicked(bool)
{
diff --git a/gmic-qt/src/Widgets/ProgressInfoWindow.h b/gmic-qt/src/Widgets/ProgressInfoWindow.h
index 615dd16..9db9a1a 100644
--- a/gmic-qt/src/Widgets/ProgressInfoWindow.h
+++ b/gmic-qt/src/Widgets/ProgressInfoWindow.h
@@ -57,7 +57,9 @@ public:
protected:
void showEvent(QShowEvent *) override;
void closeEvent(QCloseEvent *) override;
+#ifndef _GMIC_QT_DISABLE_THEMING_
void setDarkTheme();
+#endif
public slots:
void onCancelClicked(bool);
diff --git a/gmic-qt/ui/dialogsettings.ui b/gmic-qt/ui/dialogsettings.ui
index 10b7ec8..f03ef4c 100644
--- a/gmic-qt/ui/dialogsettings.ui
+++ b/gmic-qt/ui/dialogsettings.ui
@@ -108,7 +108,7 @@
</widget>
</item>
<item row="0" column="1">
- <widget class="QGroupBox" name="groupBox_3">
+ <widget class="QGroupBox" name="groupBoxTheme">
<property name="title">
<string>Theme</string>
</property>
--
2.45.2