Commit 9323a96a authored by Mikhail Zolotukhin's avatar Mikhail Zolotukhin
Browse files

Provide an unified interface for setting GTK theme

GTK configuration in Plasma depends on xsettings daemon, that has no
separation between GTK2 and GTK3 theme, therefore separate themes for
GTK2 and GTK3 are impossible, while this daemon is working. The daemon
itself provides the functionality to apply settings to GTK applications
without restarting them.

The functionality to apply different themes to applications, depending on
the framework version isn't necessary, when 99% of the themes are
compatible with both versions and when most of the applications are
using the last GTK version anyway.

Given all that, I think, that a theme selection must be narrowed to one
and only one theme for both versions of the GTK framework.

CCBUG: 423141
parent 8359e316
......@@ -39,7 +39,6 @@ set_package_properties(XSettingsd PROPERTIES
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake kded/config.h)
add_subdirectory(gtkproxies)
add_subdirectory(gtk3proxies)
add_subdirectory(kded)
add_subdirectory(kconf_update)
......
add_executable(reload_gtk_apps reload.c)
target_link_libraries(reload_gtk_apps PkgConfig::GTK+2)
install(TARGETS reload_gtk_apps RUNTIME DESTINATION "${LIBEXEC_INSTALL_DIR}")
add_executable(gtk_preview preview.c)
target_compile_definitions(gtk_preview PRIVATE "-DDATA_DIR=\"${KDE_INSTALL_FULL_DATADIR}/kcm-gtk-module/\"")
target_link_libraries(gtk_preview PkgConfig::GTK+2)
install(TARGETS gtk_preview RUNTIME DESTINATION "${LIBEXEC_INSTALL_DIR}")
# preview file used for the gtk3 version too
install(FILES preview.ui
DESTINATION ${DATA_INSTALL_DIR}/kcm-gtk-module/)
/*
* Copyright 2011 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
* #include <gtk/gtk.h>
*/
#include <gtk/gtk.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
static void on_dlg_response(GtkDialog* dlg, int res, gpointer user_data)
{
switch(res)
{
default:
gtk_main_quit();
}
}
void reloadstyle(GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
{
if(event_type!=G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
return;
fprintf(stderr, "changing settings... %d\n", event_type);
gtk_rc_reparse_all();
fprintf(stderr, "settings changed!!\n");
}
void printHelp()
{
printf(
"Small utility for previewing Gtk2 theme.\n"
"\n"
"Using:\n"
"gtk_preview <args>\n"
"\n"
"Arguments:\n"
" -h, --help\tShows this help\n"
" -V, --version\tPrints the program version\n"
" <winid>\t Creates a window that can be embedded using XEmbed\n"
);
}
int main(int argc, char **argv)
{
GError *error = NULL;
unsigned long wid=0;
gtk_init( &argc, &argv );
int i;
for(i=0; i<argc; i++) {
if(strcmp("-h", argv[i])==0 || strcmp("--help", argv[i])==0) {
printHelp();
return 0;
}
else if(strcmp("-V", argv[i])==0 || strcmp("--version", argv[i])==0) {
printf("gtk_preview version 1.0\n");
return 0;
} else if(argc>1)
sscanf(argv[1], "%ld", &wid);
}
const char* ui_file = DATA_DIR "/preview.ui";
GtkBuilder *builder = gtk_builder_new();
if( ! gtk_builder_add_from_file( builder, ui_file, &error ) ) {
g_warning( "%s", error->message );
g_object_unref( error );
return 1;
}
GtkWidget *previewUI = GTK_WIDGET( gtk_builder_get_object( builder, "frame1" ) );
gtk_builder_connect_signals( builder, NULL );
/* a plug when embedded, a window when a window */
GtkWidget* window;
if(wid==0) {
window = gtk_dialog_new();
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (window)->vbox), previewUI);
g_signal_connect(window, "response", G_CALLBACK(on_dlg_response), NULL);
} else {
window = gtk_plug_new(wid);
gtk_container_add (GTK_CONTAINER (window), previewUI);
}
GdkColor black = {0, 0, 0, 0};
gtk_widget_modify_bg(previewUI, GTK_STATE_NORMAL, &black);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_widget_destroyed),
&window);
gtk_widget_show_all ( window );
g_object_unref( G_OBJECT( builder ) );
if(wid)
fprintf(stderr, "--- is embedded: %d\n", gtk_plug_get_embedded(GTK_PLUG(window)));
gchar** files = gtk_rc_get_default_files();
GFile* file = g_file_new_for_path(files[0]);
GFileMonitor* monitor = g_file_monitor_file(file, G_FILE_MONITOR_NONE, NULL, NULL);
g_signal_connect (monitor, "changed",
G_CALLBACK (reloadstyle), NULL);
gtk_main();
return 0;
}
This diff is collapsed.
/*
* Copyright 2011 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
*
* 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 <http://www.gnu.org/licenses/>.
*
* #include <gtk/gtk.h>
*/
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include <stdio.h>
#include <string.h>
void printHelp()
{
printf(
"Small utility for sending signal to reload theme in Gtk programs.\n"
"\n"
"Using:\n"
"reload_gtk_apps <args>\n"
"\n"
"Arguments:\n"
" -h, --help\tShows this help\n"
" -V, --version\tPrints the program version\n"
);
}
GdkEventClient createEvent()
{
GdkEventClient event;
event.type = GDK_CLIENT_EVENT;
event.send_event = TRUE;
event.window = NULL;
event.message_type = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
event.data_format = 8;
return event;
}
int main(int argc, char** argv)
{
gtk_init(&argc, &argv);
int i;
for(i=0; i<argc; i++) {
if(strcmp("-h", argv[i])==0 || strcmp("--help", argv[i])==0) {
printHelp();
return 0;
}
else if(strcmp("-V", argv[i])==0 || strcmp("--version", argv[i])==0) {
printf("reload_gtk_apps version 1.0\n");
return 0;
}
}
GdkEventClient event = createEvent();
gdk_event_send_clientmessage_toall((GdkEvent *)&event);
return 0;
}
......@@ -18,11 +18,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QDir>
#include <QString>
#include <QVariant>
#include <QRegularExpression>
#include "configeditor.h"
QString gtk2Theme();
void upgradeGtk2Theme();
void upgradeGtk3Theme();
......@@ -33,7 +36,7 @@ int main() {
}
void upgradeGtk2Theme() {
QString currentGtk2Theme = ConfigEditor::gtk2ConfigValue(QStringLiteral("gtk-theme-name"));
QString currentGtk2Theme = gtk2Theme();
if (currentGtk2Theme.isEmpty()
|| currentGtk2Theme == QStringLiteral("oxygen-gtk")
|| currentGtk2Theme == QStringLiteral("BreezyGTK")
......@@ -55,3 +58,20 @@ void upgradeGtk3Theme() {
ConfigEditor::setGtk3ConfigValueXSettingsd(QStringLiteral("Net/ThemeName"), QStringLiteral("Breeze"));
}
}
QString gtk2Theme()
{
QString gtkrcPath = QDir::homePath() + QStringLiteral("/.gtkrc-2.0");
QFile gtkrc(gtkrcPath);
if (gtkrc.open(QIODevice::ReadWrite | QIODevice::Text)) {
const QRegularExpression regExp(QStringLiteral("gtk-theme-name=[^\n]*($|\n)"));
while (!gtkrc.atEnd()) {
QString line = gtkrc.readLine();
if (line.contains(regExp)) {
return line.split('"')[1];
}
}
}
return QString();
}
......@@ -75,14 +75,14 @@ void ConfigEditor::setGtk3ConfigValueSettingsIni(const QString &paramName, const
void ConfigEditor::setGtk3ConfigValueXSettingsd(const QString &paramName, const QVariant &paramValue)
{
QString configLocation = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
QDir xsettingsdPath = configLocation + QStringLiteral("/xsettingsd");
if (!xsettingsdPath.exists()) {
xsettingsdPath.mkpath(QStringLiteral("."));
}
QString xSettingsdConfigPath = xsettingsdPath.path() + QStringLiteral("/xsettingsd.conf");
QFile xSettingsdConfig(xSettingsdConfigPath);
QString xSettingsdConfigContents = readFileContents(xSettingsdConfig);
replaceValueInXSettingsdContents(xSettingsdConfigContents, paramName, paramValue);
......@@ -104,7 +104,6 @@ void ConfigEditor::setGtk2ConfigValue(const QString &paramName, const QVariant &
gtkrc.remove();
gtkrc.open(QIODevice::WriteOnly | QIODevice::Text);
gtkrc.write(gtkrcContents.toUtf8());
reloadGtk2Apps();
}
void ConfigEditor::setGtk3Colors(const QMap<QString, QColor> &colorsDefinitions)
......@@ -114,24 +113,6 @@ void ConfigEditor::setGtk3Colors(const QMap<QString, QColor> &colorsDefinitions)
addGtkModule(QStringLiteral("colorreload-gtk-module"));
}
QString ConfigEditor::gtk2ConfigValue(const QString& paramName)
{
QString gtkrcPath = QDir::homePath() + QStringLiteral("/.gtkrc-2.0");
QFile gtkrc(gtkrcPath);
if (gtkrc.open(QIODevice::ReadWrite | QIODevice::Text)) {
const QRegularExpression regExp(paramName + QStringLiteral("=[^\n]*($|\n)"));
while (!gtkrc.atEnd()) {
QString line = gtkrc.readLine();
if (line.contains(regExp)) {
return line.split('"')[1];
}
}
}
return QString();
}
QString ConfigEditor::gtk3ConfigValueSettingsIni(const QString& paramName)
{
QString configLocation = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
......@@ -169,7 +150,6 @@ void ConfigEditor::removeLegacyGtk2Strings()
gtkrc.remove();
gtkrc.open(QIODevice::WriteOnly | QIODevice::Text);
gtkrc.write(gtkrcContents.toUtf8());
reloadGtk2Apps();
}
void ConfigEditor::addGtkModule(const QString& moduleName)
......@@ -268,11 +248,6 @@ void ConfigEditor::replaceValueInXSettingsdContents(QString &xSettingsdContents,
}
}
void ConfigEditor::reloadGtk2Apps()
{
QProcess::startDetached(QStandardPaths::findExecutable(QStringLiteral("reload_gtk_apps")));
}
pid_t ConfigEditor::pidOfXSettingsd()
{
QProcess pidof;
......
......@@ -37,7 +37,6 @@ namespace ConfigEditor
void setGtk3Colors(const QMap<QString, QColor> &colorsDefinitions);
QString gtk2ConfigValue(const QString& paramName);
QString gtk3ConfigValueSettingsIni(const QString& paramName);
void removeLegacyGtk2Strings();
......@@ -52,7 +51,6 @@ namespace ConfigEditor
QString readFileContents(QFile &gtkrc);
void reloadGtk2Apps();
void reloadXSettingsd();
pid_t pidOfXSettingsd();
......
......@@ -61,34 +61,20 @@ GtkConfig::~GtkConfig()
dbus.unregisterObject(QStringLiteral("/GtkConfig"));
}
void GtkConfig::setGtk2Theme(const QString &themeName) const
void GtkConfig::setGtkTheme(const QString &themeName) const
{
ConfigEditor::setGtk2ConfigValue(QStringLiteral("gtk-theme-name"), themeName);
}
void GtkConfig::setGtk3Theme(const QString &themeName) const
{
ConfigEditor::setGtk3ConfigValueGSettings(QStringLiteral("gtk-theme"), themeName);
ConfigEditor::setGtk3ConfigValueSettingsIni(QStringLiteral("gtk-theme-name"), themeName);
ConfigEditor::setGtk3ConfigValueXSettingsd(QStringLiteral("Net/ThemeName"), themeName);
}
QString GtkConfig::gtk2Theme() const
{
return ConfigEditor::gtk2ConfigValue(QStringLiteral("gtk-theme-name"));
}
QString GtkConfig::gtk3Theme() const
QString GtkConfig::gtkTheme() const
{
return ConfigEditor::gtk3ConfigValueSettingsIni(QStringLiteral("gtk-theme-name"));
}
void GtkConfig::showGtk2ThemePreview(const QString& themeName) const
{
themePreviewer->showGtk2App(themeName);
}
void GtkConfig::showGtk3ThemePreview(const QString& themeName) const
void GtkConfig::showGtkThemePreview(const QString& themeName) const
{
themePreviewer->showGtk3App(themeName);
}
......
......@@ -53,14 +53,9 @@ public:
void applyAllSettings() const;
public Q_SLOTS:
Q_SCRIPTABLE void setGtk2Theme(const QString &themeName) const;
Q_SCRIPTABLE void setGtk3Theme(const QString &themeName) const;
Q_SCRIPTABLE QString gtk2Theme() const;
Q_SCRIPTABLE QString gtk3Theme() const;
Q_SCRIPTABLE void showGtk2ThemePreview(const QString &themeName) const;
Q_SCRIPTABLE void showGtk3ThemePreview(const QString &themeName) const;
Q_SCRIPTABLE void setGtkTheme(const QString &themeName) const;
Q_SCRIPTABLE QString gtkTheme() const;
Q_SCRIPTABLE void showGtkThemePreview(const QString &themeName) const;
void onKdeglobalsSettingsChange(const KConfigGroup &group, const QByteArrayList &names) const;
void onKWinSettingsChange(const KConfigGroup &group, const QByteArrayList &names) const;
......
......@@ -18,62 +18,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QDir>
#include <QFile>
#include <QObject>
#include <QProcess>
#include <QProcessEnvironment>
#include <QStandardPaths>
#include <QString>
#include <QScopedPointer>
#include <KConfigGroup>
#include <KSharedConfig>
#include <signal.h>
#include "themepreviewer.h"
#include "configeditor.h"
#include "config.h"
const QString ThemePreviewer::previewGtk2ConfigPath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + QStringLiteral("/gtkrc-2.0");
const QString ThemePreviewer::currentGtk2ConfigPath = QDir::homePath() + QStringLiteral("/.gtkrc-2.0");
const QString ThemePreviewer::gtk2PreviewerExecutablePath = QStandardPaths::findExecutable(QStringLiteral("gtk_preview"), {CMAKE_INSTALL_FULL_LIBEXECDIR});
const QString ThemePreviewer::gtk3PreviewerExecutablePath = QStandardPaths::findExecutable(QStringLiteral("gtk3_preview"), {CMAKE_INSTALL_FULL_LIBEXECDIR});
ThemePreviewer::ThemePreviewer(QObject *parent) : QObject(parent),
gtk2PreviewerProccess(),
gtk3PreviewerProccess()
{
QProcessEnvironment gtk2PreviewEnvironment = QProcessEnvironment::systemEnvironment();
gtk2PreviewEnvironment.insert(QStringLiteral("GTK2_RC_FILES"), previewGtk2ConfigPath);
gtk2PreviewerProccess.setProcessEnvironment(gtk2PreviewEnvironment);
connect(&gtk2PreviewerProccess, SIGNAL(finished(int)), this, SLOT(startXsettingsd()));
}
void ThemePreviewer::showGtk2App(const QString& themeName)
{
if (gtk2PreviewerProccess.state() == QProcess::ProcessState::NotRunning) {
if (QFile::exists(previewGtk2ConfigPath)) {
QFile::remove(previewGtk2ConfigPath);
}
QFile::copy(currentGtk2ConfigPath, previewGtk2ConfigPath);
QFile previewConfig(previewGtk2ConfigPath);
QString previewConfigContents = ConfigEditor::readFileContents(previewConfig);
ConfigEditor::replaceValueInGtkrcContents(previewConfigContents, QStringLiteral("gtk-theme-name"), themeName);
previewConfig.remove();
previewConfig.open(QIODevice::WriteOnly | QIODevice::Text);
previewConfig.write(previewConfigContents.toUtf8());
stopXsettingsd();
gtk2PreviewerProccess.start(gtk2PreviewerExecutablePath);
} else {
gtk2PreviewerProccess.close();
}
}
void ThemePreviewer::showGtk3App(const QString& themeName)
......@@ -88,19 +44,3 @@ void ThemePreviewer::showGtk3App(const QString& themeName)
gtk3PreviewerProccess.close();
}
}
void ThemePreviewer::startXsettingsd()
{
if (gtk2PreviewerProccess.state() == QProcess::ProcessState::NotRunning &&
gtk3PreviewerProccess.state() == QProcess::ProcessState::NotRunning) {
QProcess::startDetached(QStandardPaths::findExecutable(QStringLiteral("xsettingsd")));
}
}
void ThemePreviewer::stopXsettingsd()
{
pid_t pidOfXSettingsd = ConfigEditor::pidOfXSettingsd();
if (pidOfXSettingsd > 0) {
kill(pidOfXSettingsd, SIGTERM);
}
}
......@@ -28,20 +28,10 @@ class ThemePreviewer : QObject {
public:
ThemePreviewer(QObject *parent);
void showGtk2App(const QString &themeName);
void showGtk3App(const QString &themeName);
private Q_SLOTS:
void startXsettingsd();
void stopXsettingsd();
private:
static const QString previewGtk2ConfigPath;
static const QString currentGtk2ConfigPath;
static const QString gtk2PreviewerExecutablePath;
static const QString gtk3PreviewerExecutablePath;
QProcess gtk2PreviewerProccess;
QProcess gtk3PreviewerProccess;
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment