Skip to content

Commit 3c33675

Browse files
committed
Allow setting of GTK theme from Tcl and Python
1 parent cfa3b18 commit 3c33675

File tree

3 files changed

+57
-43
lines changed

3 files changed

+57
-43
lines changed

example.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,12 @@ def screenshot(self, *args):
8383
from gttk import GTTK
8484

8585
window = Example()
86-
gttk = GTTK(window)
86+
gttk = GTTK(window, theme="Adwaita")
8787
style = ttk.Style(window)
8888

8989
style.theme_use("gttk")
9090

91-
print(gttk.get_theme_colour_keys())
91+
gttk.set_gtk_theme("Yaru")
92+
window.after(2000, lambda: gttk.set_gtk_theme("Adwaita"))
9293

9394
window.mainloop()

generic/gttk_Init.cpp

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "gttk_Utilities.h"
1010
#include "gttk_TkHeaders.h"
11+
#include <gtk/gtkmodules.h>
1112
#include <string.h>
1213

1314
static int gttk_GtkAppCreated = 0;
@@ -81,6 +82,25 @@ int gttk_ThemeName(ClientData clientData, Tcl_Interp *interp,
8182
return TCL_OK;
8283
}; /* gttk_ThemeName */
8384

85+
int gttk_set_gtk_theme(ClientData clientData, Tcl_Interp* interp, int objc, Tcl_Obj* const objv[]) {
86+
/** @brief Tcl command 'setGtkTheme': Set the GTK theme from Tcl */
87+
if (objc != 2) {
88+
Tcl_WrongNumArgs(interp, 1, objv, "fileName");
89+
return TCL_ERROR;
90+
}
91+
// Get the argument and format it into the proper string
92+
const char* name = Tcl_GetStringFromObj(objv[1], NULL);
93+
// Make GTK parse the resource string
94+
Tcl_MutexLock(&gttkMutex);
95+
GtkSettings* settings = gtk_settings_get_default();
96+
gtk_settings_set_string_property(settings, "gtk-theme-name", name, NULL);
97+
gtk_rc_reset_styles(settings);
98+
99+
Tcl_MutexUnlock(&gttkMutex);
100+
101+
return TCL_OK;
102+
} // gttk_set_gtk_theme
103+
84104
int gttk_SettingsProperty(ClientData clientData, Tcl_Interp *interp,
85105
int objc, Tcl_Obj *const objv[]) {
86106
static const char *Methods[] = {
@@ -810,44 +830,23 @@ _Gttk_Init(Tcl_Interp *interp)
810830
Tcl_CreateExitHandler(&gttk_ExitProc, 0);
811831
//Tcl_CreateThreadExitHandler(&gttk_ExitProc, 0);
812832

813-
/*
814-
* Register the TileGtk package...
815-
*/
816-
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::gtkEnum",
817-
gttk_GtkEnum, (ClientData) wc, NULL);
818-
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::settingsProperty",
819-
gttk_SettingsProperty, (ClientData) wc, NULL);
820-
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::widgetStyleProperty",
821-
gttk_WidgetStyleProperty, (ClientData) wc, NULL);
822-
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::widgetProperty",
823-
gttk_WidgetProperty, (ClientData) wc, NULL);
824-
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::currentThemeName",
825-
gttk_ThemeName, (ClientData) wc, NULL);
826-
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::gtkDirectory",
827-
gttk_GtkDirectory, (ClientData) wc, NULL);
828-
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::setStyle",
829-
gttk_SetStyle, (ClientData) wc, NULL);
830-
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::gtk_method",
831-
gttk_gtk_method, (ClientData) wc, NULL);
832-
Tcl_CreateObjCommand(interp,
833-
"ttk::theme::gttk::currentThemeColour",
834-
gttk_ThemeColour, (ClientData) wc, NULL);
835-
Tcl_CreateObjCommand(interp,
836-
"ttk::theme::gttk::currentThemeColourKeys",
837-
gttk_ColourKeys, (ClientData) wc, NULL);
833+
// Register ttk::theme::gttk Tcl commands
834+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::gtkEnum", gttk_GtkEnum, (ClientData) wc, NULL);
835+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::settingsProperty", gttk_SettingsProperty, (ClientData) wc, NULL);
836+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::widgetStyleProperty", gttk_WidgetStyleProperty, (ClientData) wc, NULL);
837+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::widgetProperty", gttk_WidgetProperty, (ClientData) wc, NULL);
838+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::currentThemeName", gttk_ThemeName, (ClientData) wc, NULL);
839+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::gtkDirectory", gttk_GtkDirectory, (ClientData) wc, NULL);
840+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::setStyle", gttk_SetStyle, (ClientData) wc, NULL);
841+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::gtk_method", gttk_gtk_method, (ClientData) wc, NULL);
842+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::currentThemeColour", gttk_ThemeColour, (ClientData) wc, NULL);
843+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::currentThemeColourKeys", gttk_ColourKeys, (ClientData) wc, NULL);
844+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::setGtkTheme", gttk_set_gtk_theme, (ClientData) wc, NULL);
838845
#if 0
839-
Tcl_CreateObjCommand(interp,
840-
"ttk::theme::gttk::setPalette",
841-
gttk_SetPalette, (ClientData) wc, NULL);
842-
Tcl_CreateObjCommand(interp,
843-
"ttk::theme::gttk::getPixelMetric",
844-
gttk_GetPixelMetric, (ClientData) wc, NULL);
845-
Tcl_CreateObjCommand(interp,
846-
"ttk::theme::gttk::getStyleHint",
847-
gttk_GetStyleHint, (ClientData) wc, NULL);
848-
Tcl_CreateObjCommand(interp,
849-
"ttk::theme::gttk::getSubControlMetrics",
850-
gttk_GetSubControlMetrics, (ClientData) wc, NULL);
846+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::setPalette", gttk_SetPalette, (ClientData) wc, NULL);
847+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::getPixelMetric", gttk_GetPixelMetric, (ClientData) wc, NULL);
848+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::getStyleHint", gttk_GetStyleHint, (ClientData) wc, NULL);
849+
Tcl_CreateObjCommand(interp, "ttk::theme::gttk::getSubControlMetrics", gttk_GetSubControlMetrics, (ClientData) wc, NULL);
851850
#endif
852851
/* Save the name of the current theme... */
853852
strcpy(tmpScript, "namespace eval ttk::theme::gttk { variable theme ");

