diff --git a/kcms/style/CMakeLists.txt b/kcms/style/CMakeLists.txt index c57d50191..adf2e8028 100644 --- a/kcms/style/CMakeLists.txt +++ b/kcms/style/CMakeLists.txt @@ -1,35 +1,37 @@ # KI18N Translation Domain for this library add_definitions(-DTRANSLATION_DOMAIN=\"kcmstyle\") ########### next target ############### set(kcm_style_PART_SRCS ../krdb/krdb.cpp styleconfdialog.cpp kcmstyle.cpp stylesmodel.cpp previewitem.cpp) set(klauncher_xml ${KINIT_DBUS_INTERFACES_DIR}/kf5_org.kde.KLauncher.xml) qt5_add_dbus_interface(kcm_style_PART_SRCS ${klauncher_xml} klauncher_iface) - ki18n_wrap_ui(kcm_style_PART_SRCS stylepreview.ui) +kconfig_add_kcfg_files(kcm_style_PART_SRCS stylesettings.kcfgc GENERATE_MOC) + add_library(kcm_style MODULE ${kcm_style_PART_SRCS}) target_link_libraries(kcm_style Qt5::X11Extras Qt5::DBus KF5::KCMUtils KF5::Completion KF5::I18n KF5::Notifications KF5::Plasma ${X11_LIBRARIES} KF5::KDELibs4Support KF5::GuiAddons KF5::QuickAddons KF5::WindowSystem ) kcoreaddons_desktop_to_json(kcm_style "kcm_style.desktop") +install(FILES stylesettings.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR}) install(FILES kcm_style.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR}) install(TARGETS kcm_style DESTINATION ${KDE_INSTALL_PLUGINDIR}/kcms) kpackage_install_package(package kcm_style kcms) diff --git a/kcms/style/kcmstyle.cpp b/kcms/style/kcmstyle.cpp index 8b7295c88..ba11d6793 100644 --- a/kcms/style/kcmstyle.cpp +++ b/kcms/style/kcmstyle.cpp @@ -1,368 +1,328 @@ /* * KCMStyle * Copyright (C) 2002 Karol Szwed * Copyright (C) 2002 Daniel Molkentin * Copyright (C) 2007 Urs Wolfer * Copyright (C) 2009 by Davide Bettio * Copyright (C) 2019 Kai Uwe Broulik + * Copyright (C) 2019 Cyril Rossi * * Portions Copyright (C) 2007 Paolo Capriotti * Portions Copyright (C) 2007 Ivan Cukic * Portions Copyright (C) 2008 by Petri Damsten * Portions Copyright (C) 2000 TrollTech AS. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License version 2 as published by the Free Software Foundation. * * This program 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; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kcmstyle.h" #include "styleconfdialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../krdb/krdb.h" #include "stylesmodel.h" #include "previewitem.h" +#include "stylesettings.h" K_PLUGIN_FACTORY_WITH_JSON(KCMStyleFactory, "kcm_style.json", registerPlugin();) extern "C" { Q_DECL_EXPORT void kcminit_style() { uint flags = KRdbExportQtSettings | KRdbExportGtkColors | KRdbExportQtColors | KRdbExportXftSettings | KRdbExportGtkTheme; KConfig _config( QStringLiteral("kcmdisplayrc"), KConfig::NoGlobals ); KConfigGroup config(&_config, "X11"); // This key is written by the "colors" module. bool exportKDEColors = config.readEntry("exportKDEColors", true); if (exportKDEColors) flags |= KRdbExportColors; runRdb( flags ); } } -QString KCMStyle::defaultStyle() -{ - return QStringLiteral("Breeze"); -} - KCMStyle::KCMStyle(QObject *parent, const QVariantList &args) : KQuickAddons::ConfigModule(parent, args) + , m_settings(new StyleSettings(this)) , m_model(new StylesModel(this)) { qmlRegisterUncreatableType("org.kde.private.kcms.style", 1, 0, "KCM", QStringLiteral("Cannot create instances of KCM")); + qmlRegisterType(); qmlRegisterType(); qmlRegisterType("org.kde.private.kcms.style", 1, 0, "PreviewItem"); KAboutData *about = new KAboutData( QStringLiteral("kcm_style"), i18n("Application Style"), QStringLiteral("2.0"), QString(), KAboutLicense::GPL, i18n("(c) 2002 Karol Szwed, Daniel Molkentin, (c) 2019 Kai Uwe Broulik")); about->addAuthor(i18n("Karol Szwed"), QString(), QStringLiteral("gallium@kde.org")); about->addAuthor(i18n("Daniel Molkentin"), QString(), QStringLiteral("molkentin@kde.org")); about->addAuthor(i18n("Kai Uwe Broulik"), QString(), QStringLiteral("kde@broulik.de")); setAboutData(about); connect(m_model, &StylesModel::selectedStyleChanged, this, [this] { m_selectedStyleDirty = true; setNeedsSave(true); }); + connect(m_settings, &StyleSettings::iconsOnButtonsChanged, this, [this] { + m_effectsDirty = true; + setNeedsSave(true); + }); + connect(m_settings, &StyleSettings::iconsInMenusChanged, this, [this] { + m_effectsDirty = true; + setNeedsSave(true); + }); } KCMStyle::~KCMStyle() = default; StylesModel *KCMStyle::model() const { return m_model; } -bool KCMStyle::iconsOnButtons() const -{ - return m_iconsOnButtons; -} - -void KCMStyle::setIconsOnButtons(bool enable) -{ - if (m_iconsOnButtons != enable) { - m_iconsOnButtons = enable; - emit iconsOnButtonsChanged(); - - m_effectsDirty = true; - setNeedsSave(true); - } -} - -bool KCMStyle::iconsInMenus() const -{ - return m_iconsInMenus; -} - -void KCMStyle::setIconsInMenus(bool enable) +StyleSettings *KCMStyle::styleSettings() const { - if (m_iconsInMenus != enable) { - m_iconsInMenus = enable; - emit iconsInMenusChanged(); - - m_effectsDirty = true; - setNeedsSave(true); - } + return m_settings; } KCMStyle::ToolBarStyle KCMStyle::mainToolBarStyle() const { return m_mainToolBarStyle; } void KCMStyle::setMainToolBarStyle(ToolBarStyle style) { if (m_mainToolBarStyle != style) { m_mainToolBarStyle = style; emit mainToolBarStyleChanged(); m_effectsDirty = true; setNeedsSave(true); } } KCMStyle::ToolBarStyle KCMStyle::otherToolBarStyle() const { return m_otherToolBarStyle; } void KCMStyle::setOtherToolBarStyle(ToolBarStyle style) { if (m_otherToolBarStyle != style) { m_otherToolBarStyle = style; emit otherToolBarStyleChanged(); m_effectsDirty = true; setNeedsSave(true); } } void KCMStyle::configure(const QString &styleName, QQuickItem *ctx) { if (m_styleConfigDialog) { return; } const QString configPage = m_model->styleConfigPage(styleName); if (configPage.isEmpty()) { return; } QLibrary library(KPluginLoader::findPlugin(configPage)); if (!library.load()) { qWarning() << "Failed to load style config page" << configPage << library.errorString(); emit showErrorMessage(i18n("There was an error loading the configuration dialog for this style.")); return; } auto allocPtr = library.resolve("allocate_kstyle_config"); if (!allocPtr) { qWarning() << "Failed to resolve allocate_kstyle_config in" << configPage; emit showErrorMessage(i18n("There was an error loading the configuration dialog for this style.")); return; } m_styleConfigDialog = new StyleConfigDialog(nullptr/*this*/, configPage); m_styleConfigDialog->setAttribute(Qt::WA_DeleteOnClose); m_styleConfigDialog->setWindowModality(Qt::WindowModal); m_styleConfigDialog->winId(); // so it creates windowHandle if (ctx && ctx->window()) { if (QWindow *actualWindow = QQuickRenderControl::renderWindowFor(ctx->window())) { m_styleConfigDialog->windowHandle()->setTransientParent(actualWindow); } } typedef QWidget*(* factoryRoutine)( QWidget* parent ); //Get the factory, and make the widget. factoryRoutine factory = (factoryRoutine)(allocPtr); //Grmbl. So here I am on my //"never use C casts" moralizing streak, and I find that one can't go void* -> function ptr //even with a reinterpret_cast. QWidget* pluginConfig = factory( m_styleConfigDialog.data() ); //Insert it in... m_styleConfigDialog->setMainWidget( pluginConfig ); //..and connect it to the wrapper connect(pluginConfig, SIGNAL(changed(bool)), m_styleConfigDialog.data(), SLOT(setDirty(bool))); connect(m_styleConfigDialog.data(), SIGNAL(defaults()), pluginConfig, SLOT(defaults())); connect(m_styleConfigDialog.data(), SIGNAL(save()), pluginConfig, SLOT(save())); connect(m_styleConfigDialog.data(), &QDialog::accepted, this, [this, styleName] { if (!m_styleConfigDialog->isDirty()) { return; } // Force re-rendering of the preview, to apply settings emit styleReconfigured(styleName); //For now, ask all KDE apps to recreate their styles to apply the setitngs KGlobalSettings::self()->emitChange(KGlobalSettings::StyleChanged); // When user edited a style, assume they want to use it, too m_model->setSelectedStyle(styleName); // We call setStyleDirty here to make sure we force style re-creation m_selectedStyleDirty = true; setNeedsSave(true); }); m_styleConfigDialog->show(); } void KCMStyle::load() { m_model->load(); - KConfig config(QStringLiteral("kdeglobals")); - - // Current style - KConfigGroup kdeGroup = config.group("KDE"); - const QString widgetStyle = kdeGroup.readEntry("widgetStyle", KCMStyle::defaultStyle()); - - m_model->setSelectedStyle(widgetStyle); + m_settings->load(); - // Effects settings - setIconsOnButtons(kdeGroup.readEntry("ShowIconsOnPushButtons", true)); - setIconsInMenus(kdeGroup.readEntry("ShowIconsInMenuItems", true)); - - KConfigGroup toolBarGroup = config.group("Toolbar style"); - const QString mainToolBarStyle = toolBarGroup.readEntry("ToolButtonStyle", "TextBesideIcon"); - const QString otherToolBarStyle = toolBarGroup.readEntry("ToolButtonStyleOtherToolbars", "TextBesideIcon"); - - const QMetaEnum toolBarStyleEnum = QMetaEnum::fromType(); - setMainToolBarStyle(static_cast(toolBarStyleEnum.keyToValue(qUtf8Printable(mainToolBarStyle)))); - setOtherToolBarStyle(static_cast(toolBarStyleEnum.keyToValue(qUtf8Printable(otherToolBarStyle)))); + loadSettingsToModel(); m_selectedStyleDirty = false; m_effectsDirty = false; setNeedsSave(false); } void KCMStyle::save() { if (!m_selectedStyleDirty && !m_effectsDirty) { return; } // Check whether the new style can actually be loaded before saving it. // Otherwise apps will use the default style despite something else having been written to the config bool newStyleLoaded = false; if (m_selectedStyleDirty) { QScopedPointer newStyle(QStyleFactory::create(m_model->selectedStyle())); if (newStyle) { newStyleLoaded = true; } else { const QString styleDisplay = m_model->data(m_model->index(m_model->selectedStyleIndex(), 0), Qt::DisplayRole).toString(); emit showErrorMessage(i18n("Failed to apply selected style '%1'.", styleDisplay)); } } - KConfig config(QStringLiteral("kdeglobals")); - - KConfigGroup kdeGroup = config.group("KDE"); - if (newStyleLoaded) { - kdeGroup.writeEntry("widgetStyle", m_model->selectedStyle()); + m_settings->setWidgetStyle(m_model->selectedStyle()); } - kdeGroup.writeEntry("ShowIconsOnPushButtons", m_iconsOnButtons); - kdeGroup.writeEntry("ShowIconsInMenuItems", m_iconsInMenus); - - KConfigGroup toolBarGroup = config.group("Toolbar style"); const QMetaEnum toolBarStyleEnum = QMetaEnum::fromType(); + m_settings->setToolButtonStyle(toolBarStyleEnum.valueToKey(m_mainToolBarStyle)); + m_settings->setToolButtonStyleOtherToolbars(toolBarStyleEnum.valueToKey(m_otherToolBarStyle)); - toolBarGroup.writeEntry("ToolButtonStyle", toolBarStyleEnum.valueToKey(m_mainToolBarStyle)); - toolBarGroup.writeEntry("ToolButtonStyleOtherToolbars", toolBarStyleEnum.valueToKey(m_otherToolBarStyle)); - - config.sync(); + m_settings->save(); // Export the changes we made to qtrc, and update all qt-only // applications on the fly, ensuring that we still follow the user's // export fonts/colors settings. if (m_selectedStyleDirty || m_effectsDirty) { uint flags = KRdbExportQtSettings | KRdbExportGtkTheme; KConfig _kconfig( QStringLiteral("kcmdisplayrc"), KConfig::NoGlobals ); KConfigGroup kconfig(&_kconfig, "X11"); bool exportKDEColors = kconfig.readEntry("exportKDEColors", true); if (exportKDEColors) { flags |= KRdbExportColors; } runRdb( flags ); } // Now allow KDE apps to reconfigure themselves. if (newStyleLoaded) { KGlobalSettings::self()->emitChange(KGlobalSettings::StyleChanged); } if (m_effectsDirty) { KGlobalSettings::self()->emitChange(KGlobalSettings::SettingsChanged, KGlobalSettings::SETTINGS_STYLE); // ##### FIXME - Doesn't apply all settings correctly due to bugs in // KApplication/KToolbar KGlobalSettings::self()->emitChange(KGlobalSettings::ToolbarStyleChanged); } // Reset selected style back to current in case of failure if (!newStyleLoaded) { - const QString widgetStyle = kdeGroup.readEntry("widgetStyle", KCMStyle::defaultStyle()); - m_model->setSelectedStyle(widgetStyle); + m_model->setSelectedStyle(m_settings->widgetStyle()); } + m_selectedStyleDirty = false; m_effectsDirty = false; - setNeedsSave(false); } void KCMStyle::defaults() { // TODO the old code had a fallback chain but do we actually support not having Breeze for Plasma? // defaultStyle() -> oxygen -> plastique -> windows -> platinum -> motif - m_model->setSelectedStyle(defaultStyle()); + m_settings->setDefaults(); + + loadSettingsToModel(); - setIconsOnButtons(true); - setIconsInMenus(true); - setMainToolBarStyle(TextBesideIcon); - setOtherToolBarStyle(TextBesideIcon); + setNeedsSave(m_settings->isSaveNeeded()); } -#include "kcmstyle.moc" +void KCMStyle::loadSettingsToModel() +{ + m_model->setSelectedStyle(m_settings->widgetStyle()); -// vim: set noet ts=4: + const QMetaEnum toolBarStyleEnum = QMetaEnum::fromType(); + setMainToolBarStyle(static_cast(toolBarStyleEnum.keyToValue(qUtf8Printable(m_settings->toolButtonStyle())))); + setOtherToolBarStyle(static_cast(toolBarStyleEnum.keyToValue(qUtf8Printable(m_settings->toolButtonStyleOtherToolbars())))); +} + +#include "kcmstyle.moc" diff --git a/kcms/style/kcmstyle.h b/kcms/style/kcmstyle.h index 4d64e67c1..81ec00d55 100644 --- a/kcms/style/kcmstyle.h +++ b/kcms/style/kcmstyle.h @@ -1,111 +1,101 @@ /* * KCMStyle * Copyright (C) 2002 Karol Szwed * Copyright (C) 2002 Daniel Molkentin * Copyright (C) 2007 Urs Wolfer * Copyright (C) 2019 Kai Uwe Broulik + * Copyright (C) 2019 Cyril Rossi * * Portions Copyright (C) TrollTech AS. * * Based on kcmdisplay * Copyright (C) 1997-2002 kcmdisplay Authors. * (see Help -> About Style Settings) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License version 2 as published by the Free Software Foundation. * * This program 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; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KCMSTYLE_H #define KCMSTYLE_H #include #include class QQuickItem; +class StyleSettings; class StylesModel; class StyleConfigDialog; class KCMStyle : public KQuickAddons::ConfigModule { Q_OBJECT Q_PROPERTY(StylesModel *model READ model CONSTANT) - - Q_PROPERTY(bool iconsOnButtons READ iconsOnButtons WRITE setIconsOnButtons NOTIFY iconsOnButtonsChanged) - Q_PROPERTY(bool iconsInMenus READ iconsInMenus WRITE setIconsInMenus NOTIFY iconsInMenusChanged) + Q_PROPERTY(StyleSettings *styleSettings READ styleSettings CONSTANT) Q_PROPERTY(ToolBarStyle mainToolBarStyle READ mainToolBarStyle WRITE setMainToolBarStyle NOTIFY mainToolBarStyleChanged) Q_PROPERTY(ToolBarStyle otherToolBarStyle READ otherToolBarStyle WRITE setOtherToolBarStyle NOTIFY otherToolBarStyleChanged) public: KCMStyle(QObject *parent, const QVariantList &args); ~KCMStyle() override; enum ToolBarStyle { NoText, TextOnly, TextBesideIcon, TextUnderIcon }; Q_ENUM(ToolBarStyle) StylesModel *model() const; - bool iconsOnButtons() const; - void setIconsOnButtons(bool enable); - Q_SIGNAL void iconsOnButtonsChanged(); - - bool iconsInMenus() const; - void setIconsInMenus(bool enable); - Q_SIGNAL void iconsInMenusChanged(); + StyleSettings *styleSettings() const; ToolBarStyle mainToolBarStyle() const; void setMainToolBarStyle(ToolBarStyle style); Q_SIGNAL void mainToolBarStyleChanged(); ToolBarStyle otherToolBarStyle() const; void setOtherToolBarStyle(ToolBarStyle style); Q_SIGNAL void otherToolBarStyleChanged(); Q_INVOKABLE void configure(const QString &styleName, QQuickItem *ctx = nullptr); void load() override; void save() override; void defaults() override; - static QString defaultStyle(); - Q_SIGNALS: void showErrorMessage(const QString &message); - void styleReconfigured(const QString &styleName); private: + void loadSettingsToModel(); + + StyleSettings *m_settings; StylesModel *m_model; bool m_selectedStyleDirty = false; bool m_effectsDirty = false; - bool m_iconsOnButtons = false; - bool m_iconsInMenus = false; ToolBarStyle m_mainToolBarStyle = NoText; ToolBarStyle m_otherToolBarStyle = NoText; QPointer m_styleConfigDialog; }; #endif // __KCMSTYLE_H - -// vim: set noet ts=4: diff --git a/kcms/style/package/contents/ui/EffectSettingsPopup.qml b/kcms/style/package/contents/ui/EffectSettingsPopup.qml index c28abcd03..6b368a71b 100644 --- a/kcms/style/package/contents/ui/EffectSettingsPopup.qml +++ b/kcms/style/package/contents/ui/EffectSettingsPopup.qml @@ -1,81 +1,81 @@ /* * Copyright 2018 Kai Uwe Broulik * * This program 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 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program 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 . */ import QtQuick 2.7 import QtQuick.Layouts 1.1 import QtQuick.Controls 2.3 as QtControls import org.kde.kirigami 2.4 as Kirigami import org.kde.private.kcms.style 1.0 as Private QtControls.Popup { id: effectSettingsPopup modal: true onOpened: { // can we do this automatically with "focus: true" somewhere? iconsOnButtonsCheckBox.forceActiveFocus(); } Kirigami.FormLayout { // Popup's autosizing causes FormLayout to collapse when opening it a second time :( wideMode: true QtControls.CheckBox { id: iconsOnButtonsCheckBox Kirigami.FormData.label: i18n("Show icons:") text: i18n("On buttons") - checked: kcm.iconsOnButtons - onClicked: kcm.iconsOnButtons = checked + checked: kcm.styleSettings.iconsOnButtons + onClicked: kcm.styleSettings.iconsOnButtons = checked } QtControls.CheckBox { text: i18n("In menus") - checked: kcm.iconsInMenus - onClicked: kcm.iconsInMenus = checked + checked: kcm.styleSettings.iconsInMenus + onClicked: kcm.styleSettings.iconsInMenus = checked } QtControls.ComboBox { id: mainToolBarStyleCombo Kirigami.FormData.label: i18n("Main toolbar label:") model: [ {text: i18n("None"), value: Private.KCM.NoText}, {text: i18n("Text only"), value: Private.KCM.TextOnly}, {text: i18n("Beside icons"), value: Private.KCM.TextBesideIcon}, {text: i18n("Below icon"), value: Private.KCM.TextUnderIcon} ] textRole: "text" currentIndex: model.findIndex(function (item) { return item.value === kcm.mainToolBarStyle }) onActivated: kcm.mainToolBarStyle = model[currentIndex].value } QtControls.ComboBox { Kirigami.FormData.label: i18n("Secondary toolbar label:") model: mainToolBarStyleCombo.model textRole: "text" currentIndex: model.findIndex(function (item) { return item.value === kcm.otherToolBarStyle }) onActivated: kcm.otherToolBarStyle = model[currentIndex].value } } } diff --git a/kcms/style/stylesettings.kcfg b/kcms/style/stylesettings.kcfg new file mode 100644 index 000000000..28df610f6 --- /dev/null +++ b/kcms/style/stylesettings.kcfg @@ -0,0 +1,31 @@ + + + + + + + Breeze + + + + true + + + + true + + + + + + TextBesideIcon + + + + TextBesideIcon + + + diff --git a/kcms/style/stylesettings.kcfgc b/kcms/style/stylesettings.kcfgc new file mode 100644 index 000000000..174607f56 --- /dev/null +++ b/kcms/style/stylesettings.kcfgc @@ -0,0 +1,6 @@ +File=stylesettings.kcfg +ClassName=StyleSettings +Mutators=true +DefaultValueGetters=true +GenerateProperties=true +ParentInConstructor=true