diff --git a/gmic-qt/CMakeLists.txt b/gmic-qt/CMakeLists.txt index 8bba11e..6137f59 100644 --- a/gmic-qt/CMakeLists.txt +++ b/gmic-qt/CMakeLists.txt @@ -22,7 +22,7 @@ endif() message("Build type is " ${CMAKE_BUILD_TYPE}) -set (GMIC_QT_HOST "gimp" CACHE STRING "Define for which host qmic-qt will be built: gimp, gimp3 (experimental), krita, none, paintdotnet or 8bf.") +set (GMIC_QT_HOST "gimp" CACHE STRING "Define for which host qmic-qt will be built: gimp, gimp3 (experimental), krita, krita-plugin, none, paintdotnet or 8bf.") if (${GMIC_QT_HOST} STREQUAL "none") message("Building standalone version.") else() @@ -657,6 +657,71 @@ elseif (${GMIC_QT_HOST} STREQUAL "krita") ${gmic_qt_LIBRARIES} ) install(TARGETS gmic_krita_qt RUNTIME DESTINATION bin) + install(FILES gmic_krita_qt.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications) + +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") @@ -700,7 +765,7 @@ elseif (${GMIC_QT_HOST} STREQUAL "8bf") ) else() - message(FATAL_ERROR "GMIC_QT_HOST is not defined as gimp, gimp3, krita, none, paintdotnet or 8bf") + message(FATAL_ERROR "GMIC_QT_HOST is not defined as gimp, gimp3, krita, krita-plugin, none, paintdotnet or 8bf") endif() feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) 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 b3d8c53..e4050b4 100644 --- a/gmic-qt/src/DialogSettings.cpp +++ b/gmic-qt/src/DialogSettings.cpp @@ -93,11 +93,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 (_updatePeriodicity == ui->cbUpdatePeriodicity->itemData(i).toInt()) { - ui->cbUpdatePeriodicity->setCurrentIndex(i); - } - } + ui->cbUpdatePeriodicity->setCurrentIndex(ui->cbUpdatePeriodicity->findData(_updatePeriodicity)); ui->outputMessages->setToolTip(tr("Output messages")); ui->outputMessages->addItem(tr("Quiet (default)"), (int)OutputMessageMode::Quiet); @@ -118,9 +114,12 @@ DialogSettings::DialogSettings(QWidget * parent) : QDialog(parent), ui(new Ui::D ui->rbLeftPreview->setChecked(_previewPosition == MainWindow::PreviewPosition::Left); ui->rbRightPreview->setChecked(_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(_nativeColorDialogs); ui->cbNativeColorDialogs->setToolTip(tr("Check to use Native/OS color dialog, uncheck to use Qt's")); ui->cbShowLogos->setChecked(_logosAreVisible); @@ -130,9 +129,17 @@ DialogSettings::DialogSettings(QWidget * parent) : QDialog(parent), ui(new Ui::D connect(ui->pbOk, SIGNAL(clicked()), this, SLOT(onOk())); connect(ui->rbLeftPreview, SIGNAL(toggled(bool)), this, SLOT(onRadioLeftPreviewToggled(bool))); +#ifdef _GMIC_QT_DISABLE_UPDATES_ + ui->pbUpdate->setEnabled(false); +#else connect(ui->pbUpdate, SIGNAL(clicked(bool)), this, SLOT(onUpdateClicked())); +#endif +#ifdef _GMIC_QT_DISABLE_UPDATES_ + ui->cbUpdatePeriodicity->setEnabled(false); +#else connect(ui->cbUpdatePeriodicity, SIGNAL(currentIndexChanged(int)), this, SLOT(onUpdatePeriodicityChanged(int))); +#endif connect(ui->labelPreviewLeft, SIGNAL(clicked()), ui->rbLeftPreview, SLOT(click())); connect(ui->labelPreviewRight, SIGNAL(clicked()), ui->rbRightPreview, SLOT(click())); @@ -141,7 +148,9 @@ DialogSettings::DialogSettings(QWidget * parent) : QDialog(parent), ui(new Ui::D connect(Updater::getInstance(), SIGNAL(updateIsDone(int)), this, SLOT(enableUpdateButton())); +#ifndef _GMIC_QT_DISABLE_THEMING_ connect(ui->rbDarkTheme, SIGNAL(toggled(bool)), this, SLOT(onDarkThemeToggled(bool))); +#endif connect(ui->cbShowLogos, SIGNAL(toggled(bool)), this, SLOT(onLogosVisibleToggled(bool))); @@ -151,12 +160,21 @@ DialogSettings::DialogSettings(QWidget * parent) : QDialog(parent), ui(new Ui::D connect(ui->outputMessages, SIGNAL(currentIndexChanged(int)), this, SLOT(onOutputMessageModeChanged(int))); +#ifdef _GMIC_QT_DISABLE_UPDATES_ + ui->cbNotifyFailedUpdate->setEnabled(false); +#else connect(ui->cbNotifyFailedUpdate, SIGNAL(toggled(bool)), this, SLOT(onNotifyStartupUpdateFailedToggle(bool))); +#endif +#ifdef _GMIC_QT_DISABLE_TRANSLATION_ + ui->languageSelector->setEnabled(false); +#else ui->languageSelector->selectLanguage(_languageCode); ui->languageSelector->enableFilterTranslation(_filterTranslationEnabled); +#endif - if (_darkThemeEnabled) { +#ifndef _GMIC_QT_DISABLE_THEMING_ + if (DialogSettings::darkThemeEnabled()) { QPalette p = ui->cbNativeColorDialogs->palette(); p.setColor(QPalette::Text, DialogSettings::CheckBoxTextColor); p.setColor(QPalette::Base, DialogSettings::CheckBoxBaseColor); @@ -170,6 +188,7 @@ DialogSettings::DialogSettings(QWidget * parent) : QDialog(parent), ui(new Ui::D ui->cbShowLogos->setPalette(p); ui->cbNotifyFailedUpdate->setPalette(p); } +#endif ui->pbOk->setFocus(); ui->tabWidget->setCurrentIndex(0); } @@ -181,7 +200,7 @@ DialogSettings::~DialogSettings() void DialogSettings::loadSettings(UserInterfaceMode userInterfaceMode) { - QSettings settings; + GMIC_SETTINGS(settings); if (settings.value("Config/PreviewPosition", "Left").toString() == "Left") { _previewPosition = MainWindow::PreviewPosition::Left; } else { @@ -271,11 +290,13 @@ void DialogSettings::onOk() void DialogSettings::done(int r) { - QSettings settings; + GMIC_SETTINGS(settings); saveSettings(settings); settings.setValue(DARK_THEME_KEY, ui->rbDarkTheme->isChecked()); +#ifndef _GMIC_QT_DISABLE_TRANSLATION_ settings.setValue(LANGUAGE_CODE_KEY, ui->languageSelector->selectedLanguageCode()); settings.setValue(ENABLE_FILTER_TRANSLATION, ui->languageSelector->translateFiltersEnabled()); +#endif QDialog::done(r); } @@ -350,7 +371,11 @@ void DialogSettings::onColorDialogsToggled(bool on) bool DialogSettings::darkThemeEnabled() { +#ifdef _GMIC_QT_DISABLE_THEMING_ + return GmicQtHost::DarkThemeIsDefault; +#else return _darkThemeEnabled; +#endif } QString DialogSettings::languageCode() diff --git a/gmic-qt/src/FilterParameters/BoolParameter.cpp b/gmic-qt/src/FilterParameters/BoolParameter.cpp index 7f24464..3ba8313 100644 --- a/gmic-qt/src/FilterParameters/BoolParameter.cpp +++ b/gmic-qt/src/FilterParameters/BoolParameter.cpp @@ -59,12 +59,14 @@ bool BoolParameter::addTo(QWidget * widget, int row) delete _label; _checkBox = new QCheckBox(_name, widget); _checkBox->setChecked(_value); +#ifndef _GMIC_QT_DISABLE_THEMING_ if (DialogSettings::darkThemeEnabled()) { QPalette p = _checkBox->palette(); p.setColor(QPalette::Text, DialogSettings::CheckBoxTextColor); p.setColor(QPalette::Base, DialogSettings::CheckBoxBaseColor); _checkBox->setPalette(p); } +#endif _grid->addWidget(_checkBox, row, 0, 1, 3); connectCheckBox(); return true; diff --git a/gmic-qt/src/FilterParameters/FloatParameter.cpp b/gmic-qt/src/FilterParameters/FloatParameter.cpp index c47fc9c..67a0a3e 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(SLIDER_MAX_RANGE * (_value - _min) / (_max - _min))); +#ifndef _GMIC_QT_DISABLE_THEMING_ if (DialogSettings::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 0a32a65..b12058d 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 (DialogSettings::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); _grid->addWidget(_slider, row, 1, 1, 1); _grid->addWidget(_spinBox, row, 2, 1, 1); diff --git a/gmic-qt/src/FilterParameters/NoteParameter.cpp b/gmic-qt/src/FilterParameters/NoteParameter.cpp index 34d3424..bd1df33 100644 --- a/gmic-qt/src/FilterParameters/NoteParameter.cpp +++ b/gmic-qt/src/FilterParameters/NoteParameter.cpp @@ -87,14 +87,14 @@ bool NoteParameter::initFromText(const QString & filterName, const char * text, _text = list[1].trimmed(); // Notes are never translated _text.remove(QRegExp("^\"")).remove(QRegExp("\"$")).replace(QString("\\\""), "\""); _text.replace(QString("\\n"), "
"); - +#ifndef _GMIC_QT_DISABLE_THEMING_ if (DialogSettings::darkThemeEnabled()) { _text.replace(QRegExp("color\\s*=\\s*\"purple\""), QString("color=\"#ff00ff\"")); _text.replace(QRegExp("foreground\\s*=\\s*\"purple\""), QString("foreground=\"#ff00ff\"")); _text.replace(QRegExp("color\\s*=\\s*\"blue\""), QString("color=\"#9b9bff\"")); _text.replace(QRegExp("foreground\\s*=\\s*\"blue\""), QString("foreground=\"#9b9bff\"")); } - +#endif _text.replace(QRegExp("color\\s*=\\s*\""), QString("style=\"color:")); _text.replace(QRegExp("foreground\\s*=\\s*\""), QString("style=\"color:")); _text = HtmlTranslator::fromUtf8Escapes(_text); diff --git a/gmic-qt/src/FilterParameters/SeparatorParameter.cpp b/gmic-qt/src/FilterParameters/SeparatorParameter.cpp index 40347f7..941b280 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 (DialogSettings::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 e39270f..18e722e 100644 --- a/gmic-qt/src/FilterSelector/FiltersPresenter.cpp +++ b/gmic-qt/src/FilterSelector/FiltersPresenter.cpp @@ -416,7 +416,7 @@ void FiltersPresenter::expandFaveFolder() void FiltersPresenter::expandPreviousSessionExpandedFolders() { if (_filtersView) { - QList expandedFolderPaths = QSettings().value("Config/ExpandedFolders", QStringList()).toStringList(); + QList 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 9d38982..782a732 100644 --- a/gmic-qt/src/Globals.h +++ b/gmic-qt/src/Globals.h @@ -55,7 +55,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 @@ -64,4 +70,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/GmicQt.cpp b/gmic-qt/src/GmicQt.cpp index e836072..ddf2d40 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,10 +545,12 @@ 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); QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); +#endif } void disableModes(const std::list & disabledInputModes, // diff --git a/gmic-qt/src/HeadlessProcessor.cpp b/gmic-qt/src/HeadlessProcessor.cpp index 446d1a8..3fadf4a 100644 --- a/gmic-qt/src/HeadlessProcessor.cpp +++ b/gmic-qt/src/HeadlessProcessor.cpp @@ -27,6 +27,7 @@ #include #include #include +#include "Globals.h" #include "Common.h" #include "DialogSettings.h" #include "FilterParameters/FilterParametersWidget.h" @@ -71,7 +72,7 @@ HeadlessProcessor::~HeadlessProcessor() bool HeadlessProcessor::setPluginParameters(const RunParameters & parameters) { - QSettings settings; + GMIC_SETTINGS(settings); _path = QString::fromStdString(parameters.filterPath); _inputMode = (parameters.inputMode == InputMode::Unspecified) ? DefaultInputMode : parameters.inputMode; _outputMode = (parameters.outputMode == OutputMode::Unspecified) ? DefaultOutputMode : parameters.outputMode; @@ -238,7 +239,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(); @@ -271,7 +272,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..6ef6a4e --- /dev/null +++ b/gmic-qt/src/Host/KritaPlugin/gmicqttoolplugin.cpp @@ -0,0 +1,204 @@ +/* + * 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 + * + * 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 . + * + */ + +#include +#include +#include +#include +#include +#include + +#ifdef Q_OS_ANDROID +#include +#include +#include +#include +#include +#endif + +#include "DialogSettings.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 "gmicqttoolplugin.h" + +#include "kpluginfactory.h" + +K_PLUGIN_FACTORY_WITH_JSON(KritaGmicPluginFactory, + "gmicqttoolplugin.json", + registerPlugin();) + +KritaGmicPlugin::KritaGmicPlugin(QObject *parent, const QVariantList &) + : QObject(parent) +{ +} + +int KritaGmicPlugin::launch(std::shared_ptr 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 oldFd; + std::array newStdout, newStderr; + + auto redir_worker = [](std::array &fd, android_LogPriority lvl) { + ssize_t rdsz; + std::array 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 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 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); + } + } + DialogSettings::loadSettings(GmicQt::UserInterfaceMode::ProgressDialog); + Logger::setMode(DialogSettings::outputMessageMode()); + LanguageSettings::installTranslators(); + + HeadlessProcessor processor(nullptr); + if (!processor.setPluginParameters(parameters)) { + Logger::error(processor.error()); + return 1; + } + + QPointer 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); + } + } + DialogSettings::loadSettings(GmicQt::UserInterfaceMode::Full); + Logger::setMode(DialogSettings::outputMessageMode()); + LanguageSettings::installTranslators(); + + QPointer mainWindow(new MainWindow()); + mainWindow->setPluginParameters(parameters); + // We want a non modal dialog here. + mainWindow->setWindowFlags(Qt::Tool | Qt::Dialog); + 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 + * + * 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 . + * + */ + +#ifndef GMICQT_TOOL_PLUGIN_H +#define GMICQT_TOOL_PLUGIN_H + +#include +#include +#include +#include +#include + +#include +#include + +namespace GmicQtHost +{ +extern QVector sharedMemorySegments; +extern std::shared_ptr 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 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..1f244f6 --- /dev/null +++ b/gmic-qt/src/Host/KritaPlugin/host.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2017 Boudewijn Rempt + * Copyright (C) 2020-2021 L. E. Segovia + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GmicQt.h" +#include "Host/GmicQtHost.h" +#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 sharedMemorySegments; +std::shared_ptr iface; + +void getLayersExtent(int *width, int *height, GmicQt::InputMode mode) +{ + const auto size = iface->gmic_qt_get_image_size(); + *width = size.width(); + *height = size.height(); + + // qDebug() << "gmic-qt: layers extent:" << *width << *height; +} + +void getCroppedImages(gmic_list &images, + gmic_list &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(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]; + QByteArray ba = layer->m_layerName.toUtf8().toHex(); + gmic_image::string(ba.constData()).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 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 &images, + const gmic_list &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 layers; + + for (uint i = 0; i < images.size(); ++i) { + // qDebug() << "\tgmic-qt: image number" << i; + + gmic_image gimg = images.at(i); + + QString layerName((const char *)imageNames[i]); + + KisQMicImageSP m = KisQMicImageSP::create( + layerName, gimg._width, gimg._height, gimg._spectrum); + sharedMemorySegments << m; + + { + QMutexLocker lock(&m->m_mutex); + + const size_t length = + gimg._width * gimg._height * gimg._spectrum * sizeof(float); + std::memcpy(m->m_data, gimg._data, length); + } + + layers << m; + } + + iface->gmic_qt_output_images(static_cast(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 &) +{ +} + +} // namespace GmicQtHost diff --git a/gmic-qt/src/Host/None/JpegQualityDialog.cpp b/gmic-qt/src/Host/None/JpegQualityDialog.cpp index b351994..3ea120d 100644 --- a/gmic-qt/src/Host/None/JpegQualityDialog.cpp +++ b/gmic-qt/src/Host/None/JpegQualityDialog.cpp @@ -1,6 +1,7 @@ #include "JpegQualityDialog.h" #include #include "ui_jpegqualitydialog.h" +#include "Globals.h" int JpegQualityDialog::_permanentQuality = -1; int JpegQualityDialog::_selectedQuality = -1; @@ -14,7 +15,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); @@ -24,7 +25,7 @@ JpegQualityDialog::JpegQualityDialog(QWidget * parent) : QDialog(parent), ui(new connect(ui->spinBox, QOverload::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 e18f31f..8c6f8f2 100644 --- a/gmic-qt/src/LanguageSettings.cpp +++ b/gmic-qt/src/LanguageSettings.cpp @@ -23,6 +23,7 @@ * */ +#include "Globals.h" #include "LanguageSettings.h" #include #include @@ -66,7 +67,11 @@ const QMap & 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 33db6e4..9311901 100644 --- a/gmic-qt/src/MainWindow.cpp +++ b/gmic-qt/src/MainWindow.cpp @@ -184,8 +184,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); } @@ -273,6 +277,7 @@ void MainWindow::setIcons() ui->tbExpandCollapse->setIcon(_expandIcon); } +#ifndef _GMIC_QT_DISABLE_THEMING_ void MainWindow::setDarkTheme() { // SHOW(QStyleFactory::keys()); @@ -325,6 +330,7 @@ void MainWindow::setDarkTheme() ui->vSplitterLine->setStyleSheet("QFrame{ border-top: 0px none #a0a0a0; border-bottom: 1px solid rgb(160,160,160);}"); DialogSettings::UnselectedFilterTextColor = DialogSettings::UnselectedFilterTextColor.darker(150); } +#endif void MainWindow::setPluginParameters(const RunParameters & parameters) { @@ -379,7 +385,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); @@ -477,7 +483,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(); @@ -494,7 +500,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(); } @@ -559,7 +565,9 @@ void MainWindow::onEscapeKeyPressed() } else { _processor.cancel(); ui->previewWidget->displayOriginalImage(); +#ifndef _GMIC_QT_DISABLE_UPDATES_ ui->tbUpdateFilters->setEnabled(true); +#endif } } } @@ -671,7 +679,9 @@ void MainWindow::onPreviewUpdateRequested(bool synchronous) ui->previewWidget->displayOriginalImage(); return; } +#ifndef _GMIC_QT_DISABLE_UPDATES_ ui->tbUpdateFilters->setEnabled(false); +#endif const FiltersPresenter::Filter currentFilter = _filtersPresenter->currentFilter(); GmicProcessor::FilterContext context; @@ -733,7 +743,9 @@ void MainWindow::onPreviewImageAvailable() } ui->previewWidget->setPreviewImage(_processor.previewImage()); ui->previewWidget->enableRightClick(); +#ifndef _GMIC_QT_DISABLE_UPDATES_ ui->tbUpdateFilters->setEnabled(true); +#endif if (_pendingActionAfterCurrentProcessing == ProcessingAction::Close) { close(); } @@ -743,7 +755,9 @@ void MainWindow::onPreviewError(const QString & message) { ui->previewWidget->setPreviewErrorMessage(message); ui->previewWidget->enableRightClick(); +#ifndef _GMIC_QT_DISABLE_UPDATES_ ui->tbUpdateFilters->setEnabled(true); +#endif if (_pendingActionAfterCurrentProcessing == ProcessingAction::Close) { close(); } @@ -969,7 +983,7 @@ void MainWindow::saveCurrentParameters() void MainWindow::saveSettings() { - QSettings settings; + GMIC_SETTINGS(settings); _filtersPresenter->saveSettings(settings); @@ -1010,7 +1024,7 @@ void MainWindow::saveSettings() void MainWindow::loadSettings() { - QSettings settings; + GMIC_SETTINGS(settings); _filtersPresenter->loadSettings(settings); _lastExecutionOK = settings.value("LastExecution/ExitedNormally", true).toBool(); @@ -1026,9 +1040,11 @@ void MainWindow::loadSettings() if (settings.value("Config/PreviewPosition", "Left").toString() == "Left") { setPreviewPosition(PreviewPosition::Left); } +#ifndef _GMIC_QT_DISABLE_THEMING_ if (DialogSettings::darkThemeEnabled()) { setDarkTheme(); } +#endif if (!DialogSettings::logosAreVisible()) { ui->logosLabel->hide(); } @@ -1068,7 +1084,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) @@ -1130,7 +1146,7 @@ void MainWindow::setPreviewPosition(MainWindow::PreviewPosition position) void MainWindow::adjustVerticalSplitter() { QList 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(); @@ -1251,12 +1267,16 @@ void MainWindow::showEvent(QShowEvent * event) Updater::setOutputMessageMode(DialogSettings::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::resizeEvent(QResizeEvent * e) @@ -1273,17 +1293,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 (DialogSettings::darkThemeEnabled()) { QPalette p = cb->palette(); p.setColor(QPalette::Text, DialogSettings::CheckBoxTextColor); p.setColor(QPalette::Base, DialogSettings::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 a72f762..3819510 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/Tags.cpp b/gmic-qt/src/Tags.cpp index 4092ccc..d33e460 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 a388052..67bdcd1 100644 --- a/gmic-qt/src/Widgets/InOutPanel.cpp +++ b/gmic-qt/src/Widgets/InOutPanel.cpp @@ -158,10 +158,12 @@ void InOutPanel::onResetButtonClicked() setState(InputOutputState::Default, true); } +#ifndef _GMIC_QT_DISABLE_THEMING_ void InOutPanel::setDarkTheme() { ui->tbReset->setIcon(LOAD_ICON("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 5095528..cb8f35f 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 (DialogSettings::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 2fe13cd..d1c67ad 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 8345152..17d8bb8 100644 --- a/gmic-qt/ui/dialogsettings.ui +++ b/gmic-qt/ui/dialogsettings.ui @@ -108,7 +108,7 @@ - + Theme