Skip to content

Commit

Permalink
Add color scheme (dark and light mode) support
Browse files Browse the repository at this point in the history
Add 'ui.gtk.color_scheme' config variable with 'system', 'light' and
'dark' string values. Config observer in main.py changes the color to
match the config.

System color scheme is read from freedesktop.org Settings portal via
Dbus.

The setting can be changed with a combo box in the preferences window
via new function connect_gtk_combo_box_text(). If Settings portal cannot
be found, only 'light' and 'dark' options are available in preferences.
  • Loading branch information
tpikonen committed Jan 2, 2024
1 parent e63b339 commit 2d12095
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 3 deletions.
47 changes: 45 additions & 2 deletions share/gpodder/ui/gtk/gpodderpreferences.ui
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<!-- Generated with glade 3.40.0 -->
<!--*- mode: xml -*-->
<interface>
<requires lib="gtk+" version="3.16"/>
Expand Down Expand Up @@ -273,6 +273,50 @@
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkLabel" id="label_color_scheme">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-end">8</property>
<property name="label" translatable="yes">Color scheme:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="combo_color_scheme">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="hexpand">True</property>
<property name="active">0</property>
<property name="active-id">1</property>
<items>
<item id="system" translatable="yes">System</item>
<item id="light" translatable="yes">Light</item>
<item id="dark" translatable="yes">Dark</item>
</items>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack-type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
<packing>
<property name="name">general</property>
Expand Down Expand Up @@ -1157,7 +1201,6 @@
<property name="can-focus">False</property>
<property name="border-width">0</property>
<property name="orientation">vertical</property>
<property name="spacing">0</property>
<child>
<object class="GtkTreeView" id="treeviewExtensions">
<property name="visible">True</property>
Expand Down
1 change: 1 addition & 0 deletions src/gpodder/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@
},

'html_shownotes': True, # enable webkit renderer
'color_scheme': 'system', # system, light, dark
},
},

Expand Down
45 changes: 44 additions & 1 deletion src/gpodder/gtkui/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,50 @@ def do_activate(self):
# Handle "subscribe to podcast" events from firefox
macosx.register_handlers(self.window)

# Set dark mode from config key, or from Settings portal if it
# exists and color_scheme from config is 'system'
if getattr(gpodder.dbus_session_bus, 'fake', False):
self.have_settings_portal = False
self.set_dark_mode(self.window.config.ui.gtk.color_scheme == 'dark')
else:
self.read_portal_color_scheme()
gpodder.dbus_session_bus.add_signal_receiver(
self.on_portal_setting_changed, "SettingChanged", None,
"org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop")

self.window.gPodder.present()

def set_dark_mode(self, dark):
settings = Gtk.Settings.get_default()
settings.props.gtk_application_prefer_dark_theme = 1 if dark else 0

def read_portal_color_scheme(self):
gpodder.dbus_session_bus.call_async(
"org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop",
"org.freedesktop.portal.Settings", "ReadOne", "ss",
("org.freedesktop.appearance", "color-scheme"),
self.on_portal_settings_read, self.on_portal_settings_read_error)

def on_portal_settings_read(self, value):
self.have_settings_portal = True
if self.window.config.ui.gtk.color_scheme == 'system':
self.set_dark_mode(value == 1)
else:
self.set_dark_mode(self.window.config.ui.gtk.color_scheme == 'dark')

def on_portal_settings_read_error(self, value):
self.have_settings_portal = False
self.set_dark_mode(self.window.config.ui.gtk.color_scheme == 'dark')

def on_portal_setting_changed(self, namespace, key, value):
if (namespace == 'org.freedesktop.appearance'
and key == 'color-scheme'):
dark = (value == 1)
if self.window.config.ui.gtk.color_scheme == 'system':
logger.debug(
f"'color-scheme' changed to {value}, setting dark mode to {dark}")
self.set_dark_mode(dark)

def on_menu(self, action, param):
self.menu_popover.popup()

Expand Down Expand Up @@ -265,7 +307,8 @@ def on_itemPreferences_activate(self, action, param=None):
on_send_full_subscriptions=self.window.on_send_full_subscriptions,
on_itemExportChannels_activate=self.window.on_itemExportChannels_activate,
on_extension_enabled=self.on_extension_enabled,
on_extension_disabled=self.on_extension_disabled)
on_extension_disabled=self.on_extension_disabled,
have_settings_portal=self.have_settings_portal)

def on_goto_mygpo(self, action, param):
self.window.mygpo_client.open_website()
Expand Down
7 changes: 7 additions & 0 deletions src/gpodder/gtkui/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,13 @@ def _togglebutton_toggled(togglebutton):
setattr(self, name, togglebutton.get_active())
togglebutton.connect('toggled', _togglebutton_toggled)

def connect_gtk_combo_box_text(self, name, combo_text):
combo_text.set_active_id(getattr(self, name))

def _combo_box_text_changed(combo):
setattr(self, name, combo.get_active_id())
combo_text.connect('changed', _combo_box_text_changed)

def connect_gtk_window(self, window, config_prefix, show_window=False):
cfg = getattr(self.ui.gtk.state, config_prefix)

Expand Down
15 changes: 15 additions & 0 deletions src/gpodder/gtkui/desktop/preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,21 @@ def new(self):
index = self.video_player_model.get_index(self._config.player.video)
self.combo_video_player_app.set_active(index)

self.combo_color_scheme.remove_all()
self.combo_color_scheme.prepend('dark', 'Dark')
self.combo_color_scheme.prepend('light', 'Light')
cs = self._config.ui.gtk.color_scheme
if self.have_settings_portal:
self.combo_color_scheme.prepend('system', 'System')
self.combo_color_scheme.set_active_id(cs)
else:
if cs == 'system':
self.combo_color_scheme.set_active_id('light')
self._config.ui.gtk.color_scheme = 'light'
else:
self.combo_color_scheme.set_active_id(cs)
self._config.connect_gtk_combo_box_text('ui.gtk.color_scheme', self.combo_color_scheme)

self.preferred_youtube_format_model = YouTubeVideoFormatListModel(self._config)
self.combobox_preferred_youtube_format.set_model(self.preferred_youtube_format_model)
cellrenderer = Gtk.CellRendererText()
Expand Down
5 changes: 5 additions & 0 deletions src/gpodder/gtkui/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -1486,6 +1486,11 @@ def _on_config_changed(self, name, old_value, new_value):
self.update_podcast_list_model()
elif name == 'ui.gtk.episode_list.columns':
self.update_episode_list_columns_visibility()
elif name == 'ui.gtk.color_scheme':
if new_value == 'system':
self.application.read_portal_color_scheme()
else:
self.application.set_dark_mode(new_value == 'dark')
elif name == 'limit.downloads.concurrent_max':
# Do not allow value to be set below 1
if new_value < 1:
Expand Down

0 comments on commit 2d12095

Please sign in to comment.