# -*- coding: utf-8 -*- # # gPodder - A media aggregator and podcast client # Copyright (c) 2005-2018 The gPodder Team # # gPodder 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 3 of the License, or # (at your option) any later version. # # gPodder 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 . # # # gpodder.gtkui.config -- Config object with GTK+ support (2009-08-24) # from gi.repository import Gdk, Gtk, Pango import gpodder from gpodder import config, util _ = gpodder.gettext class ConfigModel(Gtk.ListStore): C_NAME, C_TYPE_TEXT, C_VALUE_TEXT, C_TYPE, C_EDITABLE, C_FONT_STYLE, \ C_IS_BOOLEAN, C_BOOLEAN_VALUE = list(range(8)) def __init__(self, config): Gtk.ListStore.__init__(self, str, str, str, object, bool, int, bool, bool) self._config = config self._fill_model() self._config.add_observer(self._on_update) def _type_as_string(self, type): if type == int: return _('Integer') elif type == float: return _('Float') elif type == bool: return _('Boolean') else: return _('String') def _fill_model(self): self.clear() for key in sorted(self._config.all_keys()): # Ignore Gtk window state data (position, size, ...) if key.startswith('ui.gtk.state.'): continue value = self._config._lookup(key) fieldtype = type(value) style = Pango.Style.NORMAL # if value == default: # style = Pango.Style.NORMAL # else: # style = Pango.Style.ITALIC self.append((key, self._type_as_string(fieldtype), config.config_value_to_string(value), fieldtype, fieldtype is not bool, style, fieldtype is bool, bool(value))) def _on_update(self, name, old_value, new_value): for row in self: if row[self.C_NAME] == name: style = Pango.Style.NORMAL # if new_value == self._config.Settings[name]: # style = Pango.Style.NORMAL # else: # style = Pango.Style.ITALIC new_value_text = config.config_value_to_string(new_value) self.set(row.iter, self.C_VALUE_TEXT, new_value_text, self.C_BOOLEAN_VALUE, bool(new_value), self.C_FONT_STYLE, style) break def stop_observing(self): self._config.remove_observer(self._on_update) class UIConfig(config.Config): def __init__(self, filename='gpodder.conf'): config.Config.__init__(self, filename) self.__ignore_window_events = False def connect_gtk_editable(self, name, editable): editable.delete_text(0, -1) editable.insert_text(str(getattr(self, name))) def _editable_changed(editable): setattr(self, name, editable.get_chars(0, -1)) editable.connect('changed', _editable_changed) def connect_gtk_spinbutton(self, name, spinbutton, forced_upper=None): """ bind a Gtk.SpinButton to a configuration entry. It's now possible to specify an upper value (forced_upper). It's not done automatically (always look for name + '_max') because it's used only once. If it becomes commonplace, better make it automatic. :param str name: configuration key (e.g. 'max_downloads' or 'limit.downloads.concurrent') :param Gtk.SpinButton spinbutton: button to bind to config :param float forced_upper: forced upper limit on spinbutton. Overrides value in .ui to be consistent with code """ current_value = getattr(self, name) adjustment = spinbutton.get_adjustment() if forced_upper is not None: adjustment.set_upper(forced_upper) if current_value > adjustment.get_upper(): adjustment.set_upper(current_value) spinbutton.set_value(current_value) def _spinbutton_changed(spinbutton): setattr(self, name, spinbutton.get_value()) spinbutton.connect('value-changed', _spinbutton_changed) def connect_gtk_paned(self, name, paned): paned.set_position(getattr(self, name)) paned_child = paned.get_child1() def _child_size_allocate(x, y): setattr(self, name, paned.get_position()) paned_child.connect('size-allocate', _child_size_allocate) def connect_gtk_togglebutton(self, name, togglebutton): togglebutton.set_active(getattr(self, name)) def _togglebutton_toggled(togglebutton): setattr(self, name, togglebutton.get_active()) togglebutton.connect('toggled', _togglebutton_toggled) def connect_gtk_window(self, window, config_prefix, show_window=False): cfg = getattr(self.ui.gtk.state, config_prefix) if gpodder.ui.win32: window.set_gravity(Gdk.Gravity.STATIC) window.resize(cfg.width, cfg.height) if cfg.x == -1 or cfg.y == -1: window.set_position(Gtk.WindowPosition.CENTER_ON_PARENT) else: window.move(cfg.x, cfg.y) # Ignore events while we're connecting to the window self.__ignore_window_events = True def _receive_configure_event(widget, event): x_pos, y_pos = event.x, event.y width_size, height_size = event.width, event.height maximized = bool(event.window.get_state() & Gdk.WindowState.MAXIMIZED) if not self.__ignore_window_events and not maximized: cfg.x = x_pos cfg.y = y_pos cfg.width = width_size cfg.height = height_size window.connect('configure-event', _receive_configure_event) def _receive_window_state(widget, event): # ELL: why is it commented out? # new_value = bool(event.new_window_state & Gdk.WindowState.MAXIMIZED) # cfg.maximized = new_value pass window.connect('window-state-event', _receive_window_state) # After the window has been set up, we enable events again def _enable_window_events(): self.__ignore_window_events = False util.idle_add(_enable_window_events) if show_window: window.show() if cfg.maximized: window.maximize()