68
from spectlib.trayicon import Tray
69
60
from spectlib.notifier import Notifier
70
from spectlib.preferences import Preferences
71
from spectlib.add_watch import Add_watch
72
from spectlib.about import About
73
from spectlib.edit_watch import Edit_watch
74
from spectlib.logger import Log_dialog
77
63
""" The main Specto class. """
84
65
def __init__(self):
69
self.PATH = self.util.get_path()
70
self.SRC_PATH = self.util.get_path("src")
71
self.SPECTO_DIR = self.util.get_path("specto")
72
self.CACHE_DIR = self.util.get_path("tmp")
73
self.FILE = self.util.get_file()
86
75
import gettext #this is for the glade files
87
76
self.glade_gettext = gettext.textdomain("specto")
88
77
self.logger = Logger(self)
89
78
self.check_instance() #see if specto is already running
91
self.PATH = self.util.get_path()
92
79
self.specto_gconf = specto_gconf
93
80
self.check_default_settings()#if this is the first run of specto, set the default values for gconf. Whenever you add some gconf preference for specto, this function will also need to be updated.
96
self.tray = Tray(self)
83
self.connection_manager = conmgr.get_net_listener()
85
#create the watch collection and add the watches
86
self.watch_db = Watch_collection(self)
87
self.watch_io = Watch_io(self.FILE)
88
values = self.watch_io.read_all_watches()
90
self.watch_db.create(values)
91
except AttributeError, error_fields:
92
self.logger.log("Specto could not create a corrupted watch.", "critical", "Specto")
95
if "--console" in sys.argv[1:][0]:
96
self.logger.log("Console mode enabled.", "debug", "Specto")
100
args = sys.argv[1:][1]
103
self.console = Console(self, args)
104
self.console.start_watches()
97
109
self.icon_theme = gtk.icon_theme_get_default()
110
self.notifier = Notifier(self)
99
self.watch_io = Watch_io(os.environ['HOME'] + "/.specto/" + "watches.list")
101
#read all the watches from a file
102
values = self.watch_io.read_all_watches()
104
#create the watch collection and add the watches
105
self.watch_db = Watch_collection()
106
self.watch_db.add(self, values)
108
self.preferences_initialized = False
109
self.notifier_initialized = False
110
112
#listen for gconf keys
111
113
self.specto_gconf.notify_entry("debug_mode", self.key_changed, "debug")
113
self.connection_manager = conmgr.get_net_listener()
116
self.create_notifier_entries()
117
116
if self.specto_gconf.get_entry("always_show_icon") == False:
118
117
#if the user has not requested the tray icon to be shown at all times, it's impossible that the notifier is hidden on startup, so we must show it.
119
self.notifier_keep_hidden = False
120
self.toggle_notifier()
118
self.notifier_hide = False
121
119
elif self.specto_gconf.get_entry("show_notifier")==True:
122
self.notifier_keep_hidden = False
120
self.notifier_hide = False
123
121
self.toggle_notifier()
124
122
elif self.specto_gconf.get_entry("show_notifier")==False:
125
self.notifier_keep_hidden = True
126
self.toggle_notifier()
127
self.notifier_keep_hidden = False
123
self.notifier_hide = True
128
124
else:#just in case the entry was never created in gconf
129
125
self.notifier_keep_hidden = False
130
self.toggle_notifier()
127
for watch in self.watch_db:
128
self.notifier.add_notifier_entry(watch.id)
130
self.notifier.refresh_all_watches()
134
self.go = gobject.MainLoop()
136
self.go = gobject.MainLoop()
138
except (KeyboardInterrupt, SystemExit):
137
141
def key_changed(self, *args):
138
142
""" Listen for gconf keys. """
187
197
f=open(pidfile, "w")
188
198
f.write(str(os.getpid()))
191
def recreate_tray(self, *args):
193
Recreate a tray icon if the notification area unexpectedly quits.
195
try:self.tray.destroy()
198
self.tray = Tray(self)
199
self.watch_db.count_updated_watches()
201
def create_all_watches(self, value_db):
203
Create the watches at startup.
206
self.create_watch(value_db[i])
208
while gtk.events_pending():
209
gtk.main_iteration_do(False)
211
if self.specto_gconf.get_entry("show_deactivated_watches")== True:
212
self.notifier.wTree.get_widget("display_all_watches").set_active(True)
213
self.notifier.toggle_show_deactivated_watches(startup=True)#True makes startup=True, only used on the first startup to avoid duplicate watches.
215
#start the active watches
216
if self.notifier_initialized:
217
self.notifier.refresh()
219
def create_notifier_entries(self):
220
for watch in self.watch_db:
221
self.create_notifier_entry(watch)
223
def create_notifier_entry(self, watch):
224
""" Add a watch to the watches repository. """
225
if not self.notifier_initialized:
226
self.notifier = Notifier(self)
227
#self.notifier.restore_size_and_position()#fixme: is this necessary? this makes specto output stuff for nothing.
228
self.notifier.add_notifier_entry(watch.id)
231
## self.toggle_updated(watch.id)
236
## if watch.active == False:
237
## self.notifier.deactivate(watch.id)
241
def clear_watch(self, id):
242
""" Mark a watch as not updated. """
244
self.watch_db[id].updated = False
245
new_values['name'] = self.watch_db[id].name
246
new_values['updated'] = False
247
self.watch_io.write_options(new_values)
249
self.count_updated_watches()
251
201
def mark_watch_status(self, status, id):
252
202
""" get the watch status (updating, updated, idle) """
253
self.notifier.mark_watch_status(status, id)
255
def set_status(self, id, status):
256
""" Set the status from a watch (active/not active). """
258
new_values['name'] = self.watch_db[id].name
259
new_values['active'] = status
261
new_values['updated'] = False
262
self.watch_db[id].updated = False
263
self.notifier.clear_watch('',id)
264
self.watch_db[id].active = status
265
self.watch_io.write_options(new_values)
267
def replace_name(self, orig, new):
268
""" Replace the name from a watch in watches.list. """
269
self.watch_io.replace_name(orig, new)
271
def start_watch(self, id):
272
""" Start a watch. """
273
self.notifier.toggle_updating(True, id)
274
self.watch_db[id].start_watch()
275
self.logger.log(_("watch \"%s\" started") % self.watch_db[id].name, "info", self.__class__)
277
def stop_watch(self, id):
278
""" Stop a watch. """
279
self.watch_db[id].stop_watch()
280
self.logger.log(_("watch \"%s\" stopped") % self.watch_db[id].name, "info", self.__class__)
282
def add_watch(self, values):
283
""" Add a new watch. """
285
new_values['name'] = values['name']
286
new_values['type'] = values['type']
287
new_values['refresh'] = self.set_interval(values['refresh_value'], values['refresh_unit'])
289
if int(values['type']) == 0: #web
290
new_values['uri'] = values['url']
291
new_values['error_margin'] = values['error_margin']
293
elif int(values['type']) == 1: #mail
294
if int(values['prot']) == 0 or int(values['prot']) == 1:
295
new_values['host'] = values['host']
296
new_values['ssl'] = values['ssl']
298
new_values['username'] = values['username']
299
new_values['password'] = values['password']
300
new_values['prot'] = values['prot']
302
elif int(values['type']) == 2: #file
303
new_values['file'] = values['file']
304
new_values['mode'] = values['mode']
306
elif int(values['type']) == 3: #process
307
new_values['process'] = values['process']
309
elif int(values['type']) == 4: #port
310
new_values['port'] = values['port']
312
elif int(values['type']) == 5: #google reader
313
new_values['username'] = values['username']
314
new_values['password'] = values['password']
316
id = self.create_watch(new_values)
319
self.watch_io.write_options(new_values)
321
def edit_watch(self, values):
322
""" Edit a watch. """
324
new_values['name'] = values['name']
325
new_values['type'] = values['type']
326
new_values['refresh'] = self.set_interval(values['refresh_value'], values['refresh_unit'])
328
if int(values['type']) == 0: #web
329
new_values['uri'] = values['url']
330
new_values['error_margin'] = values['error_margin']
332
elif int(values['type']) == 1: #mail
333
if int(values['prot']) != 2: #gmail doesn't need a host and SSL it seems, so this is updated only of it's another kind of mail watch
334
new_values['host'] = values['host']
335
new_values['ssl'] = values['ssl']
337
new_values['username'] = values['username']
338
new_values['password'] = values['password']
339
new_values['prot'] = values['prot']
341
elif int(values['type']) == 2: #file
342
new_values['file'] = values['file']
344
elif int(values['type']) == 3: #process
345
new_values['process'] = values['process']
347
elif int(values['type']) == 4: #port
348
new_values['port'] = values['port']
350
elif int(values['type']) == 5: #google reader
351
new_values['username'] = values['username']
352
new_values['password'] = values['password']
354
self.watch_io.write_options(new_values)
355
self.notifier.show_watch_info()
357
def remove_watch(self, name, id):
358
""" Remove a watch. """
363
del self.watch_db[id]
364
self.count_updated_watches()
365
self.watch_io.remove_watch(name)#do not clear the watch after removing it or it will mess up the watches.list
366
self.notifier.model.remove(self.notifier.iter[id])
368
def count_updated_watches(self):
369
""" Count the number of updated watches for the tooltip. """
370
for i in self.watch_db:
371
if self.watch_db[i].updated == True:
372
self.tray.set_icon_state_excited()#change the tray icon color to orange
373
tooltip_updated_watches[self.watch_db[i].type] += 1
374
if tooltip_updated_watches.values() == [0,0,0,0,0,0]:#there are no more watches to clear, reset the tray icon
375
self.tray.set_icon_state_normal()
376
self.notifier.wTree.get_widget("button_clear_all").set_sensitive(False)
378
self.tray.show_tooltip(tooltip_updated_watches)
380
def toggle_updated(self, id):
382
When a watch is updated: change name in notifier window,
383
change the tray icon state, play a sound, ...
386
now = datetime.today()
389
new_values['last_updated'] = now.strftime("%A %d %b %Y %H:%M")
390
self.watch_db[id].last_updated = now.strftime("%A %d %b %Y %H:%M")
392
self.watch_db[id].updated = True
394
if self.notifier_initialized: self.notifier.toggle_updated(id)
395
new_values['name'] = self.watch_db[id].name
396
new_values['updated'] = True
397
self.watch_io.write_options(new_values) #write the watches state in watches.list
399
self.count_updated_watches() #show the tooltip
401
def toggle_all_cleared(self):
402
""" Set the state from all the watches back to 'not updated'. """
403
for i in self.watch_db:
405
self.watch_db[i].updated = False
406
new_values['name'] = self.watch_db[i].name
407
new_values['updated'] = False
408
self.watch_io.write_options(new_values)
410
self.count_updated_watches()
412
def set_interval(self, refresh, refresh_unit):
414
Set the interval between the update checks.
416
refresh_unit = days, hours, minutes,... in values of 0, 1, 2, 3.
419
if refresh_unit == 0:#seconds
420
new_refresh = refresh * 1000
421
elif refresh_unit == 1:#minutes
422
new_refresh = refresh * 60 * 1000
423
elif refresh_unit == 2:#hours
424
new_refresh = (refresh * 60) * 60 * 1000
425
elif refresh_unit == 3:#days
426
new_refresh = ((refresh * 60) * 60) * 24 *1000
430
def get_interval(self, value):
431
""" Get the interval between 2 updates. """
432
if ((value / 60) / 60) / 24 / 1000 > 0:
433
refresh_value = ((value / 60) / 60) / 24 / 1000
435
elif (value / 60) / 60 / 1000 > 0:
436
refresh_value = (value / 60) / 60 / 1000
438
elif value / 60 / 1000 > 0:
439
refresh_value = value / 60 / 1000
442
refresh_value = value / 1000
445
return refresh_value, type
204
self.notifier.mark_watch_status(status, id)
206
self.console.mark_watch_status(status, id)
447
208
def toggle_notifier(self, *args):
450
211
It will save the size, position, and the last state when you closed Specto.
452
213
#Creating the notifier window, but keeping it hidden
453
if not self.notifier_initialized and self.notifier_keep_hidden:
454
self.notifier = Notifier(self)
455
#self.notifier.restore_size_and_position()#this is NOT needed here because it already does that on instanciation on the line above -kiddo
456
self.notifier.notifier.hide()
457
#Creating the notifier window and displaying it
458
elif not self.notifier_initialized and not self.notifier_keep_hidden:
459
self.notifier = Notifier(self)
460
#self.notifier.restore_size_and_position()#this is NOT needed here because it already does that on instanciation on the line above -kiddo
461
self.notifier.notifier.show()
463
elif self.notifier_initialized:
464
if self.notifier.get_state()==True and self.notifier_keep_hidden:
465
self.logger.log(_("notifier: reappear"), "debug", self.__class__)
466
self.specto_gconf.set_entry("show_notifier", True)
467
self.notifier.restore_size_and_position()#to make sure that the x and y positions don't jump around
468
self.notifier.notifier.show()
469
elif self.notifier.get_state()==True and not self.notifier_keep_hidden:
470
self.logger.log(_("notifier: hide"), "debug", self.__class__)
471
self.specto_gconf.set_entry("show_notifier", False)
472
self.notifier.notifier.hide()
474
self.logger.log(_("notifier: reappear"), "debug", self.__class__)
475
self.specto_gconf.set_entry("show_notifier", True)
476
self.notifier.restore_size_and_position()#to make sure that the x and y positions don't jump around
477
self.notifier.notifier.show()
478
self.notifier_initialized = True
480
def show_preferences(self, *args):
481
""" Show the preferences window. """
482
if not self.preferences_initialized or self.preferences.get_state() == True:
483
self.logger.log(_("preferences: create"), "debug", self.__class__)
484
self.pref=Preferences(self)
486
self.logger.log(_("preferences: reappear"), "debug", self.__class__)
489
def show_error_log(self, *args):
490
""" Show the error log. """
491
if self.error_l == "":
492
self.error_l= Log_dialog(self)
493
self.logger.log(_("error log: create"), "debug", self.__class__)
494
elif self.error_l.log_dialog.flags() & gtk.MAPPED:
495
self.logger.log(_("error log: already visible"), "debug", self.__class__)
497
self.error_l= Log_dialog(self)
498
self.logger.log(_("error log: recreate"), "debug", self.__class__)
500
def show_add_watch(self, *args):
501
""" Show the add watch window. """
503
self.add_w= Add_watch(self)
504
self.logger.log(_("add watch: create"), "debug", self.__class__)
505
elif self.add_w.add_watch.flags() & gtk.MAPPED:
506
self.logger.log(_("add watch: already visible"), "debug", self.__class__)
508
self.add_w= Add_watch(self)
509
self.logger.log(_("add watch: recreate"), "debug", self.__class__)
511
def show_edit_watch(self, id, *args):
512
""" Show the edit watch window. """
515
selected = self.watch_db[id]
517
for i in self.watch_db:
518
if self.watch_db[i].name == args[0]:
519
selected = self.watch_db[i]
521
if self.edit_w == "":
522
self.edit_w= Edit_watch(self, selected)
523
self.logger.log(_("edit watch: create"), "debug", self.__class__)
524
elif self.edit_w.edit_watch.flags() & gtk.MAPPED:
525
self.logger.log(_("edit watch: already visible"), "debug", self.__class__)
527
self.edit_w= Edit_watch(self, selected)
528
self.logger.log(_("edit watch: recreate"), "debug", self.__class__)
530
def show_about(self, *args):
531
""" Show the about window. """
533
self.about = About(self)
534
elif self.about.about.flags() & gtk.MAPPED:
537
self.about = About(self)
539
def show_help(self, *args):
540
""" Show the help web page. """
541
self.util.show_webpage("http://code.google.com/p/specto/w/list")
543
def import_export_watches(self, action):
544
""" Show the import/export window. """
545
if self.export == "":
546
self.export = Import_watch(self, action)
547
elif self.export.import_watch.flags() & gtk.MAPPED:
550
self.export = Import_watch(self, action)
214
if self.notifier.get_state()==True and not self.notifier_hide:
215
self.specto_gconf.set_entry("show_notifier", True)
216
self.notifier.restore_size_and_position()#to make sure that the x and y positions don't jump around
217
self.notifier.notifier.show()
218
self.notifier_hide = True
219
elif self.notifier.get_state()==True and self.notifier_hide:
220
self.notifier.save_size_and_position()
221
self.specto_gconf.set_entry("show_notifier", False)
222
self.notifier.notifier.hide()
223
self.notifier_hide = False
225
self.specto_gconf.set_entry("show_notifier", True)
226
self.notifier.restore_size_and_position()#to make sure that the x and y positions don't jump around
227
self.notifier.notifier.show()
228
self.notifier_hide = True
552
230
def quit(self, *args):
553
231
""" Save the save and position from the notifier and quit Specto. """
554
if self.notifier.get_state()==True and not self.notifier_keep_hidden:
232
if self.notifier.get_state()==True and self.notifier_hide:
555
233
self.notifier.save_size_and_position()#when quitting specto abruptly, remember the notifier window properties