Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
graphics
gmic
krita5.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File krita5.patch of Package gmic
Krita 5 plugin support Origin: https://github.com/amyspark/gmic Rebased for gmic 3.3.3 --- 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 | 5 +- 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, 715 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 8a09de7..90c5eed 100644 --- a/gmic-qt/src/FilterParameters/BoolParameter.cpp +++ b/gmic-qt/src/FilterParameters/BoolParameter.cpp @@ -63,12 +63,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 01a01c6..d9524e4 100644 --- a/gmic-qt/src/FilterParameters/FloatParameter.cpp +++ b/gmic-qt/src/FilterParameters/FloatParameter.cpp @@ -72,13 +72,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 0bdcba7..2a657c0 100644 --- a/gmic-qt/src/FilterParameters/IntParameter.cpp +++ b/gmic-qt/src/FilterParameters/IntParameter.cpp @@ -80,12 +80,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 1d54b97..fd46545 100644 --- a/gmic-qt/src/GmicProcessor.cpp +++ b/gmic-qt/src/GmicProcessor.cpp @@ -208,6 +208,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 89875ca..d1d58b8 100644 --- a/gmic-qt/src/GmicProcessor.h +++ b/gmic-qt/src/GmicProcessor.h @@ -93,6 +93,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 14ecacc..52642cc 100644 --- a/gmic-qt/src/MainWindow.cpp +++ b/gmic-qt/src/MainWindow.cpp @@ -188,8 +188,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 } } } @@ -695,7 +705,9 @@ void MainWindow::onPreviewUpdateRequested(bool synchronous) ui->previewWidget->invalidateSavedPreview(); return; } +#ifndef _GMIC_QT_DISABLE_UPDATES_ ui->tbUpdateFilters->setEnabled(false); +#endif _processor.init(); GmicProcessor::FilterContext context; if (!ui->cbPreview->isChecked()) { @@ -762,7 +774,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() @@ -777,9 +791,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() @@ -861,12 +885,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() @@ -1001,7 +1029,7 @@ void MainWindow::saveCurrentParameters() void MainWindow::saveSettings() { - QSettings settings; + GMIC_SETTINGS(settings); _filtersPresenter->saveSettings(settings); @@ -1043,7 +1071,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(); @@ -1058,9 +1086,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(); } @@ -1104,7 +1134,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) @@ -1166,7 +1196,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(); @@ -1294,17 +1324,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 4f436f9..bccd72c 100644 --- a/gmic-qt/src/MainWindow.h +++ b/gmic-qt/src/MainWindow.h @@ -71,7 +71,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 c50020c..08c1c89 100644 --- a/gmic-qt/src/Settings.cpp +++ b/gmic-qt/src/Settings.cpp @@ -75,7 +75,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(); @@ -129,7 +129,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) @@ -271,8 +275,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..6b721ce 100644 --- a/gmic-qt/src/Tags.cpp +++ b/gmic-qt/src/Tags.cpp @@ -148,7 +148,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.43.0
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor