1
# -.- coding: utf-8 -.-
5
# Copyright © 2009 Markus Korn <thekorn@gmx.de>
7
# This program is free software: you can redistribute it and/or modify
8
# it under the terms of the GNU Lesser General Public License as published by
9
# the Free Software Foundation, either version 3 of the License, or
10
# (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU Lesser General Public License for more details.
17
# You should have received a copy of the GNU Lesser General Public License
18
# along with this program. If not, see <http://www.gnu.org/licenses/>.
25
import dbus.mainloop.glib
26
from ConfigParser import SafeConfigParser
27
from xdg import BaseDirectory
28
from StringIO import StringIO
30
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
32
class DataProviderService(dbus.service.Object):
34
def __init__(self, datasources, mainloop=None):
35
bus_name = dbus.service.BusName("org.gnome.zeitgeist.datahub", dbus.SessionBus())
36
dbus.service.Object.__init__(self, bus_name, "/org/gnome/zeitgeist/datahub")
37
self._mainloop = mainloop
38
self.__datasources = datasources
40
@dbus.service.method("org.gnome.zeitgeist.DataHub",
42
def GetDataProviders(self):
43
return [i.config.get_internal_name() for i in self.__datasources if i.config.has_dbus_service()]
45
def needs_setup(self):
46
return not self.__configuration.isConfigured()
49
class SetupService(dbus.service.Object):
51
def __init__(self, datasource, root_config, mainloop=None):
52
bus_name = dbus.service.BusName("org.gnome.zeitgeist.datahub", dbus.SessionBus())
53
dbus.service.Object.__init__(self,
54
bus_name, "/org/gnome/zeitgeist/datahub/dataprovider/%s" %datasource)
55
self._mainloop = mainloop
56
self.__configuration = root_config
57
if not isinstance(self.__configuration, _Configuration):
59
self.__setup_is_running = None
61
@dbus.service.method("org.gnome.zeitgeist.DataHub",
63
def SetConfiguration(self, token, option, value):
64
if token != self.__setup_is_running:
65
raise RuntimeError("wrong client")
66
self.__configuration.set_attribute(option, value)
68
@dbus.service.signal("org.gnome.zeitgeist.DataHub")
72
@dbus.service.method("org.gnome.zeitgeist.DataHub",
73
in_signature="i", out_signature="b")
74
def RequestSetupRun(self, token):
75
if self.__setup_is_running is None:
76
self.__setup_is_running = token
81
@dbus.service.method("org.gnome.zeitgeist.DataHub",
82
out_signature="a(sb)")
83
def GetOptions(self, token):
84
if token != self.__setup_is_running:
85
raise RuntimeError("wrong client")
86
return self.__configuration.get_options()
88
def needs_setup(self):
89
return not self.__configuration.isConfigured()
92
class _Configuration(gobject.GObject):
96
if isinstance(value, bool):
98
elif value.lower() in ("true", "1", "on"):
100
elif value.lower() in ("false", "0", "off"):
105
def __init__(self, internal_name, use_dbus=True, mainloop=None):
106
gobject.GObject.__init__(self)
107
self.__required = set()
108
self.__items = dict()
109
self.__internal_name = internal_name.replace(" ", "_").lower()
111
self.__dbus_service = SetupService(self.__internal_name, self, mainloop)
113
self.__dbus_service = None
115
def has_dbus_service(self):
116
return self.__dbus_service is not None
118
def get_internal_name(self):
119
return self.__internal_name
121
def add_option(self, name, to_type=str, to_string=str, default=None,
122
required=True, secret=False):
123
if name in self.__items:
126
self.__required.add(name)
128
to_type = lambda x: x
129
self.__items[name] = (to_type(default), (to_type, to_string), secret)
131
def __getattr__(self, name):
132
if not self.isConfigured():
134
return self.__items[name][0]
136
def get_as_string(self, name):
137
if not self.isConfigured():
140
value, (_, to_string), _ = self.__items[name]
143
return str(to_string(value))
145
def set_attribute(self, name, value, check_configured=True):
146
if name not in self.__items:
148
_, (to_type, to_string), secret = self.__items[name]
149
self.__items[name] = (to_type(value), (to_type, to_string), secret)
150
if name in self.__required:
151
self.remove_requirement(name)
152
if check_configured and self.isConfigured():
153
glib.idle_add(self.emit, "configured")
155
def remove_requirement(self, name):
156
self.__required.remove(name)
158
def add_requirement(self, name):
159
if not name in self.__items:
161
self.__required.add(name)
163
def isConfigured(self):
164
return not self.__required
166
def read_config(self, filename, section):
167
config = SafeConfigParser()
168
config.readfp(open(filename))
169
if config.has_section(section):
170
for name, value in config.items(section):
171
self.set_attribute(name, value)
173
def dump_config(self, config=None):
174
section = self.get_internal_name()
176
config = SafeConfigParser()
178
config.add_section(section)
179
except ConfigParser.DuplicateSectionError:
181
for key, value in self.__items.iteritems():
182
value, _, secret = value
184
config.set(section, key, str(value))
189
def get_requirements(self):
190
return self.__required
192
def get_options(self):
193
return [(str(key), key in self.__required) for key in self.__items]
196
gobject.signal_new("configured", _Configuration,
197
gobject.SIGNAL_RUN_LAST,
202
class DefaultConfiguration(_Configuration):
204
CONFIGFILE = BaseDirectory.load_first_config("zeitgeist", "dataprovider.conf")
206
("enabled", _Configuration.like_bool, str, True, False),
209
def __init__(self, dataprovider):
210
super(DefaultConfiguration, self).__init__(dataprovider)
211
for default in self.DEFAULTS:
212
self.add_option(*default)
214
self.read_config(self.CONFIGFILE, self.get_internal_name())
216
def save_config(self):
218
config = SafeConfigParser()
219
config.readfp(open(self.CONFIGFILE))
220
self.dump_config(config)
223
configfile = open(self.CONFIGFILE, "w")
225
config.write(configfile)
229
if __name__ == "__main__":
231
# TODO: Move this to test/.
234
for option, required in config.get_options():
235
print option, getattr(config, option)
237
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
238
mainloop = gobject.MainLoop()
240
config = _Configuration("test", True, mainloop)
241
config.add_option("enabled", _Configuration.like_bool, default=False)
242
config.connect("configured", test)