Internet radio browser GUI for music/video streams from various directory services.

⌈⌋ branch:  streamtuner2


Check-in [303e1c8e48]

Overview
Comment:Introduce Gtk theme switching again.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 303e1c8e489f0ad1b5071e15575a416c582a82b3
User & Date: mario on 2016-12-03 14:47:25
Other Links: manifest | tags
Context
2016-12-03
21:23
Removed plugin option background colors. check-in: 9520bc51a3 user: mario tags: trunk
14:47
Introduce Gtk theme switching again. check-in: 303e1c8e48 user: mario tags: trunk
14:47
Prevent crash on absent opt["select"] field. check-in: 2e9f6d9a19 user: mario tags: trunk
Changes

Modified channels/pluginmanager2.py from [7a64df83b9] to [5a7e32371d].

106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
        self.add_(uikit.label("You can update existing plugins, or install new contrib/ channels. User plugins reside in ~/.config/streamtuner2/plugins/ and can even be modified there (such as setting a custom # color: entry).\n", size=520, markup=1))
        self.add_(self.button("Refresh", stock="gtk-refresh", cb=self.refresh), "Show available plugins from repository\nhttp://fossil.include-once.org/streamtuner2/")
        self.add_(gtk.image_new_from_stock("gtk-info", gtk.ICON_SIZE_LARGE_TOOLBAR), "While plugins are generally compatible across releases, newer versions may also require to update the streamtuner2 core setup.")
        for i in range(1,10):
            self.add_(uikit.label(""))


    # Append to vbox
    def add_(self, w, label=None, markup=0):
        w = uikit.wrap(w=w, label=label, align=10, label_size=400, label_markup=1)
        self.vbox.add(w)

    # Create button, connect click signal    
    def button(self, label, stock=None, cb=None):
        b = gtk.Button(label, stock=stock)
        b.connect("clicked", cb)
        return b

    







<
<
<
<
<







106
107
108
109
110
111
112





113
114
115
116
117
118
119
        self.add_(uikit.label("You can update existing plugins, or install new contrib/ channels. User plugins reside in ~/.config/streamtuner2/plugins/ and can even be modified there (such as setting a custom # color: entry).\n", size=520, markup=1))
        self.add_(self.button("Refresh", stock="gtk-refresh", cb=self.refresh), "Show available plugins from repository\nhttp://fossil.include-once.org/streamtuner2/")
        self.add_(gtk.image_new_from_stock("gtk-info", gtk.ICON_SIZE_LARGE_TOOLBAR), "While plugins are generally compatible across releases, newer versions may also require to update the streamtuner2 core setup.")
        for i in range(1,10):
            self.add_(uikit.label(""))







    # Create button, connect click signal    
    def button(self, label, stock=None, cb=None):
        b = gtk.Button(label, stock=stock)
        b.connect("clicked", cb)
        return b

    
143
144
145
146
147
148
149





150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
            if dep.valid(newpl) and dep.depends(newpl):
                self.add_plugin(newpl)

        # Readd some filler labels
        _ = [self.add_(uikit.label("")) for i in range(1,3)]







    # Entry for plugin list
    def add_plugin(self, p):
        b = self.button("Install", stock="gtk-save", cb=lambda *w:self.install(p))
        p = self.update_p(p)
        text = "<b>$title</b>, "\
               "<small>version:</small> <span weight='bold' color='orange'>$version</span>, "\
               "<small>type: <i><span color='#559'>$type</span></i> "\
               "category: <i><span color='blue'>$category</span></i></small>\n"\
               "<span size='smaller' color='#364'>$description</span>\n"\
               "<span size='small' color='#532' weight='ultralight'>$extras, <a href='$file'>view src</a></span>"
        self.add_(b, safe_format(text, **p), markup=1)

        
    # Add placeholder fields
    def update_p(self, p):
        fields = ("status", "priority", "support", "author", "depends")
        extras = ["{}: <b>{}</b>".format(n, html_escape(p[n])) for n in fields if p.get(n)]
        p["extras"] = " ".join(["💁"] + extras)







>
>
>
>
>










|







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
            if dep.valid(newpl) and dep.depends(newpl):
                self.add_plugin(newpl)

        # Readd some filler labels
        _ = [self.add_(uikit.label("")) for i in range(1,3)]


    # Append to vbox
    def add_(self, w, label=None, markup=0, align=10, label_size=400):
        w = uikit.wrap(w=w, label=label, align=align, label_size=label_size, label_markup=markup)
        self.vbox.add(w)

    # Entry for plugin list
    def add_plugin(self, p):
        b = self.button("Install", stock="gtk-save", cb=lambda *w:self.install(p))
        p = self.update_p(p)
        text = "<b>$title</b>, "\
               "<small>version:</small> <span weight='bold' color='orange'>$version</span>, "\
               "<small>type: <i><span color='#559'>$type</span></i> "\
               "category: <i><span color='blue'>$category</span></i></small>\n"\
               "<span size='smaller' color='#364'>$description</span>\n"\
               "<span size='small' color='#532' weight='ultralight'>$extras, <a href='$file'>view src</a></span>"
        self.add_(b, label=safe_format(text, **p), markup=1, align=10, label_size=375)

        
    # Add placeholder fields
    def update_p(self, p):
        fields = ("status", "priority", "support", "author", "depends")
        extras = ["{}: <b>{}</b>".format(n, html_escape(p[n])) for n in fields if p.get(n)]
        p["extras"] = " ".join(["💁"] + extras)

