1443 lines
53 KiB
Diff
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
|
|
|