diff --git a/kcms/colors/colors.cpp b/kcms/colors/colors.cpp index 88e53c51a..d93772aea 100644 --- a/kcms/colors/colors.cpp +++ b/kcms/colors/colors.cpp @@ -1,692 +1,480 @@ /* * Copyright (C) 2007 Matthew Woehlke * Copyright (C) 2007 Jeremy Whiting * Copyright (C) 2016 Olivier Churlaud * Copyright (C) 2019 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 . */ #include "colors.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../krdb/krdb.h" #include "colorsmodel.h" #include "filterproxymodel.h" static const QString s_defaultColorSchemeName = QStringLiteral("Breeze"); K_PLUGIN_FACTORY_WITH_JSON(KCMColorsFactory, "kcm_colors.json", registerPlugin();) KCMColors::KCMColors(QObject *parent, const QVariantList &args) : KQuickAddons::ConfigModule(parent, args) , m_model(new ColorsModel(this)) , m_filteredModel(new FilterProxyModel(this)) , m_config(KSharedConfig::openConfig(QStringLiteral("kdeglobals"))) { qmlRegisterUncreatableType("org.kde.private.kcms.colors", 1, 0, "KCM", QStringLiteral("Cannot create instances of KCM")); qmlRegisterType(); qmlRegisterType(); KAboutData *about = new KAboutData(QStringLiteral("kcm_colors"), i18n("Colors"), QStringLiteral("2.0"), QString(), KAboutLicense::GPL); about->addAuthor(i18n("Kai Uwe Broulik"), QString(), QStringLiteral("kde@privat.broulik.de")); setAboutData(about); connect(m_model, &ColorsModel::selectedSchemeChanged, this, [this] { m_selectedSchemeDirty = true; setNeedsSave(true); }); connect(m_model, &ColorsModel::pendingDeletionsChanged, this, [this] { setNeedsSave(true); }); connect(m_model, &ColorsModel::selectedSchemeChanged, m_filteredModel, &FilterProxyModel::setSelectedScheme); m_filteredModel->setSourceModel(m_model); } KCMColors::~KCMColors() { m_config->markAsClean(); } ColorsModel *KCMColors::model() const { return m_model; } FilterProxyModel *KCMColors::filteredModel() const { return m_filteredModel; } bool KCMColors::downloadingFile() const { return m_tempCopyJob; } void KCMColors::getNewStuff(QQuickItem *ctx) { if (!m_newStuffDialog) { m_newStuffDialog = new KNS3::DownloadDialog(QStringLiteral("colorschemes.knsrc")); m_newStuffDialog.data()->setWindowTitle(i18n("Download New Color Schemes")); m_newStuffDialog->setWindowModality(Qt::WindowModal); m_newStuffDialog->winId(); // so it creates the windowHandle(); connect(m_newStuffDialog.data(), &KNS3::DownloadDialog::accepted, this, [this] { m_model->load(); const auto newEntries = m_newStuffDialog->installedEntries(); // If one new theme was installed, select the first color file in it if (newEntries.count() == 1) { QStringList installedThemes; const QString suffix = QStringLiteral(".colors"); for (const QString &path : newEntries.first().installedFiles()) { const QString fileName = path.section(QLatin1Char('/'), -1, -1); const int suffixPos = fileName.indexOf(suffix); if (suffixPos != fileName.length() - suffix.length()) { continue; } installedThemes.append(fileName.left(suffixPos)); } if (!installedThemes.isEmpty()) { // The list is sorted by (potentially translated) name // but that would require us parse every file, so this should be close enough std::sort(installedThemes.begin(), installedThemes.end()); m_model->setSelectedScheme(installedThemes.constFirst()); } } }); } if (ctx && ctx->window()) { m_newStuffDialog->windowHandle()->setTransientParent(ctx->window()); } m_newStuffDialog.data()->show(); } void KCMColors::installSchemeFromFile(const QUrl &url) { if (url.isLocalFile()) { installSchemeFile(url.toLocalFile()); return; } if (m_tempCopyJob) { return; } m_tempInstallFile.reset(new QTemporaryFile()); if (!m_tempInstallFile->open()) { emit showErrorMessage(i18n("Unable to create a temporary file.")); m_tempInstallFile.reset(); return; } // Ideally we copied the file into the proper location right away but // (for some reason) we determine the file name from the "Name" inside the file m_tempCopyJob = KIO::file_copy(url, QUrl::fromLocalFile(m_tempInstallFile->fileName()), -1, KIO::Overwrite); m_tempCopyJob->uiDelegate()->setAutoErrorHandlingEnabled(true); emit downloadingFileChanged(); connect(m_tempCopyJob, &KIO::FileCopyJob::result, this, [this, url](KJob *job) { if (job->error() != KJob::NoError) { emit showErrorMessage(i18n("Unable to download the color scheme: %1", job->errorText())); return; } installSchemeFile(m_tempInstallFile->fileName()); m_tempInstallFile.reset(); }); connect(m_tempCopyJob, &QObject::destroyed, this, &KCMColors::downloadingFileChanged); } void KCMColors::installSchemeFile(const QString &path) { KSharedConfigPtr config = KSharedConfig::openConfig(path, KConfig::SimpleConfig); KConfigGroup group(config, "General"); const QString name = group.readEntry("Name"); if (name.isEmpty()) { emit showErrorMessage(i18n("This file is not a color scheme file.")); return; } // Do not overwrite another scheme int increment = 0; QString newName = name; QString testpath; do { if (increment) { newName = name + QString::number(increment); } testpath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("color-schemes/%1.colors").arg(newName)); increment++; } while (!testpath.isEmpty()); QString newPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1String("/color-schemes/"); if (!QDir().mkpath(newPath)) { emit showErrorMessage(i18n("Failed to create 'color-scheme' data folder.")); return; } newPath += newName + QLatin1String(".colors"); if (!QFile::copy(path, newPath)) { emit showErrorMessage(i18n("Failed to copy color scheme into 'color-scheme' data folder.")); return; } // Update name KSharedConfigPtr config2 = KSharedConfig::openConfig(newPath, KConfig::SimpleConfig); KConfigGroup group2(config2, "General"); group2.writeEntry("Name", newName); config2->sync(); m_model->load(); const auto results = m_model->match(m_model->index(0, 0), SchemeNameRole, newName); if (!results.isEmpty()) { m_model->setSelectedScheme(newName); } emit showSuccessMessage(i18n("Color scheme installed successfully.")); } void KCMColors::editScheme(const QString &schemeName, QQuickItem *ctx) { if (m_editDialogProcess) { return; } QModelIndex idx = m_model->index(m_model->indexOfScheme(schemeName), 0); m_editDialogProcess = new QProcess(this); connect(m_editDialogProcess, QOverload::of(&QProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) { Q_UNUSED(exitCode); Q_UNUSED(exitStatus); const auto savedThemes = QString::fromUtf8(m_editDialogProcess->readAllStandardOutput()).split(QLatin1Char('\n'), QString::SkipEmptyParts); if (!savedThemes.isEmpty()) { m_model->load(); // would be cool to just reload/add the changed/new ones m_model->setSelectedScheme(savedThemes.last()); } m_editDialogProcess->deleteLater(); m_editDialogProcess = nullptr; }); QStringList args; args << idx.data(KCMColors::SchemeNameRole).toString(); if (idx.data(KCMColors::RemovableRole).toBool()) { args << QStringLiteral("--overwrite"); } if (ctx && ctx->window()) { // QQuickWidget, used for embedding QML KCMs, renders everything into an offscreen window // Qt is able to resolve this on its own when setting transient parents in-process. // However, since we pass the ID to an external process which has no idea of this // we need to resolve the actual window we end up showing in. if (QWindow *actualWindow = QQuickRenderControl::renderWindowFor(ctx->window())) { if (KWindowSystem::isPlatformX11()) { // TODO wayland: once we have foreign surface support args << QStringLiteral("--attach") << (QStringLiteral("x11:") + QString::number(actualWindow->winId())); } } } m_editDialogProcess->start(QStringLiteral("kcolorschemeeditor"), args); } void KCMColors::load() { m_model->load(); m_config->markAsClean(); m_config->reparseConfiguration(); KConfigGroup group(m_config, "General"); const QString schemeName = group.readEntry("ColorScheme", s_defaultColorSchemeName); // If the scheme named in kdeglobals doesn't exist, show a warning and use default scheme if (m_model->indexOfScheme(schemeName) == -1) { m_model->setSelectedScheme(s_defaultColorSchemeName); // These are normally synced but initially the model doesn't emit a change to avoid the // Apply button from being enabled without any user interaction. Sync manually here. m_filteredModel->setSelectedScheme(s_defaultColorSchemeName); emit showSchemeNotInstalledWarning(schemeName); } else { m_model->setSelectedScheme(schemeName); m_filteredModel->setSelectedScheme(schemeName); } { KConfig cfg(QStringLiteral("kcmdisplayrc"), KConfig::NoGlobals); group = KConfigGroup(&cfg, "X11"); m_applyToAlien = group.readEntry("exportKDEColors", true); } } void KCMColors::save() { if (m_selectedSchemeDirty) { saveColors(); } processPendingDeletions(); setNeedsSave(false); } void KCMColors::saveColors() { KConfigGroup grp(m_config, "General"); grp.writeEntry("ColorScheme", m_model->selectedScheme()); const QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("color-schemes/%1.colors").arg(m_model->selectedScheme())); KSharedConfigPtr config = KSharedConfig::openConfig(path); const QStringList colorSetGroupList{ QStringLiteral("Colors:View"), QStringLiteral("Colors:Window"), QStringLiteral("Colors:Button"), QStringLiteral("Colors:Selection"), QStringLiteral("Colors:Tooltip"), QStringLiteral("Colors:Complementary") }; const QList colorSchemes{ KColorScheme(QPalette::Active, KColorScheme::View, config), KColorScheme(QPalette::Active, KColorScheme::Window, config), KColorScheme(QPalette::Active, KColorScheme::Button, config), KColorScheme(QPalette::Active, KColorScheme::Selection, config), KColorScheme(QPalette::Active, KColorScheme::Tooltip, config), KColorScheme(QPalette::Active, KColorScheme::Complementary, config) }; for (int i = 0; i < colorSchemes.length(); ++i) { KConfigGroup group(m_config, colorSetGroupList.value(i)); group.writeEntry("BackgroundNormal", colorSchemes[i].background(KColorScheme::NormalBackground).color()); group.writeEntry("BackgroundAlternate", colorSchemes[i].background(KColorScheme::AlternateBackground).color()); group.writeEntry("ForegroundNormal", colorSchemes[i].foreground(KColorScheme::NormalText).color()); group.writeEntry("ForegroundInactive", colorSchemes[i].foreground(KColorScheme::InactiveText).color()); group.writeEntry("ForegroundActive", colorSchemes[i].foreground(KColorScheme::ActiveText).color()); group.writeEntry("ForegroundLink", colorSchemes[i].foreground(KColorScheme::LinkText).color()); group.writeEntry("ForegroundVisited", colorSchemes[i].foreground(KColorScheme::VisitedText).color()); group.writeEntry("ForegroundNegative", colorSchemes[i].foreground(KColorScheme::NegativeText).color()); group.writeEntry("ForegroundNeutral", colorSchemes[i].foreground(KColorScheme::NeutralText).color()); group.writeEntry("ForegroundPositive", colorSchemes[i].foreground(KColorScheme::PositiveText).color()); group.writeEntry("DecorationFocus", colorSchemes[i].decoration(KColorScheme::FocusColor).color()); group.writeEntry("DecorationHover", colorSchemes[i].decoration(KColorScheme::HoverColor).color()); } KConfigGroup groupWMTheme(config, "WM"); KConfigGroup groupWMOut(m_config, "WM"); const QStringList colorItemListWM{ QStringLiteral("activeBackground"), QStringLiteral("activeForeground"), QStringLiteral("inactiveBackground"), QStringLiteral("inactiveForeground"), QStringLiteral("activeBlend"), QStringLiteral("inactiveBlend") }; const QVector defaultWMColors{ QColor(71,80,87), QColor(239,240,241), QColor(239,240,241), QColor(189,195,199), QColor(255,255,255), QColor(75,71,67) }; int i = 0; for (const QString &coloritem : colorItemListWM) { groupWMOut.writeEntry(coloritem, groupWMTheme.readEntry(coloritem, defaultWMColors.value(i))); ++i; } const QStringList groupNameList{ QStringLiteral("ColorEffects:Inactive"), QStringLiteral("ColorEffects:Disabled") }; const QStringList effectList{ QStringLiteral("Enable"), QStringLiteral("ChangeSelectionColor"), QStringLiteral("IntensityEffect"), QStringLiteral("IntensityAmount"), QStringLiteral("ColorEffect"), QStringLiteral("ColorAmount"), QStringLiteral("Color"), QStringLiteral("ContrastEffect"), QStringLiteral("ContrastAmount") }; for (const QString &groupName : groupNameList) { KConfigGroup groupEffectOut(m_config, groupName); KConfigGroup groupEffectTheme(config, groupName); for (const QString &effect : effectList) { groupEffectOut.writeEntry(effect, groupEffectTheme.readEntry(effect)); } } m_config->sync(); runRdb(KRdbExportQtColors | KRdbExportGtkTheme | KRdbExportGtkColors | (m_applyToAlien ? KRdbExportColors : 0)); - KCMColors::saveGtkColors(config); + saveGtkColors(config); QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KGlobalSettings"), QStringLiteral("org.kde.KGlobalSettings"), QStringLiteral("notifyChange")); message.setArguments({ 0, //previous KGlobalSettings::PaletteChanged. This is now private API in khintsettings 0 //unused in palette changed but needed for the DBus signature }); QDBusConnection::sessionBus().send(message); if (KWindowSystem::isPlatformX11()) { // Send signal to all kwin instances QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig")); QDBusConnection::sessionBus().send(message); } m_selectedSchemeDirty = false; } void KCMColors::processPendingDeletions() { const QStringList pendingDeletions = m_model->pendingDeletions(); for (const QString &schemeName : pendingDeletions) { Q_ASSERT(schemeName != m_model->selectedScheme()); const QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("color-schemes/%1.colors").arg(schemeName)); auto *job = KIO::del(QUrl::fromLocalFile(path), KIO::HideProgressInfo); // needs to block for it to work on "OK" where the dialog (kcmshell) closes job->exec(); } m_model->removeItemsPendingDeletion(); } void KCMColors::defaults() { m_model->setSelectedScheme(s_defaultColorSchemeName); setNeedsSave(true); } -QString KCMColors::gtkColorsHelper(const QString &name, const QString &color) -{ - return QStringLiteral("@define-color %1 %2;\n").arg(name, color); -} - -void KCMColors::saveGtkColors(KSharedConfigPtr& config) -{ - QFile gtkCss(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/gtk-3.0/gtk.css"); - QFile colorsCss(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/gtk-3.0/colors.css"); - - if (gtkCss.open(QIODevice::ReadWrite)) { - QTextStream gtkStream(>kCss); - bool hasImport = false; - while (!gtkStream.atEnd()) { - QString line = gtkStream.readLine(); - if (line.contains("@import 'colors.css';")) { - hasImport = true; - } - } - if (!hasImport) { - gtkStream << "@import 'colors.css';"; - } - } - if (colorsCss.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - QTextStream colorsStream(&colorsCss); - /* - 0 Active View - 1 Active Window - 2 Active Button - 3 Active Selection - 4 Active Tooltip - 5 Active Complimentary - */ - - QList activeColorSchemes{ - KColorScheme(QPalette::Active, KColorScheme::View, config), - KColorScheme(QPalette::Active, KColorScheme::Window, config), - KColorScheme(QPalette::Active, KColorScheme::Button, config), - KColorScheme(QPalette::Active, KColorScheme::Selection, config), - KColorScheme(QPalette::Active, KColorScheme::Tooltip, config), - KColorScheme(QPalette::Active, KColorScheme::Complementary, config) - }; - QList inactiveColorSchemes{ - KColorScheme(QPalette::Inactive, KColorScheme::View, config), - KColorScheme(QPalette::Inactive, KColorScheme::Window, config), - KColorScheme(QPalette::Inactive, KColorScheme::Button, config), - KColorScheme(QPalette::Inactive, KColorScheme::Selection, config), - KColorScheme(QPalette::Inactive, KColorScheme::Tooltip, config), - KColorScheme(QPalette::Inactive, KColorScheme::Complementary, config) - }; - QList disabledColorSchemes{ - KColorScheme(QPalette::Disabled, KColorScheme::View, config), - KColorScheme(QPalette::Disabled, KColorScheme::Window, config), - KColorScheme(QPalette::Disabled, KColorScheme::Button, config), - KColorScheme(QPalette::Disabled, KColorScheme::Selection, config), - KColorScheme(QPalette::Disabled, KColorScheme::Tooltip, config), - KColorScheme(QPalette::Disabled, KColorScheme::Complementary, config) - }; - - /* - Normal (Non Backdrop, Non Insensitive) - */ - - // General Colors - - colorsStream << gtkColorsHelper("theme_fg_color", activeColorSchemes[1].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_bg_color", activeColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_text_color", activeColorSchemes[0].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_base_color", activeColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_view_hover_decoration_color", activeColorSchemes[0].decoration(KColorScheme::HoverColor).color().name()); - colorsStream << gtkColorsHelper("theme_hovering_selected_bg_color", activeColorSchemes[3].decoration(KColorScheme::HoverColor).color().name()); - colorsStream << gtkColorsHelper("theme_selected_bg_color", activeColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_selected_fg_color", activeColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_view_active_decoration_color", activeColorSchemes[0].decoration(KColorScheme::HoverColor).color().name()); - - // Button Colors - colorsStream << gtkColorsHelper("theme_button_background_normal", activeColorSchemes[2].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_hover", activeColorSchemes[2].decoration(KColorScheme::HoverColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_focus", activeColorSchemes[2].decoration(KColorScheme::FocusColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_normal", activeColorSchemes[2].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_active", activeColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Misc Colors - QColor windowForegroundColor = activeColorSchemes[1].foreground(KColorScheme::NormalText).color(); - QColor windowBackgroundColor = activeColorSchemes[1].background(KColorScheme::NormalBackground).color(); - QColor bordersColor = KColorUtils::mix(windowBackgroundColor,windowForegroundColor, 0.25); - - colorsStream << gtkColorsHelper("borders", bordersColor.name()); - colorsStream << gtkColorsHelper("warning_color", activeColorSchemes[0].foreground(KColorScheme::NeutralText).color().name()); - colorsStream << gtkColorsHelper("success_color", activeColorSchemes[0].foreground(KColorScheme::PositiveText).color().name()); - colorsStream << gtkColorsHelper("error_color", activeColorSchemes[0].foreground(KColorScheme::NegativeText).color().name()); - - /* - Backdrop (Inactive) - */ - - // General - colorsStream << gtkColorsHelper("theme_unfocused_fg_color",inactiveColorSchemes[1].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_text_color", inactiveColorSchemes[0].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_bg_color", inactiveColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_base_color", inactiveColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_selected_bg_color_alt", inactiveColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_selected_bg_color", inactiveColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_selected_fg_color", inactiveColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Button - colorsStream << gtkColorsHelper("theme_button_background_normal_backdrop", inactiveColorSchemes[2].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_hover_backdrop", inactiveColorSchemes[2].decoration(KColorScheme::HoverColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_focus_backdrop", inactiveColorSchemes[2].decoration(KColorScheme::FocusColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_normal_backdrop", inactiveColorSchemes[2].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_active_backdrop", inactiveColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Misc Colors - QColor inactiveWindowForegroundColor = inactiveColorSchemes[1].foreground(KColorScheme::NormalText).color(); - QColor inactiveWindowBackgroundColor = inactiveColorSchemes[1].background(KColorScheme::NormalBackground).color(); - QColor inactiveBordersColor = KColorUtils::mix(inactiveWindowBackgroundColor,inactiveWindowForegroundColor, 0.25); - - colorsStream << gtkColorsHelper("unfocused_borders", inactiveBordersColor.name()); - colorsStream << gtkColorsHelper("warning_color_backdrop", inactiveColorSchemes[0].foreground(KColorScheme::NeutralText).color().name()); - colorsStream << gtkColorsHelper("success_color_backdrop", inactiveColorSchemes[0].foreground(KColorScheme::PositiveText).color().name()); - colorsStream << gtkColorsHelper("error_color_backdrop", inactiveColorSchemes[0].foreground(KColorScheme::NegativeText).color().name()); - - /* - Insensitive (Disabled) - */ - - // General - colorsStream << gtkColorsHelper("insensitive_fg_color",disabledColorSchemes[1].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("insensitive_base_fg_color", disabledColorSchemes[0].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("insensitive_bg_color", disabledColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("insensitive_base_color", disabledColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("insensitive_selected_bg_color", disabledColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("insensitive_selected_fg_color", disabledColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Button - colorsStream << gtkColorsHelper("theme_button_background_normal_insensitive", disabledColorSchemes[2].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_hover_insensitive", disabledColorSchemes[2].decoration(KColorScheme::HoverColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_focus_insensitive", disabledColorSchemes[2].decoration(KColorScheme::FocusColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_normal_insensitive", disabledColorSchemes[2].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_active_insensitive", disabledColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Misc Colors - QColor disabledWindowForegroundColor = disabledColorSchemes[1].foreground(KColorScheme::NormalText).color(); - QColor disabledWindowBackgroundColor = disabledColorSchemes[1].background(KColorScheme::NormalBackground).color(); - QColor disabledBordersColor = KColorUtils::mix(disabledWindowBackgroundColor,disabledWindowForegroundColor, 0.25); - - colorsStream << gtkColorsHelper("insensitive_borders", disabledBordersColor.name()); - colorsStream << gtkColorsHelper("warning_color_insensitive", disabledColorSchemes[0].foreground(KColorScheme::NeutralText).color().name()); - colorsStream << gtkColorsHelper("success_color_insensitive", disabledColorSchemes[0].foreground(KColorScheme::PositiveText).color().name()); - colorsStream << gtkColorsHelper("error_color_insensitive", disabledColorSchemes[0].foreground(KColorScheme::NegativeText).color().name()); - - /* - Insensitive Backdrop (Inactive Disabled) These pretty much have the same appearance as regular inactive colors, but they're seperate in case we decide to make - them different in the future. - */ - - // General - colorsStream << gtkColorsHelper("insensitive_unfocused_fg_color",disabledColorSchemes[1].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_view_text_color", disabledColorSchemes[0].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("insensitive_unfocused_bg_color", disabledColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_view_bg_color", disabledColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("insensitive_unfocused_selected_bg_color", disabledColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("insensitive_unfocused_selected_fg_color", disabledColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Button - colorsStream << gtkColorsHelper("theme_button_background_normal_backdrop_insensitive", disabledColorSchemes[2].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_hover_backdrop_insensitive", disabledColorSchemes[2].decoration(KColorScheme::HoverColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_focus_backdrop_insensitive", disabledColorSchemes[2].decoration(KColorScheme::FocusColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_normal_backdrop_insensitive", disabledColorSchemes[2].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_active_backdrop_insensitive", disabledColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Misc Colors - QColor unfocusedDisabledWindowForegroundColor = disabledColorSchemes[1].foreground(KColorScheme::NormalText).color(); - QColor unfocusedDisabledWindowBackgroundColor = disabledColorSchemes[1].background(KColorScheme::NormalBackground).color(); - QColor unfocusedDisabledBordersColor = KColorUtils::mix(unfocusedDisabledWindowBackgroundColor,unfocusedDisabledWindowForegroundColor, 0.25); - - colorsStream << gtkColorsHelper("unfocused_insensitive_borders", unfocusedDisabledBordersColor.name()); - colorsStream << gtkColorsHelper("warning_color_insensitive_backdrop", disabledColorSchemes[0].foreground(KColorScheme::NeutralText).color().name()); - colorsStream << gtkColorsHelper("success_color_insensitive_backdrop", disabledColorSchemes[0].foreground(KColorScheme::PositiveText).color().name()); - colorsStream << gtkColorsHelper("error_color_insensitive_backdrop", disabledColorSchemes[0].foreground(KColorScheme::NegativeText).color().name()); - - /* - Ignorant Colors (These colors do not care about backdrop or insensitive states) - */ - - colorsStream << gtkColorsHelper("link_color", activeColorSchemes[0].foreground(KColorScheme::LinkText).color().name()); - colorsStream << gtkColorsHelper("link_visited_color", activeColorSchemes[0].foreground(KColorScheme::VisitedText).color().name()); - - QColor tooltipForegroundColor = activeColorSchemes[4].foreground(KColorScheme::NormalText).color(); - QColor tooltipBackgroundColor = activeColorSchemes[4].background(KColorScheme::NormalBackground).color(); - QColor tooltipBorderColor = KColorUtils::mix(tooltipBackgroundColor, tooltipForegroundColor, 0.25); - - colorsStream << gtkColorsHelper("tooltip_text", tooltipForegroundColor.name()); - colorsStream << gtkColorsHelper("tooltip_background", tooltipBackgroundColor.name()); - colorsStream << gtkColorsHelper("tooltip_border", tooltipBorderColor.name()); - - colorsStream << gtkColorsHelper("content_view_bg", activeColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); - - /* - Theme titlebar colors - */ - KConfigGroup groupWMTheme(config, "WM"); - colorsStream << gtkColorsHelper("theme_titlebar_background", "rgb(" + groupWMTheme.readEntry("activeBackground", "") + ")"); - colorsStream << gtkColorsHelper("theme_titlebar_foreground", "rgb(" + groupWMTheme.readEntry("activeForeground", "") + ")"); - colorsStream << gtkColorsHelper("theme_titlebar_background_light", activeColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_titlebar_foreground_backdrop", "rgb(" + groupWMTheme.readEntry("inactiveForeground", "") + ")"); - colorsStream << gtkColorsHelper("theme_titlebar_background_backdrop", "rgb(" + groupWMTheme.readEntry("inactiveBackground", "") + ")"); - colorsStream << gtkColorsHelper("theme_titlebar_foreground_insensitive", "rgb(" + groupWMTheme.readEntry("inactiveForeground", "") + ")"); - colorsStream << gtkColorsHelper("theme_titlebar_foreground_insensitive_backdrop", "rgb(" + groupWMTheme.readEntry("inactiveForeground", "") + ")"); - } -} - #include "colors.moc" diff --git a/kcms/colors/colors.h b/kcms/colors/colors.h index 9cb723a29..2ca811007 100644 --- a/kcms/colors/colors.h +++ b/kcms/colors/colors.h @@ -1,118 +1,116 @@ /* * Copyright (c) 2019 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 . */ #pragma once #include #include #include #include #include class QProcess; class QTemporaryFile; namespace KIO { class FileCopyJob; } class ColorsModel; class FilterProxyModel; class KCMColors : public KQuickAddons::ConfigModule { Q_OBJECT Q_PROPERTY(ColorsModel *model READ model CONSTANT) Q_PROPERTY(FilterProxyModel *filteredModel READ filteredModel CONSTANT) Q_PROPERTY(bool downloadingFile READ downloadingFile NOTIFY downloadingFileChanged) public: KCMColors(QObject *parent, const QVariantList &args); ~KCMColors() override; enum Roles { SchemeNameRole = Qt::UserRole + 1, PaletteRole, RemovableRole, PendingDeletionRole }; enum SchemeFilter { AllSchemes, LightSchemes, DarkSchemes }; Q_ENUM(SchemeFilter) ColorsModel *model() const; FilterProxyModel *filteredModel() const; bool downloadingFile() const; Q_INVOKABLE void getNewStuff(QQuickItem *ctx); Q_INVOKABLE void installSchemeFromFile(const QUrl &url); Q_INVOKABLE void editScheme(const QString &schemeName, QQuickItem *ctx); public Q_SLOTS: void load() override; void save() override; void defaults() override; Q_SIGNALS: void selectedSchemeChanged(); void selectedSchemeIndexChanged(); void downloadingFileChanged(); void showSuccessMessage(const QString &message); void showErrorMessage(const QString &message); void showSchemeNotInstalledWarning(const QString &schemeName); private: void saveColors(); - static void saveGtkColors(KSharedConfigPtr& config); - static QString gtkColorsHelper(const QString &name, const QString &color); void processPendingDeletions(); void installSchemeFile(const QString &path); ColorsModel *m_model; FilterProxyModel *m_filteredModel; bool m_selectedSchemeDirty = false; bool m_applyToAlien = true; QPointer m_newStuffDialog; QProcess *m_editDialogProcess = nullptr; KSharedConfigPtr m_config; QScopedPointer m_tempInstallFile; QPointer m_tempCopyJob; }; diff --git a/kcms/krdb/krdb.cpp b/kcms/krdb/krdb.cpp index 997cb692b..aaea26bcf 100644 --- a/kcms/krdb/krdb.cpp +++ b/kcms/krdb/krdb.cpp @@ -1,938 +1,990 @@ /**************************************************************************** ** ** ** KRDB - puts current KDE color scheme into preprocessor statements ** cats specially written application default files and uses xrdb -merge to ** write to RESOURCE_MANAGER. Thus it gives a simple way to make non-KDE ** applications fit in with the desktop ** ** Copyright (C) 1998 by Mark Donohoe ** Copyright (C) 1999 by Dirk A. Mueller (reworked for KDE 2.0) ** Copyright (C) 2001 by Matthias Ettrich (add support for GTK applications ) ** Copyright (C) 2001 by Waldo Bastian ** Copyright (C) 2002 by Karol Szwed ** This application is freely distributable under the GNU Public License. ** *****************************************************************************/ #include #include #include #include #include #include #undef Unsorted #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "krdb.h" #if HAVE_X11 #include #include #endif inline const char * gtkEnvVar(int version) { return 2==version ? "GTK2_RC_FILES" : "GTK_RC_FILES"; } inline const char * sysGtkrc(int version) { if(2==version) { if(access("/etc/opt/gnome/gtk-2.0", F_OK) == 0) return "/etc/opt/gnome/gtk-2.0/gtkrc"; else return "/etc/gtk-2.0/gtkrc"; } else { if(access("/etc/opt/gnome/gtk", F_OK) == 0) return "/etc/opt/gnome/gtk/gtkrc"; else return "/etc/gtk/gtkrc"; } } inline const char * userGtkrc(int version) { return 2==version ? "/.gtkrc-2.0" : "/.gtkrc"; } // ----------------------------------------------------------------------------- static QString writableGtkrc(int version) { QString gtkrc = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); QDir dir; dir.mkpath(gtkrc); gtkrc += 2==version?"/gtkrc-2.0":"/gtkrc"; return gtkrc; } // ----------------------------------------------------------------------------- static void applyGtkStyles(bool active, int version) { QString gtkkde = writableGtkrc(version); QByteArray gtkrc = getenv(gtkEnvVar(version)); QStringList list = QFile::decodeName(gtkrc).split( QLatin1Char(':')); QString userHomeGtkrc = QDir::homePath()+userGtkrc(version); if (!list.contains(userHomeGtkrc)) list.prepend(userHomeGtkrc); QLatin1String systemGtkrc = QLatin1String(sysGtkrc(version)); if (!list.contains(systemGtkrc)) list.prepend(systemGtkrc); list.removeAll(QLatin1String("")); list.removeAll(gtkkde); list.append(gtkkde); // Pass env. var to kdeinit. QString name = gtkEnvVar(version); QString value = list.join(QStringLiteral(":")); org::kde::KLauncher klauncher(QStringLiteral("org.kde.klauncher5"), QStringLiteral("/KLauncher"), QDBusConnection::sessionBus()); klauncher.setLaunchEnv(name, value); } // ----------------------------------------------------------------------------- static void applyQtColors( KSharedConfigPtr kglobalcfg, QSettings& settings, QPalette& newPal ) { QStringList actcg, inactcg, discg; /* export kde color settings */ int i; for (i = 0; i < QPalette::NColorRoles; i++) actcg << newPal.color(QPalette::Active, (QPalette::ColorRole) i).name(); for (i = 0; i < QPalette::NColorRoles; i++) inactcg << newPal.color(QPalette::Inactive, (QPalette::ColorRole) i).name(); for (i = 0; i < QPalette::NColorRoles; i++) discg << newPal.color(QPalette::Disabled, (QPalette::ColorRole) i).name(); settings.setValue(QStringLiteral("/qt/Palette/active"), actcg); settings.setValue(QStringLiteral("/qt/Palette/inactive"), inactcg); settings.setValue(QStringLiteral("/qt/Palette/disabled"), discg); // export kwin's colors to qtrc for kstyle to use KConfigGroup wmCfgGroup(kglobalcfg, "WM"); // active colors QColor clr = newPal.color( QPalette::Active, QPalette::Window ); clr = wmCfgGroup.readEntry("activeBackground", clr); settings.setValue(QStringLiteral("/qt/KWinPalette/activeBackground"), clr.name()); if (QPixmap::defaultDepth() > 8) clr = clr.darker(110); clr = wmCfgGroup.readEntry("activeBlend", clr); settings.setValue(QStringLiteral("/qt/KWinPalette/activeBlend"), clr.name()); clr = newPal.color( QPalette::Active, QPalette::HighlightedText ); clr = wmCfgGroup.readEntry("activeForeground", clr); settings.setValue(QStringLiteral("/qt/KWinPalette/activeForeground"), clr.name()); clr = newPal.color( QPalette::Active,QPalette::Window ); clr = wmCfgGroup.readEntry("frame", clr); settings.setValue(QStringLiteral("/qt/KWinPalette/frame"), clr.name()); clr = wmCfgGroup.readEntry("activeTitleBtnBg", clr); settings.setValue(QStringLiteral("/qt/KWinPalette/activeTitleBtnBg"), clr.name()); // inactive colors clr = newPal.color(QPalette::Inactive, QPalette::Window); clr = wmCfgGroup.readEntry("inactiveBackground", clr); settings.setValue(QStringLiteral("/qt/KWinPalette/inactiveBackground"), clr.name()); if (QPixmap::defaultDepth() > 8) clr = clr.darker(110); clr = wmCfgGroup.readEntry("inactiveBlend", clr); settings.setValue(QStringLiteral("/qt/KWinPalette/inactiveBlend"), clr.name()); clr = newPal.color(QPalette::Inactive, QPalette::Window).darker(); clr = wmCfgGroup.readEntry("inactiveForeground", clr); settings.setValue(QStringLiteral("/qt/KWinPalette/inactiveForeground"), clr.name()); clr = newPal.color(QPalette::Inactive, QPalette::Window); clr = wmCfgGroup.readEntry("inactiveFrame", clr); settings.setValue(QStringLiteral("/qt/KWinPalette/inactiveFrame"), clr.name()); clr = wmCfgGroup.readEntry("inactiveTitleBtnBg", clr); settings.setValue(QStringLiteral("/qt/KWinPalette/inactiveTitleBtnBg"), clr.name()); KConfigGroup kdeCfgGroup(kglobalcfg, "KDE"); settings.setValue(QStringLiteral("/qt/KDE/contrast"), kdeCfgGroup.readEntry("contrast", 7)); } // ----------------------------------------------------------------------------- static void applyQtSettings( KSharedConfigPtr kglobalcfg, QSettings& settings ) { /* export font settings */ // NOTE keep this in sync with kfontsettingsdata in plasma-integration (cf. also Bug 378262) QFont defaultFont(QStringLiteral("Noto Sans"), 10, -1); defaultFont.setStyleHint(QFont::SansSerif); const KConfigGroup configGroup(KSharedConfig::openConfig(), QStringLiteral("General")); const QString fontInfo = configGroup.readEntry(QStringLiteral("font"), QString()); if (!fontInfo.isEmpty()) { defaultFont.fromString(fontInfo); } settings.setValue(QStringLiteral("/qt/font"), defaultFont.toString()); /* export effects settings */ KConfigGroup kdeCfgGroup(kglobalcfg, "General"); bool effectsEnabled = kdeCfgGroup.readEntry("EffectsEnabled", false); bool fadeMenus = kdeCfgGroup.readEntry("EffectFadeMenu", false); bool fadeTooltips = kdeCfgGroup.readEntry("EffectFadeTooltip", false); bool animateCombobox = kdeCfgGroup.readEntry("EffectAnimateCombo", false); QStringList guieffects; if (effectsEnabled) { guieffects << QStringLiteral("general"); if (fadeMenus) guieffects << QStringLiteral("fademenu"); if (animateCombobox) guieffects << QStringLiteral("animatecombo"); if (fadeTooltips) guieffects << QStringLiteral("fadetooltip"); } else guieffects << QStringLiteral("none"); settings.setValue(QStringLiteral("/qt/GUIEffects"), guieffects); } // ----------------------------------------------------------------------------- static void addColorDef(QString& s, const char* n, const QColor& col) { QString tmp; tmp.sprintf("#define %s #%02x%02x%02x\n", n, col.red(), col.green(), col.blue()); s += tmp; } // ----------------------------------------------------------------------------- static void copyFile(QFile& tmp, QString const& filename, bool ) { QFile f( filename ); if ( f.open(QIODevice::ReadOnly) ) { QByteArray buf( 8192, ' ' ); while ( !f.atEnd() ) { int read = f.read( buf.data(), buf.size() ); if ( read > 0 ) tmp.write( buf.data(), read ); } } } // ----------------------------------------------------------------------------- static QString item( int i ) { return QString::number( i / 255.0, 'f', 3 ); } static QString color( const QColor& col ) { return QStringLiteral( "{ %1, %2, %3 }" ).arg( item( col.red() ) ).arg( item( col.green() ) ).arg( item( col.blue() ) ); } static void createGtkrc( bool exportColors, const QPalette& cg, bool exportGtkTheme, const QString& gtkTheme, int version ) { // lukas: why does it create in ~/.kde/share/config ??? // pfeiffer: so that we don't overwrite the user's gtkrc. // it is found via the GTK_RC_FILES environment variable. QSaveFile saveFile( writableGtkrc(version) ); if ( !saveFile.open(QIODevice::WriteOnly) ) return; QTextStream t ( &saveFile ); t.setCodec( QTextCodec::codecForLocale () ); t << i18n( "# created by KDE Plasma, %1\n" "#\n" "# If you do not want Plasma to override your GTK settings, select\n" "# Colors in the System Settings and disable the checkbox\n" "# \"Apply colors to non-Qt applications\"\n" "#\n" "#\n", QDateTime::currentDateTime().toString()); if ( 2==version ) { // we should maybe check for MacOS settings here t << endl; t << "gtk-alternative-button-order = 1" << endl; t << endl; } if (exportGtkTheme) { QString gtkStyle; if (gtkTheme.toLower() == QLatin1String("oxygen")) gtkStyle = QStringLiteral("oxygen-gtk"); else gtkStyle = gtkTheme; bool exist_gtkrc = false; QByteArray gtkrc = getenv(gtkEnvVar(version)); QStringList listGtkrc = QFile::decodeName(gtkrc).split(QLatin1Char(':')); if (listGtkrc.contains(saveFile.fileName())) listGtkrc.removeAll(saveFile.fileName()); listGtkrc.append(QDir::homePath() + userGtkrc(version)); listGtkrc.append(QDir::homePath() + "/.gtkrc-2.0-kde"); listGtkrc.append(QDir::homePath() + "/.gtkrc-2.0-kde4"); listGtkrc.removeAll(QLatin1String("")); listGtkrc.removeDuplicates(); for (int i = 0; i < listGtkrc.size(); ++i) { if ((exist_gtkrc = QFile::exists(listGtkrc.at(i)))) break; } if (!exist_gtkrc) { QString gtk2ThemeFilename; gtk2ThemeFilename = QStringLiteral("%1/.themes/%2/gtk-2.0/gtkrc").arg(QDir::homePath()).arg(gtkStyle); if (!QFile::exists(gtk2ThemeFilename)) { QStringList gtk2ThemePath; gtk2ThemeFilename.clear(); QByteArray xdgDataDirs = getenv("XDG_DATA_DIRS"); gtk2ThemePath.append(QDir::homePath() + "/.local"); gtk2ThemePath.append(QFile::decodeName(xdgDataDirs).split(QLatin1Char(':'))); gtk2ThemePath.removeDuplicates(); for (int i = 0; i < gtk2ThemePath.size(); ++i) { gtk2ThemeFilename = QStringLiteral("%1/themes/%2/gtk-2.0/gtkrc").arg(gtk2ThemePath.at(i)).arg(gtkStyle); if (QFile::exists(gtk2ThemeFilename)) break; else gtk2ThemeFilename.clear(); } } if (!gtk2ThemeFilename.isEmpty()) { t << "include \"" << gtk2ThemeFilename << "\"" << endl; t << endl; t << "gtk-theme-name=\"" << gtkStyle << "\"" << endl; t << endl; if (gtkStyle == QLatin1String("oxygen-gtk")) exportColors = false; } } } if (exportColors) { t << "style \"default\"" << endl; t << "{" << endl; t << " bg[NORMAL] = " << color( cg.color( QPalette::Active, QPalette::Window ) ) << endl; t << " bg[SELECTED] = " << color( cg.color(QPalette::Active, QPalette::Highlight) ) << endl; t << " bg[INSENSITIVE] = " << color( cg.color( QPalette::Active, QPalette::Window ) ) << endl; t << " bg[ACTIVE] = " << color( cg.color( QPalette::Active, QPalette::Mid ) ) << endl; t << " bg[PRELIGHT] = " << color( cg.color( QPalette::Active, QPalette::Window ) ) << endl; t << endl; t << " base[NORMAL] = " << color( cg.color( QPalette::Active, QPalette::Base ) ) << endl; t << " base[SELECTED] = " << color( cg.color(QPalette::Active, QPalette::Highlight) ) << endl; t << " base[INSENSITIVE] = " << color( cg.color( QPalette::Active, QPalette::Window ) ) << endl; t << " base[ACTIVE] = " << color( cg.color(QPalette::Active, QPalette::Highlight) ) << endl; t << " base[PRELIGHT] = " << color( cg.color(QPalette::Active, QPalette::Highlight) ) << endl; t << endl; t << " text[NORMAL] = " << color( cg.color(QPalette::Active, QPalette::Text) ) << endl; t << " text[SELECTED] = " << color( cg.color(QPalette::Active, QPalette::HighlightedText) ) << endl; t << " text[INSENSITIVE] = " << color( cg.color( QPalette::Active, QPalette::Mid ) ) << endl; t << " text[ACTIVE] = " << color( cg.color(QPalette::Active, QPalette::HighlightedText) ) << endl; t << " text[PRELIGHT] = " << color( cg.color(QPalette::Active, QPalette::HighlightedText) ) << endl; t << endl; t << " fg[NORMAL] = " << color ( cg.color( QPalette::Active, QPalette::WindowText ) ) << endl; t << " fg[SELECTED] = " << color( cg.color(QPalette::Active, QPalette::HighlightedText) ) << endl; t << " fg[INSENSITIVE] = " << color( cg.color( QPalette::Active, QPalette::Mid ) ) << endl; t << " fg[ACTIVE] = " << color( cg.color( QPalette::Active, QPalette::WindowText ) ) << endl; t << " fg[PRELIGHT] = " << color( cg.color( QPalette::Active, QPalette::WindowText ) ) << endl; t << "}" << endl; t << endl; t << "class \"*\" style \"default\"" << endl; t << endl; // tooltips don't have the standard background color t << "style \"ToolTip\"" << endl; t << "{" << endl; t << " bg[NORMAL] = " << color( cg.color( QPalette::ToolTipBase ) ) << endl; t << " base[NORMAL] = " << color( cg.color( QPalette::ToolTipBase ) ) << endl; t << " text[NORMAL] = " << color( cg.color( QPalette::ToolTipText ) ) << endl; t << " fg[NORMAL] = " << color( cg.color( QPalette::ToolTipText ) ) << endl; t << "}" << endl; t << endl; t << "widget \"gtk-tooltip\" style \"ToolTip\"" << endl; t << "widget \"gtk-tooltips\" style \"ToolTip\"" << endl; t << "widget \"gtk-tooltip*\" style \"ToolTip\"" << endl; t << endl; // highlight the current (mouse-hovered) menu-item // not every button, checkbox, etc. t << "style \"MenuItem\"" << endl; t << "{" << endl; t << " bg[PRELIGHT] = " << color( cg.color(QPalette::Highlight) ) << endl; t << " fg[PRELIGHT] = " << color( cg.color(QPalette::HighlightedText) ) << endl; t << "}" << endl; t << endl; t << "class \"*MenuItem\" style \"MenuItem\"" << endl; t << endl; } saveFile.commit(); } // --------------------------------------------------------------------- QString gtkColorsHelper(const QString &name, const QString &color) { return QStringLiteral("@define-color %1 %2;\n").arg(name, color); } +void checkGtkCss() +{ + QFile gtkCss(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/gtk-3.0/gtk.css"); + if (gtkCss.open(QIODevice::ReadWrite)) { + QTextStream gtkStream(>kCss); + bool hasImport = false; + while (!gtkStream.atEnd()) { + QString line = gtkStream.readLine(); + if (line.contains("@import 'colors.css';")) { + hasImport = true; + } + } + if (!hasImport) { + gtkStream << "@import 'colors.css';"; + } + } +} +void exportGtkColors(QList activeColorSchemes, QList inactiveColorSchemes, QList disabledColorSchemes, KConfigGroup groupWMTheme, QTextStream& colorsStream) +{ + /* + Normal (Non Backdrop, Non Insensitive) + */ + + // General Colors + + colorsStream << gtkColorsHelper("theme_fg_color", activeColorSchemes[1].foreground(KColorScheme::NormalText).color().name()); + colorsStream << gtkColorsHelper("theme_bg_color", activeColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("theme_text_color", activeColorSchemes[0].foreground(KColorScheme::NormalText).color().name()); + colorsStream << gtkColorsHelper("theme_base_color", activeColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("theme_view_hover_decoration_color", activeColorSchemes[0].decoration(KColorScheme::HoverColor).color().name()); + colorsStream << gtkColorsHelper("theme_hovering_selected_bg_color", activeColorSchemes[3].decoration(KColorScheme::HoverColor).color().name()); + colorsStream << gtkColorsHelper("theme_selected_bg_color", activeColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("theme_selected_fg_color", activeColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); + colorsStream << gtkColorsHelper("theme_view_active_decoration_color", activeColorSchemes[0].decoration(KColorScheme::HoverColor).color().name()); + + // Button Colors + colorsStream << gtkColorsHelper("theme_button_background_normal", activeColorSchemes[2].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("theme_button_decoration_hover", activeColorSchemes[2].decoration(KColorScheme::HoverColor).color().name()); + colorsStream << gtkColorsHelper("theme_button_decoration_focus", activeColorSchemes[2].decoration(KColorScheme::FocusColor).color().name()); + colorsStream << gtkColorsHelper("theme_button_foreground_normal", activeColorSchemes[2].foreground(KColorScheme::NormalText).color().name()); + colorsStream << gtkColorsHelper("theme_button_foreground_active", activeColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); + + // Misc Colors + QColor windowForegroundColor = activeColorSchemes[1].foreground(KColorScheme::NormalText).color(); + QColor windowBackgroundColor = activeColorSchemes[1].background(KColorScheme::NormalBackground).color(); + QColor bordersColor = KColorUtils::mix(windowBackgroundColor,windowForegroundColor, 0.25); + + colorsStream << gtkColorsHelper("borders", bordersColor.name()); + colorsStream << gtkColorsHelper("warning_color", activeColorSchemes[0].foreground(KColorScheme::NeutralText).color().name()); + colorsStream << gtkColorsHelper("success_color", activeColorSchemes[0].foreground(KColorScheme::PositiveText).color().name()); + colorsStream << gtkColorsHelper("error_color", activeColorSchemes[0].foreground(KColorScheme::NegativeText).color().name()); + + /* + Backdrop (Inactive) + */ + + // General + colorsStream << gtkColorsHelper("theme_unfocused_fg_color",inactiveColorSchemes[1].foreground(KColorScheme::NormalText).color().name()); + colorsStream << gtkColorsHelper("theme_unfocused_text_color", inactiveColorSchemes[0].foreground(KColorScheme::NormalText).color().name()); + colorsStream << gtkColorsHelper("theme_unfocused_bg_color", inactiveColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("theme_unfocused_base_color", inactiveColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("theme_unfocused_selected_bg_color_alt", inactiveColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("theme_unfocused_selected_bg_color", inactiveColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("theme_unfocused_selected_fg_color", inactiveColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); + + // Button + colorsStream << gtkColorsHelper("theme_button_background_normal_backdrop", inactiveColorSchemes[2].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("theme_button_decoration_hover_backdrop", inactiveColorSchemes[2].decoration(KColorScheme::HoverColor).color().name()); + colorsStream << gtkColorsHelper("theme_button_decoration_focus_backdrop", inactiveColorSchemes[2].decoration(KColorScheme::FocusColor).color().name()); + colorsStream << gtkColorsHelper("theme_button_foreground_normal_backdrop", inactiveColorSchemes[2].foreground(KColorScheme::NormalText).color().name()); + colorsStream << gtkColorsHelper("theme_button_foreground_active_backdrop", inactiveColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); + + // Misc Colors + QColor inactiveWindowForegroundColor = inactiveColorSchemes[1].foreground(KColorScheme::NormalText).color(); + QColor inactiveWindowBackgroundColor = inactiveColorSchemes[1].background(KColorScheme::NormalBackground).color(); + QColor inactiveBordersColor = KColorUtils::mix(inactiveWindowBackgroundColor,inactiveWindowForegroundColor, 0.25); + + colorsStream << gtkColorsHelper("unfocused_borders", inactiveBordersColor.name()); + colorsStream << gtkColorsHelper("warning_color_backdrop", inactiveColorSchemes[0].foreground(KColorScheme::NeutralText).color().name()); + colorsStream << gtkColorsHelper("success_color_backdrop", inactiveColorSchemes[0].foreground(KColorScheme::PositiveText).color().name()); + colorsStream << gtkColorsHelper("error_color_backdrop", inactiveColorSchemes[0].foreground(KColorScheme::NegativeText).color().name()); + + /* + Insensitive (Disabled) + */ + + // General + colorsStream << gtkColorsHelper("insensitive_fg_color",disabledColorSchemes[1].foreground(KColorScheme::NormalText).color().name()); + colorsStream << gtkColorsHelper("insensitive_base_fg_color", disabledColorSchemes[0].foreground(KColorScheme::NormalText).color().name()); + colorsStream << gtkColorsHelper("insensitive_bg_color", disabledColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("insensitive_base_color", disabledColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("insensitive_selected_bg_color", disabledColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("insensitive_selected_fg_color", disabledColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); + + // Button + colorsStream << gtkColorsHelper("theme_button_background_normal_insensitive", disabledColorSchemes[2].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("theme_button_decoration_hover_insensitive", disabledColorSchemes[2].decoration(KColorScheme::HoverColor).color().name()); + colorsStream << gtkColorsHelper("theme_button_decoration_focus_insensitive", disabledColorSchemes[2].decoration(KColorScheme::FocusColor).color().name()); + colorsStream << gtkColorsHelper("theme_button_foreground_normal_insensitive", disabledColorSchemes[2].foreground(KColorScheme::NormalText).color().name()); + colorsStream << gtkColorsHelper("theme_button_foreground_active_insensitive", disabledColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); + + // Misc Colors + QColor disabledWindowForegroundColor = disabledColorSchemes[1].foreground(KColorScheme::NormalText).color(); + QColor disabledWindowBackgroundColor = disabledColorSchemes[1].background(KColorScheme::NormalBackground).color(); + QColor disabledBordersColor = KColorUtils::mix(disabledWindowBackgroundColor,disabledWindowForegroundColor, 0.25); + + colorsStream << gtkColorsHelper("insensitive_borders", disabledBordersColor.name()); + colorsStream << gtkColorsHelper("warning_color_insensitive", disabledColorSchemes[0].foreground(KColorScheme::NeutralText).color().name()); + colorsStream << gtkColorsHelper("success_color_insensitive", disabledColorSchemes[0].foreground(KColorScheme::PositiveText).color().name()); + colorsStream << gtkColorsHelper("error_color_insensitive", disabledColorSchemes[0].foreground(KColorScheme::NegativeText).color().name()); + + /* + Insensitive Backdrop (Inactive Disabled) These pretty much have the same appearance as regular inactive colors, but they're seperate in case we decide to make + them different in the future. + */ + + // General + colorsStream << gtkColorsHelper("insensitive_unfocused_fg_color",disabledColorSchemes[1].foreground(KColorScheme::NormalText).color().name()); + colorsStream << gtkColorsHelper("theme_unfocused_view_text_color", disabledColorSchemes[0].foreground(KColorScheme::NormalText).color().name()); + colorsStream << gtkColorsHelper("insensitive_unfocused_bg_color", disabledColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("theme_unfocused_view_bg_color", disabledColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("insensitive_unfocused_selected_bg_color", disabledColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("insensitive_unfocused_selected_fg_color", disabledColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); + + // Button + colorsStream << gtkColorsHelper("theme_button_background_normal_backdrop_insensitive", disabledColorSchemes[2].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("theme_button_decoration_hover_backdrop_insensitive", disabledColorSchemes[2].decoration(KColorScheme::HoverColor).color().name()); + colorsStream << gtkColorsHelper("theme_button_decoration_focus_backdrop_insensitive", disabledColorSchemes[2].decoration(KColorScheme::FocusColor).color().name()); + colorsStream << gtkColorsHelper("theme_button_foreground_normal_backdrop_insensitive", disabledColorSchemes[2].foreground(KColorScheme::NormalText).color().name()); + colorsStream << gtkColorsHelper("theme_button_foreground_active_backdrop_insensitive", disabledColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); + + // Misc Colors + QColor unfocusedDisabledWindowForegroundColor = disabledColorSchemes[1].foreground(KColorScheme::NormalText).color(); + QColor unfocusedDisabledWindowBackgroundColor = disabledColorSchemes[1].background(KColorScheme::NormalBackground).color(); + QColor unfocusedDisabledBordersColor = KColorUtils::mix(unfocusedDisabledWindowBackgroundColor,unfocusedDisabledWindowForegroundColor, 0.25); + + colorsStream << gtkColorsHelper("unfocused_insensitive_borders", unfocusedDisabledBordersColor.name()); + colorsStream << gtkColorsHelper("warning_color_insensitive_backdrop", disabledColorSchemes[0].foreground(KColorScheme::NeutralText).color().name()); + colorsStream << gtkColorsHelper("success_color_insensitive_backdrop", disabledColorSchemes[0].foreground(KColorScheme::PositiveText).color().name()); + colorsStream << gtkColorsHelper("error_color_insensitive_backdrop", disabledColorSchemes[0].foreground(KColorScheme::NegativeText).color().name()); + + /* + Ignorant Colors (These colors do not care about backdrop or insensitive states) + */ + + colorsStream << gtkColorsHelper("link_color", activeColorSchemes[0].foreground(KColorScheme::LinkText).color().name()); + colorsStream << gtkColorsHelper("link_visited_color", activeColorSchemes[0].foreground(KColorScheme::VisitedText).color().name()); + + QColor tooltipForegroundColor = activeColorSchemes[4].foreground(KColorScheme::NormalText).color(); + QColor tooltipBackgroundColor = activeColorSchemes[4].background(KColorScheme::NormalBackground).color(); + QColor tooltipBorderColor = KColorUtils::mix(tooltipBackgroundColor, tooltipForegroundColor, 0.25); + + colorsStream << gtkColorsHelper("tooltip_text", tooltipForegroundColor.name()); + colorsStream << gtkColorsHelper("tooltip_background", tooltipBackgroundColor.name()); + colorsStream << gtkColorsHelper("tooltip_border", tooltipBorderColor.name()); + + colorsStream << gtkColorsHelper("content_view_bg", activeColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); + + // Titlebar colors + colorsStream << gtkColorsHelper("theme_titlebar_background", "rgb(" + groupWMTheme.readEntry("activeBackground", "") + ")"); + colorsStream << gtkColorsHelper("theme_titlebar_foreground", "rgb(" + groupWMTheme.readEntry("activeForeground", "") + ")"); + colorsStream << gtkColorsHelper("theme_titlebar_background_light", activeColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); + colorsStream << gtkColorsHelper("theme_titlebar_foreground_backdrop", "rgb(" + groupWMTheme.readEntry("inactiveForeground", "") + ")"); + colorsStream << gtkColorsHelper("theme_titlebar_background_backdrop", "rgb(" + groupWMTheme.readEntry("inactiveBackground", "") + ")"); + colorsStream << gtkColorsHelper("theme_titlebar_foreground_insensitive", "rgb(" + groupWMTheme.readEntry("inactiveForeground", "") + ")"); + colorsStream << gtkColorsHelper("theme_titlebar_foreground_insensitive_backdrop", "rgb(" + groupWMTheme.readEntry("inactiveForeground", "") + ")"); +} +void saveGtkColors(KSharedConfigPtr& config) +{ + checkGtkCss(); + QFile colorsCss(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/gtk-3.0/colors.css"); + + if (colorsCss.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + QTextStream colorsStream(&colorsCss); + /* + 0 Active View + 1 Active Window + 2 Active Button + 3 Active Selection + 4 Active Tooltip + 5 Active Complimentary + */ + + QList activeColorSchemes{ + KColorScheme(QPalette::Active, KColorScheme::View, config), + KColorScheme(QPalette::Active, KColorScheme::Window, config), + KColorScheme(QPalette::Active, KColorScheme::Button, config), + KColorScheme(QPalette::Active, KColorScheme::Selection, config), + KColorScheme(QPalette::Active, KColorScheme::Tooltip, config), + KColorScheme(QPalette::Active, KColorScheme::Complementary, config) + }; + QList inactiveColorSchemes{ + KColorScheme(QPalette::Inactive, KColorScheme::View, config), + KColorScheme(QPalette::Inactive, KColorScheme::Window, config), + KColorScheme(QPalette::Inactive, KColorScheme::Button, config), + KColorScheme(QPalette::Inactive, KColorScheme::Selection, config), + KColorScheme(QPalette::Inactive, KColorScheme::Tooltip, config), + KColorScheme(QPalette::Inactive, KColorScheme::Complementary, config) + }; + QList disabledColorSchemes{ + KColorScheme(QPalette::Disabled, KColorScheme::View, config), + KColorScheme(QPalette::Disabled, KColorScheme::Window, config), + KColorScheme(QPalette::Disabled, KColorScheme::Button, config), + KColorScheme(QPalette::Disabled, KColorScheme::Selection, config), + KColorScheme(QPalette::Disabled, KColorScheme::Tooltip, config), + KColorScheme(QPalette::Disabled, KColorScheme::Complementary, config) + }; + KConfigGroup groupWMTheme(config, "WM"); + exportGtkColors(activeColorSchemes, inactiveColorSchemes, disabledColorSchemes, groupWMTheme, colorsStream); + } +} void saveGtkColors() { - KConfigGroup g(KSharedConfig::openConfig(), "WM"); - QFile gtkCss(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/gtk-3.0/gtk.css"); + checkGtkCss(); QFile colorsCss(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/gtk-3.0/colors.css"); + KConfigGroup groupWMTheme(KSharedConfig::openConfig(), "WM"); - if (gtkCss.open(QIODevice::ReadWrite)) { - QTextStream gtkStream(>kCss); - bool hasImport = false; - while (!gtkStream.atEnd()) { - QString line = gtkStream.readLine(); - if (line.contains("@import 'colors.css';")) { - hasImport = true; - } - } - if (!hasImport) { - gtkStream << "@import 'colors.css';"; - } - } if (colorsCss.open(QIODevice::WriteOnly | QIODevice::Truncate)) { QTextStream colorsStream(&colorsCss); /* 0 Active View 1 Active Window 2 Active Button 3 Active Selection 4 Active Tooltip 5 Active Complimentary */ QList activeColorSchemes{ KColorScheme(QPalette::Active, KColorScheme::View), KColorScheme(QPalette::Active, KColorScheme::Window), KColorScheme(QPalette::Active, KColorScheme::Button), KColorScheme(QPalette::Active, KColorScheme::Selection), KColorScheme(QPalette::Active, KColorScheme::Tooltip), KColorScheme(QPalette::Active, KColorScheme::Complementary) }; QList inactiveColorSchemes{ KColorScheme(QPalette::Inactive, KColorScheme::View), KColorScheme(QPalette::Inactive, KColorScheme::Window), KColorScheme(QPalette::Inactive, KColorScheme::Button), KColorScheme(QPalette::Inactive, KColorScheme::Selection), KColorScheme(QPalette::Inactive, KColorScheme::Tooltip), KColorScheme(QPalette::Inactive, KColorScheme::Complementary) }; QList disabledColorSchemes{ KColorScheme(QPalette::Disabled, KColorScheme::View), KColorScheme(QPalette::Disabled, KColorScheme::Window), KColorScheme(QPalette::Disabled, KColorScheme::Button), KColorScheme(QPalette::Disabled, KColorScheme::Selection), KColorScheme(QPalette::Disabled, KColorScheme::Tooltip), KColorScheme(QPalette::Disabled, KColorScheme::Complementary) }; - /* - Normal (Non Backdrop, Non Insensitive) - */ - - // General Colors - - colorsStream << gtkColorsHelper("theme_fg_color", activeColorSchemes[1].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_bg_color", activeColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_text_color", activeColorSchemes[0].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_base_color", activeColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_view_hover_decoration_color", activeColorSchemes[0].decoration(KColorScheme::HoverColor).color().name()); - colorsStream << gtkColorsHelper("theme_hovering_selected_bg_color", activeColorSchemes[3].decoration(KColorScheme::HoverColor).color().name()); - colorsStream << gtkColorsHelper("theme_selected_bg_color", activeColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_selected_fg_color", activeColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_view_active_decoration_color", activeColorSchemes[0].decoration(KColorScheme::HoverColor).color().name()); - - // Button Colors - colorsStream << gtkColorsHelper("theme_button_background_normal", activeColorSchemes[2].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_hover", activeColorSchemes[2].decoration(KColorScheme::HoverColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_focus", activeColorSchemes[2].decoration(KColorScheme::FocusColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_normal", activeColorSchemes[2].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_active", activeColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Misc Colors - QColor windowForegroundColor = activeColorSchemes[1].foreground(KColorScheme::NormalText).color(); - QColor windowBackgroundColor = activeColorSchemes[1].background(KColorScheme::NormalBackground).color(); - QColor bordersColor = KColorUtils::mix(windowBackgroundColor,windowForegroundColor, 0.25); - - colorsStream << gtkColorsHelper("borders", bordersColor.name()); - colorsStream << gtkColorsHelper("warning_color", activeColorSchemes[0].foreground(KColorScheme::NeutralText).color().name()); - colorsStream << gtkColorsHelper("success_color", activeColorSchemes[0].foreground(KColorScheme::PositiveText).color().name()); - colorsStream << gtkColorsHelper("error_color", activeColorSchemes[0].foreground(KColorScheme::NegativeText).color().name()); - - /* - Backdrop (Inactive) - */ - - // General - colorsStream << gtkColorsHelper("theme_unfocused_fg_color",inactiveColorSchemes[1].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_text_color", inactiveColorSchemes[0].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_bg_color", inactiveColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_base_color", inactiveColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_selected_bg_color_alt", inactiveColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_selected_bg_color", inactiveColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_selected_fg_color", inactiveColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Button - colorsStream << gtkColorsHelper("theme_button_background_normal_backdrop", inactiveColorSchemes[2].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_hover_backdrop", inactiveColorSchemes[2].decoration(KColorScheme::HoverColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_focus_backdrop", inactiveColorSchemes[2].decoration(KColorScheme::FocusColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_normal_backdrop", inactiveColorSchemes[2].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_active_backdrop", inactiveColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Misc Colors - QColor inactiveWindowForegroundColor = inactiveColorSchemes[1].foreground(KColorScheme::NormalText).color(); - QColor inactiveWindowBackgroundColor = inactiveColorSchemes[1].background(KColorScheme::NormalBackground).color(); - QColor inactiveBordersColor = KColorUtils::mix(inactiveWindowBackgroundColor,inactiveWindowForegroundColor, 0.25); - - colorsStream << gtkColorsHelper("unfocused_borders", inactiveBordersColor.name()); - colorsStream << gtkColorsHelper("warning_color_backdrop", inactiveColorSchemes[0].foreground(KColorScheme::NeutralText).color().name()); - colorsStream << gtkColorsHelper("success_color_backdrop", inactiveColorSchemes[0].foreground(KColorScheme::PositiveText).color().name()); - colorsStream << gtkColorsHelper("error_color_backdrop", inactiveColorSchemes[0].foreground(KColorScheme::NegativeText).color().name()); - - /* - Insensitive (Disabled) - */ - - // General - colorsStream << gtkColorsHelper("insensitive_fg_color",disabledColorSchemes[1].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("insensitive_base_fg_color", disabledColorSchemes[0].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("insensitive_bg_color", disabledColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("insensitive_base_color", disabledColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("insensitive_selected_bg_color", disabledColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("insensitive_selected_fg_color", disabledColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Button - colorsStream << gtkColorsHelper("theme_button_background_normal_insensitive", disabledColorSchemes[2].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_hover_insensitive", disabledColorSchemes[2].decoration(KColorScheme::HoverColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_focus_insensitive", disabledColorSchemes[2].decoration(KColorScheme::FocusColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_normal_insensitive", disabledColorSchemes[2].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_active_insensitive", disabledColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Misc Colors - QColor disabledWindowForegroundColor = disabledColorSchemes[1].foreground(KColorScheme::NormalText).color(); - QColor disabledWindowBackgroundColor = disabledColorSchemes[1].background(KColorScheme::NormalBackground).color(); - QColor disabledBordersColor = KColorUtils::mix(disabledWindowBackgroundColor,disabledWindowForegroundColor, 0.25); - - colorsStream << gtkColorsHelper("insensitive_borders", disabledBordersColor.name()); - colorsStream << gtkColorsHelper("warning_color_insensitive", disabledColorSchemes[0].foreground(KColorScheme::NeutralText).color().name()); - colorsStream << gtkColorsHelper("success_color_insensitive", disabledColorSchemes[0].foreground(KColorScheme::PositiveText).color().name()); - colorsStream << gtkColorsHelper("error_color_insensitive", disabledColorSchemes[0].foreground(KColorScheme::NegativeText).color().name()); - - /* - Insensitive Backdrop (Inactive Disabled) These pretty much have the same appearance as regular inactive colors, but they're seperate in case we decide to make - them different in the future. - */ - - // General - colorsStream << gtkColorsHelper("insensitive_unfocused_fg_color",disabledColorSchemes[1].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_view_text_color", disabledColorSchemes[0].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("insensitive_unfocused_bg_color", disabledColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_unfocused_view_bg_color", disabledColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("insensitive_unfocused_selected_bg_color", disabledColorSchemes[3].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("insensitive_unfocused_selected_fg_color", disabledColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Button - colorsStream << gtkColorsHelper("theme_button_background_normal_backdrop_insensitive", disabledColorSchemes[2].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_hover_backdrop_insensitive", disabledColorSchemes[2].decoration(KColorScheme::HoverColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_decoration_focus_backdrop_insensitive", disabledColorSchemes[2].decoration(KColorScheme::FocusColor).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_normal_backdrop_insensitive", disabledColorSchemes[2].foreground(KColorScheme::NormalText).color().name()); - colorsStream << gtkColorsHelper("theme_button_foreground_active_backdrop_insensitive", disabledColorSchemes[3].foreground(KColorScheme::NormalText).color().name()); - - // Misc Colors - QColor unfocusedDisabledWindowForegroundColor = disabledColorSchemes[1].foreground(KColorScheme::NormalText).color(); - QColor unfocusedDisabledWindowBackgroundColor = disabledColorSchemes[1].background(KColorScheme::NormalBackground).color(); - QColor unfocusedDisabledBordersColor = KColorUtils::mix(unfocusedDisabledWindowBackgroundColor,unfocusedDisabledWindowForegroundColor, 0.25); - - colorsStream << gtkColorsHelper("unfocused_insensitive_borders", unfocusedDisabledBordersColor.name()); - colorsStream << gtkColorsHelper("warning_color_insensitive_backdrop", disabledColorSchemes[0].foreground(KColorScheme::NeutralText).color().name()); - colorsStream << gtkColorsHelper("success_color_insensitive_backdrop", disabledColorSchemes[0].foreground(KColorScheme::PositiveText).color().name()); - colorsStream << gtkColorsHelper("error_color_insensitive_backdrop", disabledColorSchemes[0].foreground(KColorScheme::NegativeText).color().name()); - - /* - Ignorant Colors (These colors do not care about backdrop or insensitive states) - */ - - colorsStream << gtkColorsHelper("link_color", activeColorSchemes[0].foreground(KColorScheme::LinkText).color().name()); - colorsStream << gtkColorsHelper("link_visited_color", activeColorSchemes[0].foreground(KColorScheme::VisitedText).color().name()); - - QColor tooltipForegroundColor = activeColorSchemes[4].foreground(KColorScheme::NormalText).color(); - QColor tooltipBackgroundColor = activeColorSchemes[4].background(KColorScheme::NormalBackground).color(); - QColor tooltipBorderColor = KColorUtils::mix(tooltipBackgroundColor, tooltipForegroundColor, 0.25); - - colorsStream << gtkColorsHelper("tooltip_text", tooltipForegroundColor.name()); - colorsStream << gtkColorsHelper("tooltip_background", tooltipBackgroundColor.name()); - colorsStream << gtkColorsHelper("tooltip_border", tooltipBorderColor.name()); - - colorsStream << gtkColorsHelper("content_view_bg", activeColorSchemes[0].background(KColorScheme::NormalBackground).color().name()); - - /* - Theme titlebar colors - */ - colorsStream << gtkColorsHelper("theme_titlebar_background", "rgb(" + g.readEntry("activeBackground", "") + ")"); - colorsStream << gtkColorsHelper("theme_titlebar_foreground", "rgb(" + g.readEntry("activeForeground", "") + ")"); - colorsStream << gtkColorsHelper("theme_titlebar_background_light", activeColorSchemes[1].background(KColorScheme::NormalBackground).color().name()); - colorsStream << gtkColorsHelper("theme_titlebar_foreground_backdrop", "rgb(" + g.readEntry("inactiveForeground", "") + ")"); - colorsStream << gtkColorsHelper("theme_titlebar_background_backdrop", "rgb(" + g.readEntry("inactiveBackground", "") + ")"); - colorsStream << gtkColorsHelper("theme_titlebar_foreground_insensitive", "rgb(" + g.readEntry("inactiveForeground", "") + ")"); - colorsStream << gtkColorsHelper("theme_titlebar_foreground_insensitive_backdrop", "rgb(" + g.readEntry("inactiveForeground", "") + ")"); + exportGtkColors(activeColorSchemes, inactiveColorSchemes, disabledColorSchemes, groupWMTheme, colorsStream); } } // ----------------------------------------------------------------------------- void runRdb( uint flags ) { // Obtain the application palette that is about to be set. bool exportColors = flags & KRdbExportColors; bool exportQtColors = flags & KRdbExportQtColors; bool exportQtSettings = flags & KRdbExportQtSettings; bool exportXftSettings = flags & KRdbExportXftSettings; bool exportGtkTheme = flags & KRdbExportGtkTheme; bool exportGtkColors = flags & KRdbExportGtkColors; KSharedConfigPtr kglobalcfg = KSharedConfig::openConfig( QStringLiteral("kdeglobals") ); KConfigGroup kglobals(kglobalcfg, "KDE"); QPalette newPal = KColorScheme::createApplicationPalette(kglobalcfg); QTemporaryFile tmpFile; if (!tmpFile.open()) { qDebug() << "Couldn't open temp file"; exit(0); } KConfigGroup generalCfgGroup(kglobalcfg, "General"); QString gtkTheme; if (kglobals.hasKey("widgetStyle")) gtkTheme = kglobals.readEntry("widgetStyle"); else gtkTheme = QStringLiteral("oxygen"); createGtkrc( exportColors, newPal, exportGtkTheme, gtkTheme, 1 ); createGtkrc( exportColors, newPal, exportGtkTheme, gtkTheme, 2 ); // Export colors to non-(KDE/Qt) apps (e.g. Motif, GTK+ apps) if (exportColors) { KConfigGroup g(KSharedConfig::openConfig(), "WM"); QString preproc; QColor backCol = newPal.color( QPalette::Active, QPalette::Window ); addColorDef(preproc, "FOREGROUND" , newPal.color( QPalette::Active, QPalette::WindowText ) ); addColorDef(preproc, "BACKGROUND" , backCol); addColorDef(preproc, "HIGHLIGHT" , backCol.lighter(100+(2*KColorScheme::contrast()+4)*16/1)); addColorDef(preproc, "LOWLIGHT" , backCol.darker(100+(2*KColorScheme::contrast()+4)*10)); addColorDef(preproc, "SELECT_BACKGROUND" , newPal.color( QPalette::Active, QPalette::Highlight)); addColorDef(preproc, "SELECT_FOREGROUND" , newPal.color( QPalette::Active, QPalette::HighlightedText)); addColorDef(preproc, "WINDOW_BACKGROUND" , newPal.color( QPalette::Active, QPalette::Base ) ); addColorDef(preproc, "WINDOW_FOREGROUND" , newPal.color( QPalette::Active, QPalette::Text ) ); addColorDef(preproc, "INACTIVE_BACKGROUND", g.readEntry("inactiveBackground", QColor(224, 223, 222))); addColorDef(preproc, "INACTIVE_FOREGROUND", g.readEntry("inactiveBackground", QColor(224, 223, 222))); addColorDef(preproc, "ACTIVE_BACKGROUND" , g.readEntry("activeBackground", QColor(48, 174, 232))); addColorDef(preproc, "ACTIVE_FOREGROUND" , g.readEntry("activeBackground", QColor(48, 174, 232))); //--------------------------------------------------------------- tmpFile.write( preproc.toLatin1(), preproc.length() ); QStringList list; const QStringList adPaths = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("kdisplay/app-defaults/"), QStandardPaths::LocateDirectory); for (QStringList::ConstIterator it = adPaths.constBegin(); it != adPaths.constEnd(); ++it) { QDir dSys( *it ); if ( dSys.exists() ) { dSys.setFilter( QDir::Files ); dSys.setSorting( QDir::Name ); dSys.setNameFilters(QStringList(QStringLiteral("*.ad"))); list += dSys.entryList(); } } for (QStringList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it) copyFile(tmpFile, QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kdisplay/app-defaults/"+(*it)), true); } // Merge ~/.Xresources or fallback to ~/.Xdefaults QString homeDir = QDir::homePath(); QString xResources = homeDir + "/.Xresources"; // very primitive support for ~/.Xresources by appending it if ( QFile::exists( xResources ) ) copyFile(tmpFile, xResources, true); else copyFile(tmpFile, homeDir + "/.Xdefaults", true); // Export the Xcursor theme & size settings KConfigGroup mousecfg(KSharedConfig::openConfig( QStringLiteral("kcminputrc") ), "Mouse" ); QString theme = mousecfg.readEntry("cursorTheme", QString()); QString size = mousecfg.readEntry("cursorSize", QString()); QString contents; if (!theme.isNull()) contents = "Xcursor.theme: " + theme + '\n'; if (!size.isNull()) contents += "Xcursor.size: " + size + '\n'; if (exportXftSettings) { contents += QLatin1String("Xft.antialias: "); if(generalCfgGroup.readEntry("XftAntialias", true)) contents += QLatin1String("1\n"); else contents += QLatin1String("0\n"); QString hintStyle = generalCfgGroup.readEntry("XftHintStyle", "hintslight"); contents += QLatin1String("Xft.hinting: "); if(hintStyle.isEmpty()) contents += QLatin1String("-1\n"); else { if(hintStyle!=QLatin1String("hintnone")) contents += QLatin1String("1\n"); else contents += QLatin1String("0\n"); contents += "Xft.hintstyle: " + hintStyle + '\n'; } QString subPixel = generalCfgGroup.readEntry("XftSubPixel", "rgb"); if(!subPixel.isEmpty()) contents += "Xft.rgba: " + subPixel + '\n'; KConfig _cfgfonts( QStringLiteral("kcmfonts") ); KConfigGroup cfgfonts(&_cfgfonts, "General"); int dpi; //even though this sets up the X rdb, we want to use the value the //user has set to use when under wayland - as X apps will be scaled by the compositor if (KWindowSystem::isPlatformWayland()) { dpi = cfgfonts.readEntry( "forceFontDPIWayland", 0); if (dpi == 0) { //with wayland we want xwayland to run at 96 dpi (unless set otherwise) as we have wayland scaling on top dpi = 96; } } else { dpi = cfgfonts.readEntry( "forceFontDPI", 0); } if( dpi != 0 ) contents += "Xft.dpi: " + QString::number(dpi) + '\n'; else { KProcess proc; proc << QStringLiteral("xrdb") << QStringLiteral("-quiet") << QStringLiteral("-remove") << QStringLiteral("-nocpp"); proc.start(); if (proc.waitForStarted()) { proc.write( QByteArray( "Xft.dpi\n" ) ); proc.closeWriteChannel(); proc.waitForFinished(); } } } if (contents.length() > 0) tmpFile.write( contents.toLatin1(), contents.length() ); tmpFile.flush(); KProcess proc; #ifndef NDEBUG proc << QStringLiteral("xrdb") << QStringLiteral("-merge") << tmpFile.fileName(); #else proc << "xrdb" << "-quiet" << "-merge" << tmpFile.fileName(); #endif proc.execute(); applyGtkStyles(exportColors, 1); applyGtkStyles(exportColors, 2); /* Qt exports */ if ( exportQtColors || exportQtSettings ) { QSettings* settings = new QSettings(QStringLiteral("Trolltech")); if ( exportQtColors ) applyQtColors( kglobalcfg, *settings, newPal ); // For kcmcolors if ( exportQtSettings ) applyQtSettings( kglobalcfg, *settings ); // For kcmstyle delete settings; QApplication::flush(); #if HAVE_X11 if (qApp->platformName() == QStringLiteral("xcb")) { // We let KIPC take care of ourselves, as we are in a KDE app with // QApp::setDesktopSettingsAware(false); // Instead of calling QApp::x11_apply_settings() directly, we instead // modify the timestamp which propagates the settings changes onto // Qt-only apps without adversely affecting ourselves. // Cheat and use the current timestamp, since we just saved to qtrc. QDateTime settingsstamp = QDateTime::currentDateTime(); static Atom qt_settings_timestamp = 0; if (!qt_settings_timestamp) { QString atomname(QStringLiteral("_QT_SETTINGS_TIMESTAMP_")); atomname += XDisplayName( nullptr ); // Use the $DISPLAY envvar. qt_settings_timestamp = XInternAtom( QX11Info::display(), atomname.toLatin1(), False); } QBuffer stamp; QDataStream s(&stamp.buffer(), QIODevice::WriteOnly); s << settingsstamp; XChangeProperty( QX11Info::display(), QX11Info::appRootWindow(), qt_settings_timestamp, qt_settings_timestamp, 8, PropModeReplace, (unsigned char*) stamp.buffer().data(), stamp.buffer().size() ); QApplication::flush(); } #endif } //Legacy support: //Try to sync kde4 settings with ours Kdelibs4Migration migration; //kf5 congig groups for general and icons KConfigGroup generalGroup(kglobalcfg, "General"); KConfigGroup iconsGroup(kglobalcfg, "Icons"); const QString colorSchemeName = generalGroup.readEntry("ColorScheme", QString()); //if no valid color scheme saved, something weird is going on, abort if (colorSchemeName.isEmpty()) { return; } QString colorSchemeSrcFile; if (colorSchemeName != QLatin1String("Default")) { //fix filename, copied from ColorsCM::saveScheme() QString colorSchemeFilename = colorSchemeName; colorSchemeFilename.remove('\''); // So Foo's does not become FooS QRegExp fixer(QStringLiteral("[\\W,.-]+(.?)")); int offset; while ((offset = fixer.indexIn(colorSchemeFilename)) >= 0) colorSchemeFilename.replace(offset, fixer.matchedLength(), fixer.cap(1).toUpper()); colorSchemeFilename.replace(0, 1, colorSchemeFilename.at(0).toUpper()); //clone the color scheme colorSchemeSrcFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "color-schemes/" + colorSchemeFilename + ".colors"); const QString dest = migration.saveLocation("data", QStringLiteral("color-schemes")) + colorSchemeName + ".colors"; QFile::remove(dest); QFile::copy(colorSchemeSrcFile, dest); } //Apply the color scheme QString configFilePath = migration.saveLocation("config") + "kdeglobals"; if (configFilePath.isEmpty()) { return; } KConfig kde4config(configFilePath, KConfig::SimpleConfig); KConfigGroup kde4generalGroup(&kde4config, "General"); kde4generalGroup.writeEntry("ColorScheme", colorSchemeName); //fonts QString font = generalGroup.readEntry("font", QString()); if (!font.isEmpty()) { kde4generalGroup.writeEntry("font", font); } font = generalGroup.readEntry("desktopFont", QString()); if (!font.isEmpty()) { kde4generalGroup.writeEntry("desktopFont", font); } font = generalGroup.readEntry("menuFont", QString()); if (!font.isEmpty()) { kde4generalGroup.writeEntry("menuFont", font); } font = generalGroup.readEntry("smallestReadableFont", QString()); if (!font.isEmpty()) { kde4generalGroup.writeEntry("smallestReadableFont", font); } font = generalGroup.readEntry("taskbarFont", QString()); if (!font.isEmpty()) { kde4generalGroup.writeEntry("taskbarFont", font); } font = generalGroup.readEntry("toolBarFont", QString()); if (!font.isEmpty()) { kde4generalGroup.writeEntry("toolBarFont", font); } //TODO: does exist any way to check if a qt4 widget style is present from a qt5 app? //kde4generalGroup.writeEntry("widgetStyle", "qtcurve"); kde4generalGroup.sync(); KConfigGroup kde4IconGroup(&kde4config, "Icons"); QString iconTheme = iconsGroup.readEntry("Theme", QString()); if (!iconTheme.isEmpty()) { kde4IconGroup.writeEntry("Theme", iconTheme); } kde4IconGroup.sync(); if (!colorSchemeSrcFile.isEmpty()) { //copy all the groups in the color scheme in kdeglobals KSharedConfigPtr kde4ColorConfig = KSharedConfig::openConfig(colorSchemeSrcFile, KConfig::SimpleConfig); foreach (const QString &grp, kde4ColorConfig->groupList()) { KConfigGroup cg(kde4ColorConfig, grp); KConfigGroup cg2(&kde4config, grp); cg.copyTo(&cg2); } } //widgets settings KConfigGroup kglobals4(&kde4config, "KDE"); kglobals4.writeEntry("ShowIconsInMenuItems", kglobals.readEntry("ShowIconsInMenuItems", true)); kglobals4.writeEntry("ShowIconsOnPushButtons", kglobals.readEntry("ShowIconsOnPushButtons", true)); kglobals4.writeEntry("contrast", kglobals.readEntry("contrast", 4)); //FIXME: this should somehow check if the kde4 version of the style is installed kde4generalGroup.writeEntry("widgetStyle", kglobals.readEntry("widgetStyle", "breeze")); //toolbar style KConfigGroup toolbars4(&kde4config, "Toolbar style"); KConfigGroup toolbars5(kglobalcfg, "Toolbar style"); toolbars4.writeEntry("ToolButtonStyle", toolbars5.readEntry("ToolButtonStyle", "TextBesideIcon")); toolbars4.writeEntry("ToolButtonStyleOtherToolbars", toolbars5.readEntry("ToolButtonStyleOtherToolbars", "TextBesideIcon")); - saveGtkColors(); + if (exportGtkColors) { + saveGtkColors(); + } } \ No newline at end of file diff --git a/kcms/krdb/krdb.h b/kcms/krdb/krdb.h index 1388fd18b..7e290adb4 100644 --- a/kcms/krdb/krdb.h +++ b/kcms/krdb/krdb.h @@ -1,35 +1,38 @@ /* This file is part of the KDE base distribution Copyright (c) 2001 Waldo Bastian This library 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 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. */ #ifndef _KRDB_H_ #define _KRDB_H_ +#include enum KRdbAction { KRdbExportColors = 0x0001, // Export colors to non-(KDE/Qt) apps KRdbExportQtColors = 0x0002, // Export KDE's colors to qtrc KRdbExportQtSettings = 0x0004, // Export all possible qtrc settings, excluding colors KRdbExportXftSettings = 0x0008, // Export KDE's Xft (anti-alias) settings KRdbExportGtkTheme = 0x0010, // Export KDE's widget style to Gtk if possible - KRdbExportGtkColors = 0x0012 // Export KDE's colors to Gtk if possible + KRdbExportGtkColors = 0x0020 // Export KDE's colors to Gtk if possible }; void runRdb( uint flags ); +void saveGtkColors(); +void saveGtkColors(KSharedConfigPtr& config); #endif diff --git a/kcms/style/kcmstyle.cpp b/kcms/style/kcmstyle.cpp index 03739ad5d..fd8d1c6b8 100644 --- a/kcms/style/kcmstyle.cpp +++ b/kcms/style/kcmstyle.cpp @@ -1,716 +1,716 @@ /* * KCMStyle * Copyright (C) 2002 Karol Szwed * Copyright (C) 2002 Daniel Molkentin * Copyright (C) 2007 Urs Wolfer * Copyright (C) 2009 by Davide Bettio * 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" #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) #include #endif #include "styleconfdialog.h" #include "ui_stylepreview.h" #include "ui_styleconfig.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) #include #endif #include "../krdb/krdb.h" #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) #include #endif // X11 namespace cleanup #undef Bool #undef Below #undef KeyPress #undef KeyRelease /**** DLL Interface for kcontrol ****/ #include #include #include K_PLUGIN_FACTORY(KCMStyleFactory, registerPlugin();) K_EXPORT_PLUGIN(KCMStyleFactory("kcmstyle")) extern "C" { Q_DECL_EXPORT void kcminit_style() { - uint flags = KRdbExportQtSettings | KRdbExportQtColors | KRdbExportXftSettings | KRdbExportGtkTheme; + 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 ); } } class StylePreview : public QWidget, public Ui::StylePreview { public: StylePreview(QWidget *parent = nullptr) : QWidget(parent) { setupUi(this); // Ensure that the user can't toy with the child widgets. // Method borrowed from Qt's qtconfig. QList widgets = findChildren(); foreach (QWidget* widget, widgets) { widget->installEventFilter(this); widget->setFocusPolicy(Qt::NoFocus); } } bool eventFilter( QObject* /* obj */, QEvent* ev ) override { switch( ev->type() ) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::MouseMove: case QEvent::KeyPress: case QEvent::KeyRelease: case QEvent::Enter: case QEvent::Leave: case QEvent::Wheel: case QEvent::ContextMenu: return true; // ignore default: break; } return false; } }; class StyleConfig : public QWidget, public Ui::StyleConfig { public: StyleConfig(QWidget *parent = nullptr) : QWidget(parent) { setupUi(this); } }; QString KCMStyle::defaultStyle() { #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) return QStringLiteral("breeze"); #else return QString(); // native style #endif } KCMStyle::KCMStyle( QWidget* parent, const QVariantList& ) : KCModule( parent ), appliedStyle(nullptr) { setQuickHelp( i18n("This module allows you to modify the visual appearance " "of applications' user interface elements.")); m_bStyleDirty= false; m_bEffectsDirty = false; KGlobal::dirs()->addResourceType("themes", "data", "kstyle/themes"); KAboutData *about = new KAboutData( QStringLiteral("kcmstyle"), i18n("Application Style"), QStringLiteral("1.0"), QString(), KAboutLicense::GPL, i18n("(c) 2002 Karol Szwed, Daniel Molkentin")); about->addAuthor(i18n("Karol Szwed"), QString(), QStringLiteral("gallium@kde.org")); about->addAuthor(i18n("Daniel Molkentin"), QString(), QStringLiteral("molkentin@kde.org")); setAboutData( about ); // Setup mainLayout mainLayout = new QVBoxLayout( this ); mainLayout->setContentsMargins(0, 0, 0, 0); styleConfig = new StyleConfig(); QHBoxLayout *previewLayout = new QHBoxLayout(); QGroupBox *gbPreview = new QGroupBox( i18n( "Preview" ) ); QHBoxLayout *previewLayoutInner = new QHBoxLayout(gbPreview); previewLayout->setContentsMargins(0, 0, 0, 0); previewLayoutInner->setContentsMargins(0, 0, 0, 0); previewLayout->addStretch(); previewLayout->addWidget( gbPreview ); previewLayout->addStretch(); stylePreview = new StylePreview( gbPreview ); previewLayoutInner->addWidget( stylePreview ); mainLayout->addWidget( styleConfig ); mainLayout->addLayout( previewLayout ); mainLayout->addStretch(); connect( styleConfig->comboStyle, SIGNAL(activated(int)), this, SLOT(styleChanged()) ); connect( styleConfig->comboStyle, SIGNAL(activated(int)), this, SLOT(updateConfigButton()) ); connect( styleConfig->pbConfigStyle, &QAbstractButton::clicked, this, &KCMStyle::styleSpecificConfig ); connect( styleConfig->comboStyle, SIGNAL(activated(int)), this, SLOT(setStyleDirty()) ); connect( styleConfig->cbIconsOnButtons, &QAbstractButton::toggled, this, &KCMStyle::setEffectsDirty ); connect( styleConfig->cbIconsInMenus, &QAbstractButton::toggled, this, &KCMStyle::setEffectsDirty ); connect( styleConfig->comboToolbarIcons, SIGNAL(activated(int)), this, SLOT(setEffectsDirty()) ); connect( styleConfig->comboSecondaryToolbarIcons, SIGNAL(activated(int)), this, SLOT(setEffectsDirty()) ); addWhatsThis(); } KCMStyle::~KCMStyle() { qDeleteAll(styleEntries); delete appliedStyle; } void KCMStyle::updateConfigButton() { if (!styleEntries[currentStyle()] || styleEntries[currentStyle()]->configPage.isEmpty()) { styleConfig->pbConfigStyle->setEnabled(false); return; } // We don't check whether it's loadable here - // lets us report an error and not waste time // loading things if the user doesn't click the button styleConfig->pbConfigStyle->setEnabled( true ); } void KCMStyle::styleSpecificConfig() { QString libname = styleEntries[currentStyle()]->configPage; KLibrary library(libname); if (!library.load()) { KMessageBox::detailedError(this, i18n("There was an error loading the configuration dialog for this style."), library.errorString(), i18n("Unable to Load Dialog")); return; } KLibrary::void_function_ptr allocPtr = library.resolveFunction("allocate_kstyle_config"); if (!allocPtr) { KMessageBox::detailedError(this, i18n("There was an error loading the configuration dialog for this style."), library.errorString(), i18n("Unable to Load Dialog")); return; } //Create the container dialog StyleConfigDialog* dial = new StyleConfigDialog(this, styleEntries[currentStyle()]->name); 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( dial ); //Insert it in... dial->setMainWidget( pluginConfig ); //..and connect it to the wrapper connect(pluginConfig, SIGNAL(changed(bool)), dial, SLOT(setDirty(bool))); connect(dial, SIGNAL(defaults()), pluginConfig, SLOT(defaults())); connect(dial, SIGNAL(save()), pluginConfig, SLOT(save())); if (dial->exec() == QDialog::Accepted && dial->isDirty() ) { // Force re-rendering of the preview, to apply settings switchStyle(currentStyle(), true); //For now, ask all KDE apps to recreate their styles to apply the setitngs KGlobalSettings::self()->emitChange(KGlobalSettings::StyleChanged); // We call setStyleDirty here to make sure we force style re-creation setStyleDirty(); } delete dial; } void KCMStyle::changeEvent( QEvent *event ) { KCModule::changeEvent( event ); if ( event->type() == QEvent::PaletteChange ) { // Force re-rendering of the preview, to apply new palette switchStyle(currentStyle(), true); } } void KCMStyle::load() { KConfig config( QStringLiteral("kdeglobals"), KConfig::FullConfig ); loadStyle( config ); loadEffects( config ); m_bStyleDirty= false; m_bEffectsDirty = false; //Enable/disable the button for the initial style updateConfigButton(); emit changed( false ); } void KCMStyle::save() { // Don't do anything if we don't need to. if ( !(m_bStyleDirty | m_bEffectsDirty ) ) return; // Save effects. KConfig _config(QStringLiteral("kdeglobals"), KConfig::NoGlobals); KConfigGroup config(&_config, "KDE"); // Effects page config.writeEntry( "ShowIconsOnPushButtons", styleConfig->cbIconsOnButtons->isChecked()); config.writeEntry( "ShowIconsInMenuItems", styleConfig->cbIconsInMenus->isChecked()); config.writeEntry("widgetStyle", currentStyle()); KConfigGroup toolbarStyleGroup(&_config, "Toolbar style"); toolbarStyleGroup.writeEntry("ToolButtonStyle", toolbarButtonText(styleConfig->comboToolbarIcons->currentIndex())); toolbarStyleGroup.writeEntry("ToolButtonStyleOtherToolbars", toolbarButtonText(styleConfig->comboSecondaryToolbarIcons->currentIndex())); _config.sync(); // 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_bStyleDirty || m_bEffectsDirty) // Export only if necessary { 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 ( m_bStyleDirty ) KGlobalSettings::self()->emitChange(KGlobalSettings::StyleChanged); if ( m_bEffectsDirty ) { 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); #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) // Send signal to all kwin instances QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KWin"), QStringLiteral("org.kde.KWin"), QStringLiteral("reloadConfig")); QDBusConnection::sessionBus().send(message); #endif } // Clean up m_bStyleDirty = false; m_bEffectsDirty = false; emit changed( false ); } bool KCMStyle::findStyle( const QString& str, int& combobox_item ) { StyleEntry* se = styleEntries[str.toLower()]; QString name = se ? se->name : str; combobox_item = 0; //look up name for( int i = 0; i < styleConfig->comboStyle->count(); i++ ) { if ( styleConfig->comboStyle->itemText(i) == name ) { combobox_item = i; return true; } } return false; } void KCMStyle::defaults() { // Select default style int item = 0; bool found; found = findStyle( defaultStyle(), item ); if (!found) found = findStyle( QStringLiteral("oxygen"), item ); if (!found) found = findStyle( QStringLiteral("plastique"), item ); if (!found) found = findStyle( QStringLiteral("windows"), item ); if (!found) found = findStyle( QStringLiteral("platinum"), item ); if (!found) found = findStyle( QStringLiteral("motif"), item ); styleConfig->comboStyle->setCurrentIndex( item ); m_bStyleDirty = true; switchStyle( currentStyle() ); // make resets visible // Effects styleConfig->comboToolbarIcons->setCurrentIndex(toolbarButtonIndex(QStringLiteral("TextBesideIcon"))); styleConfig->comboSecondaryToolbarIcons->setCurrentIndex(toolbarButtonIndex(QStringLiteral("TextBesideIcon"))); styleConfig->cbIconsOnButtons->setChecked(true); styleConfig->cbIconsInMenus->setChecked(true); emit changed(true); emit updateConfigButton(); } void KCMStyle::setEffectsDirty() { m_bEffectsDirty = true; emit changed(true); } void KCMStyle::setStyleDirty() { m_bStyleDirty = true; emit changed(true); } // ---------------------------------------------------------------- // All the Style Switching / Preview stuff // ---------------------------------------------------------------- void KCMStyle::loadStyle( KConfig& config ) { styleConfig->comboStyle->clear(); // Create a dictionary of WidgetStyle to Name and Desc. mappings, // as well as the config page info qDeleteAll(styleEntries); styleEntries.clear(); QString strWidgetStyle; QStringList list = KGlobal::dirs()->findAllResources("themes", QStringLiteral("*.themerc"), KStandardDirs::Recursive | KStandardDirs::NoDuplicates); for (QStringList::iterator it = list.begin(); it != list.end(); ++it) { KConfig config( *it, KConfig::SimpleConfig); if ( !(config.hasGroup("KDE") && config.hasGroup("Misc")) ) continue; KConfigGroup configGroup = config.group("KDE"); strWidgetStyle = configGroup.readEntry("WidgetStyle"); if (strWidgetStyle.isNull()) continue; // We have a widgetstyle, so lets read the i18n entries for it... StyleEntry* entry = new StyleEntry; configGroup = config.group("Misc"); entry->name = configGroup.readEntry("Name"); entry->desc = configGroup.readEntry("Comment", i18n("No description available.")); entry->configPage = configGroup.readEntry("ConfigPage", QString()); // Check if this style should be shown configGroup = config.group("Desktop Entry"); entry->hidden = configGroup.readEntry("Hidden", false); // Insert the entry into our dictionary. styleEntries.insert(strWidgetStyle.toLower(), entry); } // Obtain all style names QStringList allStyles = QStyleFactory::keys(); // Get translated names, remove all hidden style entries. QStringList styles; StyleEntry* entry; for (QStringList::iterator it = allStyles.begin(); it != allStyles.end(); ++it) { QString id = (*it).toLower(); // Find the entry. if ( (entry = styleEntries[id]) != nullptr ) { // Do not add hidden entries if (entry->hidden) continue; styles += entry->name; nameToStyleKey[entry->name] = id; } else { styles += (*it); //Fall back to the key (but in original case) nameToStyleKey[*it] = id; } } // Sort the style list, and add it to the combobox styles.sort(); styleConfig->comboStyle->addItems( styles ); // Find out which style is currently being used KConfigGroup configGroup = config.group( "KDE" ); QString defaultStyle = KCMStyle::defaultStyle(); QString cfgStyle = configGroup.readEntry( "widgetStyle", defaultStyle ); // Select the current style // Do not use comboStyle->listBox() as this may be NULL for some styles when // they use QPopupMenus for the drop-down list! // ##### Since Trolltech likes to seemingly copy & paste code, // QStringList::findItem() doesn't have a Qt::StringComparisonMode field. // We roll our own (yuck) cfgStyle = cfgStyle.toLower(); int item = 0; for( int i = 0; i < styleConfig->comboStyle->count(); i++ ) { QString id = nameToStyleKey[styleConfig->comboStyle->itemText(i)]; item = i; if ( id == cfgStyle ) // ExactMatch break; else if ( id.contains( cfgStyle ) ) break; else if ( id.contains( QApplication::style()->metaObject()->className() ) ) break; item = 0; } styleConfig->comboStyle->setCurrentIndex( item ); m_bStyleDirty = false; switchStyle( currentStyle() ); // make resets visible } QString KCMStyle::currentStyle() { return nameToStyleKey[styleConfig->comboStyle->currentText()]; } void KCMStyle::styleChanged() { switchStyle( currentStyle() ); } void KCMStyle::switchStyle(const QString& styleName, bool force) { // Don't flicker the preview if the same style is chosen in the cb if (!force && appliedStyle && appliedStyle->objectName() == styleName) return; // Create an instance of the new style... QStyle* style = QStyleFactory::create(styleName); if (!style) return; // Prevent Qt from wrongly caching radio button images QPixmapCache::clear(); setStyleRecursive( stylePreview, style ); // this flickers, but reliably draws the widgets correctly. stylePreview->resize( stylePreview->sizeHint() ); delete appliedStyle; appliedStyle = style; } void KCMStyle::setStyleRecursive(QWidget* w, QStyle* s) { // Don't let broken styles kill the palette // for other styles being previewed. (e.g SGI style) w->setPalette(QPalette()); QPalette newPalette(KGlobalSettings::createApplicationPalette()); s->polish( newPalette ); w->setPalette(newPalette); // Apply the new style. w->setStyle(s); // Recursively update all children. const QObjectList children = w->children(); // Apply the style to each child widget. foreach (QObject* child, children) { if (child->isWidgetType()) setStyleRecursive((QWidget *) child, s); } } // ---------------------------------------------------------------- // All the Effects stuff // ---------------------------------------------------------------- QString KCMStyle::toolbarButtonText(int index) { switch (index) { case 1: return QStringLiteral("TextOnly"); case 2: return QStringLiteral("TextBesideIcon"); case 3: return QStringLiteral("TextUnderIcon"); default: break; } return QStringLiteral("NoText"); } int KCMStyle::toolbarButtonIndex(const QString &text) { if (text == QLatin1String("TextOnly")) { return 1; } else if (text == QLatin1String("TextBesideIcon")) { return 2; } else if (text == QLatin1String("TextUnderIcon")) { return 3; } return 0; } QString KCMStyle::menuBarStyleText(int index) { switch (index) { case 1: return QStringLiteral("Decoration"); case 2: return QStringLiteral("Widget"); } return QStringLiteral("InApplication"); } int KCMStyle::menuBarStyleIndex(const QString &text) { if (text == QLatin1String("Decoration")) { return 1; } else if (text == QLatin1String("Widget")) { return 2; } return 0; } void KCMStyle::loadEffects( KConfig& config ) { // KDE's Part via KConfig KConfigGroup configGroup = config.group("Toolbar style"); QString tbIcon = configGroup.readEntry("ToolButtonStyle", "TextBesideIcon"); styleConfig->comboToolbarIcons->setCurrentIndex(toolbarButtonIndex(tbIcon)); tbIcon = configGroup.readEntry("ToolButtonStyleOtherToolbars", "TextBesideIcon"); styleConfig->comboSecondaryToolbarIcons->setCurrentIndex(toolbarButtonIndex(tbIcon)); configGroup = config.group("KDE"); styleConfig->cbIconsOnButtons->setChecked(configGroup.readEntry("ShowIconsOnPushButtons", true)); styleConfig->cbIconsInMenus->setChecked(configGroup.readEntry("ShowIconsInMenuItems", true)); m_bEffectsDirty = false; } void KCMStyle::addWhatsThis() { stylePreview->setWhatsThis( i18n("This area shows a preview of the currently selected style " "without having to apply it to the whole desktop.") ); styleConfig->comboStyle->setWhatsThis( i18n("Here you can choose from a list of" " predefined widget styles (e.g. the way buttons are drawn) which" " may or may not be combined with a theme (additional information" " like a marble texture or a gradient).") ); styleConfig->cbIconsOnButtons->setWhatsThis( i18n( "If you enable this option, applications will " "show small icons alongside some important buttons.") ); styleConfig->cbIconsInMenus->setWhatsThis( i18n( "If you enable this option, applications will " "show small icons alongside most menu items.") ); styleConfig->comboToolbarIcons->setWhatsThis( i18n( "

No text: Shows only icons on toolbar buttons. " "Best option for low resolutions.

" "

Text only: Shows only text on toolbar buttons.

" "

Text beside icons: Shows icons and text on toolbar buttons. " "Text is aligned beside the icon.

" "Text below icons: Shows icons and text on toolbar buttons. " "Text is aligned below the icon.") ); } #include "kcmstyle.moc" // vim: set noet ts=4: