Delete button sensitivity in episode selector (bug 993)
[gpodder.git] / src / gpodder / gtkui / config.py
blob54dc515245741e3342a786d4f19448eda29325ec
1 # -*- coding: utf-8 -*-
3 # gPodder - A media aggregator and podcast client
4 # Copyright (c) 2005-2010 Thomas Perl and the gPodder Team
6 # gPodder is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # gPodder is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 # gpodder.gtkui.config -- Config object with GTK+ support (2009-08-24)
26 import gtk
27 import pango
29 import gpodder
30 from gpodder import util
31 from gpodder import config
33 _ = gpodder.gettext
35 class ConfigModel(gtk.ListStore):
36 C_NAME, C_TYPE_TEXT, C_VALUE_TEXT, C_TYPE, C_EDITABLE, C_FONT_STYLE, \
37 C_IS_BOOLEAN, C_BOOLEAN_VALUE = range(8)
39 def __init__(self, config):
40 gtk.ListStore.__init__(self, str, str, str, object, \
41 bool, int, bool, bool)
43 self._config = config
44 self._fill_model()
46 self._config.add_observer(self._on_update)
48 def _type_as_string(self, type):
49 if type == int:
50 return _('Integer')
51 elif type == float:
52 return _('Float')
53 elif type == bool:
54 return _('Boolean')
55 else:
56 return _('String')
58 def _fill_model(self):
59 self.clear()
60 for key in sorted(self._config.Settings):
61 fieldtype, default = self._config.Settings[key][:2]
62 value = getattr(self._config, key, default)
64 if value == default:
65 style = pango.STYLE_NORMAL
66 else:
67 style = pango.STYLE_ITALIC
69 self.append((key, self._type_as_string(fieldtype), \
70 str(value), fieldtype, fieldtype is not bool, style, \
71 fieldtype is bool, bool(value)))
73 def _on_update(self, name, old_value, new_value):
74 for row in self:
75 if row[self.C_NAME] == name:
76 if new_value == self._config.Settings[name][1]:
77 style = pango.STYLE_NORMAL
78 else:
79 style = pango.STYLE_ITALIC
80 self.set(row.iter, \
81 self.C_VALUE_TEXT, str(new_value), \
82 self.C_BOOLEAN_VALUE, bool(new_value), \
83 self.C_FONT_STYLE, style)
84 break
86 def stop_observing(self):
87 self._config.remove_observer(self._on_update)
89 class UIConfig(config.Config):
90 def __init__(self, filename='gpodder.conf'):
91 config.Config.__init__(self, filename)
92 self.__ignore_window_events = False
94 def connect_gtk_editable(self, name, editable):
95 assert name in self.Settings
96 editable.delete_text(0, -1)
97 editable.insert_text(str(getattr(self, name)))
99 def _editable_changed(editable):
100 setattr(self, name, editable.get_chars(0, -1))
101 editable.connect('changed', _editable_changed)
103 def connect_gtk_spinbutton(self, name, spinbutton):
104 assert name in self.Settings
105 spinbutton.set_value(getattr(self, name))
107 def _spinbutton_changed(spinbutton):
108 setattr(self, name, spinbutton.get_value())
109 spinbutton.connect('value-changed', _spinbutton_changed)
111 def connect_gtk_paned(self, name, paned):
112 assert name in self.Settings
113 paned.set_position(getattr(self, name))
114 paned_child = paned.get_child1()
116 def _child_size_allocate(x, y):
117 setattr(self, name, paned.get_position())
118 paned_child.connect('size-allocate', _child_size_allocate)
120 def connect_gtk_togglebutton(self, name, togglebutton):
121 assert name in self.Settings
122 togglebutton.set_active(getattr(self, name))
124 def _togglebutton_toggled(togglebutton):
125 setattr(self, name, togglebutton.get_active())
126 togglebutton.connect('toggled', _togglebutton_toggled)
128 def connect_gtk_filechooser(self, name, filechooser, is_for_files=False):
129 assert name in self.Settings
131 # FIXME: can we determine "is_for_files" by consulting the filechooser?
132 if is_for_files:
133 # A FileChooser for a single file
134 filechooser.set_filename(getattr(self, name))
135 else:
136 # A FileChooser for a folder
137 filechooser.set_current_folder(getattr(self, name))
139 def _chooser_selection_changed(filechooser):
140 filename = filechooser.get_filename()
141 if filename is not None:
142 setattr(self, name, filename)
144 filechooser.connect('selection-changed', _chooser_selection_changed)
146 def connect_gtk_window(self, window, config_prefix, show_window=False):
147 x, y, width, height, maximized = map(lambda x: config_prefix+'_'+x, \
148 ('x', 'y', 'width', 'height', 'maximized'))
150 if set((x, y, width, height)).issubset(set(self.Settings)):
151 window.resize(getattr(self, width), getattr(self, height))
152 if getattr(self, x) == -1 or getattr(self, y) == -1:
153 window.set_position(gtk.WIN_POS_CENTER_ON_PARENT)
154 else:
155 window.move(getattr(self, x), getattr(self, y))
157 # Ignore events while we're connecting to the window
158 self.__ignore_window_events = True
160 def _receive_configure_event(widget, event):
161 x_pos, y_pos = widget.get_position()
162 width_size, height_size = widget.get_size()
163 if not self.__ignore_window_events and not \
164 (hasattr(self, maximized) and getattr(self, maximized)):
165 setattr(self, x, x_pos)
166 setattr(self, y, y_pos)
167 setattr(self, width, width_size)
168 setattr(self, height, height_size)
170 window.connect('configure-event', _receive_configure_event)
172 def _receive_window_state(widget, event):
173 new_value = bool(event.new_window_state & \
174 gtk.gdk.WINDOW_STATE_MAXIMIZED)
175 if hasattr(self, maximized):
176 setattr(self, maximized, new_value)
178 window.connect('window-state-event', _receive_window_state)
180 # After the window has been set up, we enable events again
181 def _enable_window_events():
182 self.__ignore_window_events = False
183 util.idle_add(_enable_window_events)
185 if show_window:
186 window.show()
187 if getattr(self, maximized, False):
188 window.maximize()
189 else:
190 raise ValueError('Cannot connect %s', config_prefix, sender=self)