gttk/__init__.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
import contextlib
77
import os
88
import tkinter as tk
9-
from tkinter import ttk
10-
from typing import List, Tuple
9+
from typing import Optional, Tuple
1110

1211

1312
@contextlib.contextmanager
@@ -25,18 +24,30 @@ class GTTK(object):
2524
Class representing the GTTK extension
2625
"""
2726

28-
def __init__(self, window: tk.Tk):
27+
FOLDER = os.path.abspath(os.path.dirname(__file__))
28+
29+
def __init__(self, window: tk.Tk, theme: Optional[str] = None, theme_dir_prefix: Optional[str] = None):
2930
"""
3031
Initialize gttk and load it into a window
3132
3233
:param window: Window with Tk/Tcl interpreter to load gttk for
34+
:param theme: GTK theme to set upon initialisation
35+
:param theme_dir_prefix: Prefix to the theme directory. If not
36+
given, defaults to the current working directory. If this
37+
has the special value "LIB", the script will use the
38+
site-packages directory where it is installed.
3339
"""
3440
self.tk = window.tk
3541
folder = os.path.dirname(os.path.abspath(__file__)).replace("\\", "/")
42+
if theme_dir_prefix is not None:
43+
os.environ["GTK_DATA_PREFIX"] = theme_dir_prefix
44+
3645
with chdir(folder):
3746
self.tk.eval("set dir {0}; source {0}/pkgIndex.tcl".format(folder))
3847
self.tk.call("package", "require", "ttk::theme::gttk")
39-
print(self.get_current_theme())
48+
49+
if theme is not None:
50+
self.set_gtk_theme(theme)
4051

4152
def get_themes_directory(self) -> str:
4253
"""Return the directory in which GTK looks for installed themes"""
@@ -67,3 +78,6 @@ def get_theme_colour(self, name: str) -> str:
6778

6879
def get_theme_colour_keys(self) -> Tuple[str]:
6980
return self.tk.call("ttk::theme::gttk::currentThemeColourKeys")
81+
82+
def set_gtk_theme(self, theme: str):
83+
self.tk.call("ttk::theme::gttk::setGtkTheme", theme)

0 commit comments

Comments
 (0)