1 """ROX-Session settings with D-Bus and optional Gnome (gconf) setting
3 Setting and Settings are derived from ROX-Lib's Option and OptionGroup
4 respectively. A Setting sends a dbus message to ROX-Session when changed.
6 Use get_xsettings to get the dbus interface, then create a Settings object
7 with it to pass to each Setting.
11 from rox
.options
import OptionGroup
, Option
12 from rox
import OptionsBox
17 _warned_import
= False
18 _warned_connect
= False
22 """Returns ROX-Session's Settings dbus interface.
24 Called automatically if and when necessary
27 global _warned_connect
32 if not _warned_import
:
33 rox
.alert("Failed to import dbus module. You probably need "
34 "to install a package with a name like 'python2.3-dbus'"
35 "or 'python2.4-dbus'.\n"
36 "D-BUS can also be downloaded from http://freedesktop.org.")
41 if (hasattr(dbus
, 'SessionBus')):
42 bus
= dbus
.SessionBus()
44 bus
= dbus
.Bus(dbus
.Bus
.TYPE_SESSION
)
46 if not _warned_connect
:
47 rox
.alert('Failed to connect to D-BUS session bus. This probably '
48 "means that you're running an old version of ROX-Session "
49 '(or not using ROX-Session at all). Settings cannot be set '
50 "using this program until a newer version of ROX-Session is "
52 _warned_connect
= True
56 if hasattr(bus
, 'get_service'):
57 rox_session
= bus
.get_service('net.sf.rox.Session')
58 rox_settings
= rox_session
.get_object('/Settings',
59 'net.sf.rox.Session.Settings')
61 rox_settings
= dbus
.Interface(bus
.get_object('net.sf.rox.Session',
63 'net.sf.rox.Session.Settings')
66 rox
.alert("ROX-Session doesn't appear to be running (or "
67 "you are running an old version). Changing many of "
68 "these settings will have no effect.")
75 """Get GConf connection.
77 Some of the options have corresponding gconf entries; this gets
78 the gconf client connection. It will be called automatically if
84 client
= gconf
.client_get_default ()
85 client
.add_dir ("/desktop/gnome/interface",
86 gconf
.CLIENT_PRELOAD_NONE
)
92 class Settings(OptionGroup
):
93 """A group of options associated with the dbus interface. """
94 program
= os
.path
.basename(rox
.app_dir
)
95 def __init__(self
, bus
= get_xsettings(), client
= None):
98 bus: ROX-Session's dbus interface. Omit to use default
99 client: gconf client connection. Omit to use default
107 map(apply, self
.callbacks
)
109 option
.has_changed
= False
115 class Setting(Option
):
116 def __init__(self
, name
, default
, settings
, garbage
= False,
120 name: Option name as sent in dbus message.
121 default: Default value.
122 settings: The group of Settings this one belongs to.
123 garbage: Font and theme changes cause (some versions of?) GTK to
124 update all windows even if they're supposed to have been
125 destroyed. If we've just closed a dialog eg font selection (or
126 menu?), this can cause a crash, so this option forces a garbage
127 collection to make sure there is no stale reference.
128 gconf_key: Optional gconf setting key. If it begins with / it
129 will be treated as the absolute path, otherwise it will
130 have /desktop/gnome/interface/ prepended.
133 self
.default
= default
134 self
.settings
= settings
135 settings
.options
[name
] = self
136 self
.garbage
= garbage
138 if gconf_key
and gconf_key
[0] != '/':
139 gconf_key
= "/desktop/gnome/interface/" + gconf_key
140 self
.gconf_key
= gconf_key
142 type, value
= settings
.bus
.GetSetting(name
)
143 except: #XXX: dbus.DBusException:
146 self
._set
(value
, notify
= False)
148 def make_gconf_value(self
):
149 """Returns value ready to be converted to a GConfValue.
151 Override if necessary. Return a bool, int or string
152 (so the name is slightly misleading).
154 if type(self
.default
) is str:
155 return str(self
.value
)
157 return self
.int_value
159 def pre_notify_hook(self
):
160 """Called just before notifying dbus the standard way.
162 Override to perform additional operations and return True
163 if you want to prevent normal notification.
164 Won't be called if there's no bus.
168 def post_notify_hook(self
):
169 """Called just after notifying dbus the standard way.
171 Override to perform additional operations.
172 Won't be called if there's no bus, but otherwise will be called
173 even if pre_notif_hook() returns True.
177 def _set(self
, value
, notify
= True):
178 Option
._set
(self
, value
)
179 if not notify
: return
181 # This is a separate function because it used to be called via a
182 # GObject idle timeout instead of immediately. But that seems to be
183 # more of a hinrance than a help.
189 if not self
.settings
.bus
is None:
190 if not self
.pre_notify_hook():
191 if type(self
.default
) is str:
192 self
.settings
.bus
.SetString(self
.name
, self
.value
)
194 self
.settings
.bus
.SetInt(self
.name
, self
.int_value
)
195 self
.post_notify_hook()
198 if not self
.settings
.client
:
199 self
.settings
.client
= get_gconf()
200 if self
.settings
.client
:
201 val
= self
.make_gconf_value()
202 # Unfortunately GConfClient.set can't coerce builtin
203 # types to GConfValues
204 if type(val
) is bool:
205 self
.settings
.client
.set_bool(self
.gconf_key
, val
)
206 elif type(val
) is int:
207 self
.settings
.client
.set_int(self
.gconf_key
, val
)
209 self
.settings
.client
.set_string(self
.gconf_key
, val
)
214 gobject
.idle_add(set)
218 class BoolSetting(Setting
):
219 """Bool setting for GConf/D-Bus
221 Option doesn't distinguish between int and bool, but gconf does,
222 so use this for bool options.
224 def __init__(self
, name
, default
, settings
, theme
, gconf_key
= None):
225 Setting
.__init
__(self
, name
, default
, settings
, theme
, gconf_key
)
226 def make_gconf_value(self
):
227 return self
.int_value
!= 0