Added contrib/gtk_theme.py version [72deb69630].

































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# api: streamtuner2
# title: Gtk theme setting
# description: Gtk theme switching in Streamtuner2. (Beware of crashes!)
# type: feature
# category: ui
# version: 0.2
# config:
#    { name: theme, type: select, select: "default=default", description: "Theme name" }
#    { name: theme_instant, type: bool, value=0, description: "Activate on the fly." }
# priority: experimental
#
# Brings back the theme switching option - for Gtk2 + Gtk3 now.
#
# Note that not all themes can be loaded on the fly. And may hang
# streamtuner2 even. Most require an application restart still.
# Which is why this is not a built-in feature anymore.
#
# Btw, you could alternatively use GTK2_RC_FILES= or GTK_THEME=
# environment variables for this.


import os
from config import *
import uikit
from compat2and3 import *



# register a key
class gtk_theme(object):

    # plugin info
    module = "gtk_theme"
    meta = plugin_meta()
    theme_dirs = [uikit.gtk.rc_get_theme_dir(), conf.dir + "/themes", conf.share + "/themes"]

    # register
    def __init__(self, parent):
        self.parent = parent
        parent.hooks["config_load"].append(self.list_themes)
        parent.hooks["config_save"].append(self.apply_theme)
        self.apply_theme(True)

    # gtk.rc_parse() called on configwin.save and ST2 startup
    def apply_theme(self, now=False):
        if conf.theme == "default":
            return
        # path depends on version
        if uikit.ver == 2:
            rc = "gtk-2.0/gtkrc"
        else:
            rc = "gtk-3.0/gtk.css"

        # look if theme exists
        for fn in ["%s/%s/%s" % (dir, conf.theme, rc) for dir in self.theme_dirs]:
            if not os.path.exists(fn):
                continue
            log.GTK_THEME_FILE(fn)
            # .GTKRC/Gtk2
            if uikit.ver == 2:
                uikit.gtk.rc_parse(fn)
                if now or conf.theme_instant:
                    uikit.gtk.rc_reparse_all()
            # .CSS/Gtk3
            elif now or conf.theme_instant:
                #ctx = uikit.gtk.StyleContext    # global
                ctx = self.parent.win_streamtuner2.get_style_context() # main window
                screen = uikit.gtk.gdk.Screen.get_default()
                style = uikit.gtk.CssProvider()
                style.load_from_file(fn)
                ctx.add_provider_for_screen(screen, style, uikit.gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

   # list Gtk themes, append to existing dropdown box
    def list_themes(self):
    
        # get ComboBoxText widget (wrapper object)
        cb = self.parent.widgets["config_theme"]
        cb.ls.clear()
        
        # search themes
        themes = []
        for dir in self.theme_dirs:
            if os.path.exists(dir):
                for fn in os.listdir(dir):
                    if os.path.exists("%s/%s/gtk-%s.0" % (dir, fn, uikit.ver)):
                        themes.append(fn)
        themes = ["default"] + sorted(themes)
        
        # add to list
        for t in themes:
            cb.ls.append([t, t])
        if conf.theme in themes:
            cb.set_default(conf.theme)
        else:
            cb.set_default("default")

Modified uikit.py from [ce679bb712] to [bb85fd7f1b].

473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
        #######label.set_property("visible", True)
        label.set_line_wrap(True) 
        label.set_size_request(size, -1)
        return label

    # Wrap two widgets in horizontal box
    @staticmethod
    def hbox(w1, w2, exr=True):
        b = gtk.HBox(homogeneous=False, spacing=5)
        ######b.set_property("visible", True)
        b.pack_start(w1, expand=not exr, fill=not exr)
        b.pack_start(w2, expand=exr, fill=exr)
        return b


    # Wrap entries/checkboxes with extra label, background, images, etc.
    @staticmethod
    def wrap(widgetstore=None, id=None, w=None, label=None, color=None, image=None, align=1, label_size=305, label_markup=0):
        if id:
            widgetstore[id] = w
        if label:
            if type(w) is gtk.Entry:
                w.set_width_chars(11)
            w = uikit.hbox(w, uikit.label(label, size=label_size, markup=label_markup))
        if image:
            pix = gtk.image_new_from_pixbuf(uikit.pixbuf(image))
            if pix:
                w = uikit.hbox(w, pix, exr=False)
        if color:
            w = uikit.bg(w, color)
        if align:







|
|














|







473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
        #######label.set_property("visible", True)
        label.set_line_wrap(True) 
        label.set_size_request(size, -1)
        return label

    # Wrap two widgets in horizontal box
    @staticmethod
    def hbox(w1, w2, exr=True, spacing=5):
        b = gtk.HBox(homogeneous=False, spacing=spacing)
        ######b.set_property("visible", True)
        b.pack_start(w1, expand=not exr, fill=not exr)
        b.pack_start(w2, expand=exr, fill=exr)
        return b


    # Wrap entries/checkboxes with extra label, background, images, etc.
    @staticmethod
    def wrap(widgetstore=None, id=None, w=None, label=None, color=None, image=None, align=1, label_size=305, label_markup=0):
        if id:
            widgetstore[id] = w
        if label:
            if type(w) is gtk.Entry:
                w.set_width_chars(11)
            w = uikit.hbox(w, uikit.label(label, size=label_size, markup=label_markup), exr=True)
        if image:
            pix = gtk.image_new_from_pixbuf(uikit.pixbuf(image))
            if pix:
                w = uikit.hbox(w, pix, exr=False)
        if color:
            w = uikit.bg(w, color)
        if align: