1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 import glob
25 import os
26 import gtk
27 import gobject
28 import gettext
29 import screenlets
30
31 gettext.textdomain('screenlets')
32 gettext.bindtextdomain('screenlets', screenlets.INSTALL_PREFIX + '/share/locale')
33
35 return gettext.gettext(s)
36
37
38 try:
39 import gconf
40 except:
41 print "GConf python module not found. GConf settings backend is disabled."
42
43
45 """The backend performs the loading/saving of the 'key=value'-strings.
46 Extend this superclass to implement different saving-backends."""
47
50
52 """Delete an instance's configuration by its id."""
53 pass
54
56 """Immediately store all values to disk (in case the backend doesn't
57 save in realtime anyway."""
58 pass
59
61 """Load one option for the instance with the given id."""
62 pass
63
65 """Load all options for the instance with the given id."""
66 pass
67
69 """Save one option for the instance with the given id."""
70 pass
71
72
74 """Backend for storing settings in the GConf registry"""
75
76 gconf_dir = '/apps/screenlets/'
77
82
84 """Delete an instance's configuration by its id."""
85 os.system('gconftool-2 --recursive-unset ' + self.key + id)
86 return True
87
89 """Immediately store all values to disk (in case the backend doesn't
90 save in realtime anyway."""
91 pass
92
94 """Load one option for the instance with the given id."""
95 return self.client.get_string(self.gconf_dir + id + '/' + name)
96
98 """Load all options for the instance with the given id."""
99 keys = []
100 vals = []
101 for i in self.client.all_entries(self.gconf_dir + id):
102 keys.append(i.key.split('/')[4])
103 vals.append(self.client.get_string(i.key))
104 return dict(zip(keys, vals))
105 return None
106
108 """Save one option for the instance with the given id."""
109 self.client.set_string(self.gconf_dir + id + '/' + name, value)
110 print 'Saved option %s%s/%s = %s' % (self.gconf_dir, id, name, value)
111
112
114 """A backend that stores the settings in arrays and saves after a short
115 interval to avoid overhead when multiple values are set within a short time.
116 The data gets saved into $HOME/.config/Screenlets/<Screenletname>/, in a
117 file for each element (named like its id with the extension '.ini')."""
118
119
120 __instances = {}
121 __delay_time = 3000
122 __timeout = None
123 __queue = []
124
125
126 path = ''
127
128
133
135 """Delete an instance from the list and from the filesystem."""
136 if self.__instances.has_key(id):
137 del self.__instances[id]
138 try:
139 import os
140 os.remove(self.path + id + '.ini')
141 except Exception,ex:
142 print ex
143 print "Temporary file didn't exist - nothing to remove."
144 return False
145 print "CachingBackend: <#%s> removed!" % id
146 return True
147
149 """Immediately save all pending data."""
150 self.__save_cache()
151
169
171 """TODO: Load option from the backend (returned as str)."""
172 return self.__instances[id][name]
173
175 """Load all options for the instance with the given id."""
176
177 if self.__instances.has_key(id):
178 return self.__instances[id]
179 return None
180
182 """Load all cached files from path."""
183
184 print "CachingBackend: Loading instances from cache"
185
186 dirname = self.path
187 dirlst = glob.glob(dirname + '*')
188 tdlen = len(dirname)
189 lst = []
190 for fname in dirlst:
191 dname = fname[tdlen:]
192 if dname.endswith('.ini'):
193 id = dname[:-4]
194 print "CachingBackend: Loading <%s>" % id
195
196 if self.__instances.has_key(id) == False:
197 self.__instances[id] = {}
198
199 try:
200 f = open(fname, 'r')
201 lines = f.readlines()
202
203 for line in lines:
204
205 parts = line[:-1].split('=', 1)
206 if len(parts) > 1:
207
208
209
210 if parts[0] == 'x':
211 if parts[1].startswith("*"):
212 parts[1] = parts[1].strip("*")
213 add_width = 0
214 if parts[1].startswith("_"):
215 add_width = int(float(self.__instances[id]["width"])*float(self.__instances[id]["scale"]))
216 print "ADD W", add_width
217 parts[1] = str(gtk.gdk.screen_width() - int(parts[1].strip("_")) - add_width)
218 print ">>>X", parts[1]
219 if parts[0] == 'y':
220 if parts[1].startswith("*"):
221 parts[1] = parts[1].strip("*")
222 add_height = 0
223 if parts[1].startswith("_"):
224 add_height = int(float(self.__instances[id]["height"])*float(self.__instances[id]["scale"]))
225 print "ADD H", add_height
226 parts[1] = str(gtk.gdk.screen_height() - int(parts[1].strip("_")) - add_height)
227 print ">>>Y", parts[1]
228 if parts[0] == 'rel_x':
229 parts[0] = 'x'
230 add_width = 0
231 if parts[1].startswith("_"):
232 add_width = int(float(self.__instances[id]["width"])*float(self.__instances[id]["scale"]))
233 print "ADD W", add_width
234 parts[1] = str(int(gtk.gdk.screen_width()*float(parts[1].strip("_"))) - add_width)
235 print ">>>X", parts[1]
236 if parts[0] == 'rel_y':
237 parts[0] = 'y'
238 add_height = 0
239 if parts[1].startswith("_"):
240 add_height = int(float(self.__instances[id]["height"])*float(self.__instances[id]["scale"]))
241 print "ADD H", add_height
242 parts[1] = str(int(gtk.gdk.screen_height()*float(parts[1].strip("_"))) - add_height)
243 print ">>>Y", parts[1]
244 if parts[0] == 'rel_scale':
245 parts[0] = 'scale'
246 scale = float(self.__instances[id]["scale"])
247 initial_scale = scale + float(gtk.gdk.screen_height()*gtk.gdk.screen_width())/float(parts[1])
248 if initial_scale < 1.5:
249 initial_scale = 1.5
250 if initial_scale > 3:
251 initial_scale = 3
252 parts[1] = str(initial_scale)
253
254 print ">>>SCALE", parts[1]
255 if parts[0] == 'rel_font_name':
256 parts[0] = 'font_name'
257 print "|||", parts[1]
258 font_parts = parts[1].rsplit(" ")
259 parts[1]=""
260 for fp in font_parts:
261 if len(fp)>0 and len(fp.strip("0123456789."))==0:
262 parts[1]+= str( round(float(fp)*float(self.__instances[id]["scale"]), 1) ) + " "
263 else:
264 parts[1]+= fp + " "
265 parts[1] = parts[1].strip(" ")
266 print ">>>FONT_NAME", parts[1]
267
268 print "%s='%s'" % (parts[0], parts[1])
269 self.__instances[id][parts[0]] = parts[1]
270 f.close()
271 except Exception, ex:
272 print "Error while loading options: %s" % str(ex)
273
275 """Save the cache (for all pending instances in queue) to self.path."""
276
277 for id in self.__queue:
278
279 if self.__instances.has_key(id) == False:
280 print "Queue-element <%s> not found (already removed?)!" % id
281 self.__queue.remove(id)
282 break
283
284
285 lst = []
286 for oname in self.__instances[id]:
287 lst.append([oname, self.__instances[id][oname]])
288
289 if len(lst) > 0:
290 self.__save_settings (self.path + id + '.ini', lst)
291
292 self.__queue = []
293
294 return False
295
297 """ Try to save settings in a file, first save this to a temporal file avoid encodings a disk full errors """
298 filenametmp = filename + '.tmp'
299 isOk = True
300 newini = ''
301 try:
302
303 for el in lst:
304 newini += "%s=%s\n" % (el[0], el[1])
305 except:
306 isOk = False
307 print "error while convert config to string (encoding error?), I lose your last changes :'("
308
309 if isOk:
310
311 try:
312 open(filenametmp, 'w').write(newini)
313 except:
314 isOk = False
315 print "error while saving configuration to a temporal file %s, disk full?" % filenametmp
316
317 if isOk:
318
319 try:
320 import shutil
321 shutil.move(filenametmp, filename)
322 except:
323 print "error while moving temporal file to configuration file, %s > %s, sorry, I lose your settings. :'(" % (filenametmp, filename)
324