gmic/krita5.patch

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