Merge lp:~sncf-pde/specto/pattern_search into lp:specto
- pattern_search
- Merge into main
Status: | Needs review |
---|---|
Proposed branch: | lp:~sncf-pde/specto/pattern_search |
Merge into: | lp:specto |
Diff against target: |
29980 lines (+29110/-39) (has conflicts) 95 files modified
build/lib.linux-i686-2.6/spectlib/about.py (+88/-0) build/lib.linux-i686-2.6/spectlib/add_watch.py (+278/-0) build/lib.linux-i686-2.6/spectlib/balloons.py (+102/-0) build/lib.linux-i686-2.6/spectlib/bdd.py (+317/-0) build/lib.linux-i686-2.6/spectlib/config.py (+104/-0) build/lib.linux-i686-2.6/spectlib/console.py (+54/-0) build/lib.linux-i686-2.6/spectlib/constants.py (+7/-0) build/lib.linux-i686-2.6/spectlib/contact.py (+330/-0) build/lib.linux-i686-2.6/spectlib/crawl.py (+149/-0) build/lib.linux-i686-2.6/spectlib/edit_watch.py (+316/-0) build/lib.linux-i686-2.6/spectlib/export_watch.py (+231/-0) build/lib.linux-i686-2.6/spectlib/gtkconfig.py (+588/-0) build/lib.linux-i686-2.6/spectlib/i18n.py (+50/-0) build/lib.linux-i686-2.6/spectlib/i18n_safedict.py (+70/-0) build/lib.linux-i686-2.6/spectlib/imail.py (+294/-0) build/lib.linux-i686-2.6/spectlib/import_watch.py (+281/-0) build/lib.linux-i686-2.6/spectlib/logger.py (+344/-0) build/lib.linux-i686-2.6/spectlib/main.py (+417/-0) build/lib.linux-i686-2.6/spectlib/notifier.py (+1080/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_im_pidgin.py (+188/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_mail_evolution.py (+70/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_mail_gmail.py (+380/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_mail_gwave.py (+271/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_mail_imap.py (+272/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_mail_pop3.py (+287/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_music_amarok.py (+74/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_music_banshee.py (+88/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_music_lastfm.py (+160/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_music_rhythmbox.py (+89/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_sn_facebook.py (+355/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_sn_twitter.py (+1699/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_system_file.py (+168/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_system_folder.py (+222/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_system_mumbles.py (+110/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_system_pdf_file.py (+289/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_system_port.py (+115/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_system_process.py (+193/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_vc_bazaar.py (+168/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_vc_subversion.py (+145/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_web_greader.py (+312/-0) build/lib.linux-i686-2.6/spectlib/plugins/watch_web_static.py (+643/-0) build/lib.linux-i686-2.6/spectlib/preferences.py (+405/-0) build/lib.linux-i686-2.6/spectlib/tools/indicator.py (+184/-0) build/lib.linux-i686-2.6/spectlib/tools/iniparser.py (+783/-0) build/lib.linux-i686-2.6/spectlib/tools/keyringmanager.py (+67/-0) build/lib.linux-i686-2.6/spectlib/tools/networkmanager.py (+140/-0) build/lib.linux-i686-2.6/spectlib/tools/sound.py (+50/-0) build/lib.linux-i686-2.6/spectlib/tools/specto_gconf.py (+107/-0) build/lib.linux-i686-2.6/spectlib/tools/web_proxy.py (+41/-0) build/lib.linux-i686-2.6/spectlib/trayicon.py (+209/-0) build/lib.linux-i686-2.6/spectlib/util.py (+117/-0) build/lib.linux-i686-2.6/spectlib/watch.py (+720/-0) build/scripts-2.6/specto (+30/-0) data/uis/contact.ui (+131/-0) data/uis/contact_dialog.ui (+176/-0) data/uis/group_contact_dialog.ui (+119/-0) data/uis/notifier.ui (+16/-2) data/uis/preferences.ui (+831/-2) doc/Manual.rst (+1/-1) installed_files (+148/-0) spectlib/add_watch.py (+14/-0) spectlib/bdd.py (+317/-0) spectlib/contact.py (+330/-0) spectlib/crawl.py (+152/-0) spectlib/gtkconfig.py (+42/-0) spectlib/imail.py (+295/-0) spectlib/main.py (+31/-0) spectlib/notifier.py (+26/-0) spectlib/plugins/pdfminer/Makefile (+9/-0) spectlib/plugins/pdfminer/__init__.py (+4/-0) spectlib/plugins/pdfminer/arcfour.py (+49/-0) spectlib/plugins/pdfminer/ascii85.py (+81/-0) spectlib/plugins/pdfminer/cmap/Makefile (+9/-0) spectlib/plugins/pdfminer/cmapdb.py (+421/-0) spectlib/plugins/pdfminer/converter.py (+497/-0) spectlib/plugins/pdfminer/encodingdb.py (+58/-0) spectlib/plugins/pdfminer/fontmetrics.py (+46/-0) spectlib/plugins/pdfminer/glyphlist.py (+4339/-0) spectlib/plugins/pdfminer/latin_enc.py (+241/-0) spectlib/plugins/pdfminer/layout.py (+675/-0) spectlib/plugins/pdfminer/lzw.py (+101/-0) spectlib/plugins/pdfminer/pdfcolor.py (+33/-0) spectlib/plugins/pdfminer/pdfdevice.py (+174/-0) spectlib/plugins/pdfminer/pdffont.py (+702/-0) spectlib/plugins/pdfminer/pdfinterp.py (+834/-0) spectlib/plugins/pdfminer/pdfparser.py (+791/-0) spectlib/plugins/pdfminer/pdftypes.py (+260/-0) spectlib/plugins/pdfminer/psparser.py (+686/-0) spectlib/plugins/pdfminer/rijndael.py (+1078/-0) spectlib/plugins/pdfminer/runlength.py (+50/-0) spectlib/plugins/pdfminer/utils.py (+276/-0) spectlib/plugins/watch_system_pdf_file.py (+289/-0) spectlib/plugins/watch_web_static.py (+329/-30) spectlib/preferences.py (+198/-3) spectlib/watch.py (+0/-1) Text conflict in data/uis/preferences.ui |
To merge this branch: | bzr merge lp:~sncf-pde/specto/pattern_search |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jeff Fortin Tam | Needs Fixing | ||
Review via email: mp+97351@code.launchpad.net |
Commit message
Description of the change
- 169. By Aaron KOUAO <email address hidden>
-
add possibility to choose whether to send email to inform
Unmerged revisions
- 169. By Aaron KOUAO <email address hidden>
-
add possibility to choose whether to send email to inform
- 168. By Aaron KOUAO <email address hidden>
-
Add the possibility to crawl pdf page
- 167. By Fabien_SNCF-PDE
-
- Add a window to set database settings and check them in preferences (default set to sqlite). database in bdd.py and sqlalchemy. Don't finished actually, still work with files
- Add a class to crawl webpage "crawl.py" manually. actually just crawl, don't check pattern and no difference between rss and html page
- Add a window to manage contact and mail address in group (work with database)
- Add possibility to check multiple pattern and exception - 166. By Fabien_SNCF-PDE
-
- Fix a little bug in the previous version
- Add a window to set settings for send mails and check them in preferences
- Add a little window to alert if settings are not set when adding a watch (if you give mail adress to the watch without set smtp server the watch will ignore it)
- Add mail settings to gconf and use keyring for password - 165. By Fabien_SNCF-PDE
-
Add class to send email when a pattern is found in rss page and a best work for detecting new pattern
- 164. By Fabien_SNCF-PDE
-
First very simple version
Preview Diff
1 | === added directory 'build' |
2 | === added directory 'build/lib.linux-i686-2.6' |
3 | === added directory 'build/lib.linux-i686-2.6/spectlib' |
4 | === added file 'build/lib.linux-i686-2.6/spectlib/__init__.py' |
5 | === added file 'build/lib.linux-i686-2.6/spectlib/about.py' |
6 | --- build/lib.linux-i686-2.6/spectlib/about.py 1970-01-01 00:00:00 +0000 |
7 | +++ build/lib.linux-i686-2.6/spectlib/about.py 2012-03-14 09:03:18 +0000 |
8 | @@ -0,0 +1,88 @@ |
9 | +# -*- coding: utf-8 -*- |
10 | + |
11 | +# Specto , Unobtrusive event notifier |
12 | +# |
13 | +# about.py |
14 | +# |
15 | +# See the AUTHORS file for copyright ownership information |
16 | + |
17 | +# This program is free software; you can redistribute it and/or |
18 | +# modify it under the terms of the GNU General Public |
19 | +# License as published by the Free Software Foundation; either |
20 | +# version 2 of the License, or (at your option) any later version. |
21 | +# |
22 | +# This program is distributed in the hope that it will be useful, |
23 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
24 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
25 | +# General Public License for more details. |
26 | +# |
27 | +# You should have received a copy of the GNU General Public |
28 | +# License along with this program; if not, write to the |
29 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
30 | +# Boston, MA 02111-1307, USA. |
31 | + |
32 | +import os |
33 | +import pygtk |
34 | +pygtk.require("2.0") |
35 | +import gtk |
36 | + |
37 | +from spectlib.util import show_webpage, get_path |
38 | + |
39 | + |
40 | +class About: |
41 | + """ |
42 | + Class to create a window with the credits |
43 | + and licensing information about Specto. |
44 | + """ |
45 | + |
46 | + def __init__(self, specto): |
47 | + self.specto = specto |
48 | + |
49 | + license_file_path = (os.path.join(get_path(category="doc"), "COPYING")) |
50 | + with open(license_file_path, "r") as license_file: |
51 | + license = license_file.read() |
52 | + |
53 | + authors_file_path = (os.path.join(get_path(category="doc"), "AUTHORS")) |
54 | + with open(authors_file_path, "r") as authors_file: |
55 | + # this is a hack, because gtk.AboutDialog expects a list, not a file |
56 | + authors = authors_file.readlines() |
57 | + |
58 | + logo = gtk.gdk.pixbuf_new_from_file(os.path.join(self.specto.PATH, "icons/specto_about.png")) |
59 | + |
60 | + # gtk.AboutDialog will detect if "translator-credits" is untranslated, |
61 | + # and hide the tab. |
62 | + translator_credits = _("translator-credits") |
63 | + |
64 | + #create tree |
65 | + self.about = gtk.AboutDialog() |
66 | + |
67 | + self.about.set_name("Specto") |
68 | + self.about.set_version(self.specto.VERSION) |
69 | + self.about.set_copyright("Copyright © Jean-François Fortin Tam & Wout Clymans") |
70 | + self.about.set_comments(_("Be notified of everything")) |
71 | + self.about.set_license(license) |
72 | + #self.wTree.set_wrap_license(license) |
73 | + gtk.about_dialog_set_url_hook(lambda about, url: show_webpage(url)) |
74 | + self.about.set_website("http://specto.sourceforge.net") |
75 | + self.about.set_website_label(_("Specto's Website")) |
76 | + self.about.set_authors(authors) |
77 | + #self.about.set_documenters(documenters) |
78 | + #self.about.set_artists(artists) |
79 | + self.about.set_translator_credits(translator_credits) |
80 | + self.about.set_logo(logo) |
81 | + |
82 | + icon = gtk.gdk.pixbuf_new_from_file(os.path.join(self.specto.PATH, "icons/specto_window_icon.png")) |
83 | + self.about.set_icon(icon) |
84 | + |
85 | + self.about.connect("response", lambda d, r: self.close()) |
86 | + |
87 | + self.about.show_all() |
88 | + |
89 | + def close(self): |
90 | + self.about.destroy() |
91 | + |
92 | + |
93 | +if __name__ == "__main__": |
94 | + #run the gui |
95 | + app = About() |
96 | + gtk.main() |
97 | |
98 | === added file 'build/lib.linux-i686-2.6/spectlib/add_watch.py' |
99 | --- build/lib.linux-i686-2.6/spectlib/add_watch.py 1970-01-01 00:00:00 +0000 |
100 | +++ build/lib.linux-i686-2.6/spectlib/add_watch.py 2012-03-14 09:03:18 +0000 |
101 | @@ -0,0 +1,278 @@ |
102 | +# -*- coding: utf-8 -*- |
103 | + |
104 | +# Specto , Unobtrusive event notifier |
105 | +# |
106 | +# add_watch.py |
107 | +# |
108 | +# See the AUTHORS file for copyright ownership information |
109 | + |
110 | +# This program is free software; you can redistribute it and/or |
111 | +# modify it under the terms of the GNU General Public |
112 | +# License as published by the Free Software Foundation; either |
113 | +# version 2 of the License, or (at your option) any later version. |
114 | +# |
115 | +# This program is distributed in the hope that it will be useful, |
116 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
117 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
118 | +# General Public License for more details. |
119 | +# |
120 | +# You should have received a copy of the GNU General Public |
121 | +# License along with this program; if not, write to the |
122 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
123 | +# Boston, MA 02111-1307, USA. |
124 | + |
125 | +import os |
126 | +try: |
127 | + import pygtk |
128 | + pygtk.require("2.0") |
129 | +except: |
130 | + pass |
131 | + |
132 | +try: |
133 | + import gtk |
134 | + import spectlib.gtkutil |
135 | +except: |
136 | + pass |
137 | + |
138 | + |
139 | +class Add_watch: |
140 | + """Class to create the add watch dialog.""" |
141 | + # Please do not use confusing widget names such as 'lbl' and 'tbl', |
142 | + # Use full names like 'label' and 'table'. |
143 | + def __init__(self, specto, notifier, watch_type): |
144 | + self.specto = specto |
145 | + self.notifier = notifier |
146 | + #create tree |
147 | + uifile = os.path.join(self.specto.PATH, "uis/add_watch.ui") |
148 | + windowname = "add_watch" |
149 | + self.builder = gtk.Builder() |
150 | + self.builder.set_translation_domain("specto") |
151 | + self.builder.add_from_file(uifile) |
152 | + |
153 | + self.watch_type = watch_type |
154 | + #save the option for hiding the table |
155 | + self.option_visible = -1 |
156 | + |
157 | + #catch some events |
158 | + dic = {"on_button_cancel_clicked": self.cancel_clicked, |
159 | + "on_button_add_clicked": self.add_clicked, |
160 | + "on_button_help_clicked": self.help_clicked, |
161 | + "on_add_watch_delete_event": self.delete_event, |
162 | + "check_command_toggled": self.command_toggled, |
163 | + "check_open_toggled": self.open_toggled, |
164 | + "on_refresh_unit_changed": self.set_refresh_values} |
165 | + |
166 | + #attach the events |
167 | + self.builder.connect_signals(dic) |
168 | + |
169 | + self.add_watch = self.builder.get_object("add_watch") |
170 | + icon = gtk.gdk.pixbuf_new_from_file(os.path.join(self.specto.PATH, "icons/specto_window_icon.png")) |
171 | + self.add_watch.set_icon(icon) |
172 | + self.add_watch.set_resizable(False) |
173 | + |
174 | + self.name = self.builder.get_object("name") |
175 | + self.refresh = self.builder.get_object("refresh") |
176 | + self.refresh_unit = self.builder.get_object("refresh_unit") |
177 | + |
178 | + #create the gui |
179 | + self.plugins_ = {} |
180 | + self.watch_options = {} |
181 | + |
182 | + self.set_options(watch_type) |
183 | + |
184 | + #set the default values |
185 | + self.refresh_unit.set_active(2) |
186 | + self.refresh.set_value(1.0) |
187 | + |
188 | + self.name.grab_focus() |
189 | + |
190 | + def set_options(self, watch_type): |
191 | + """ Show the table with the right watch options. """ |
192 | + self.watch_options[watch_type] = [] |
193 | + if hasattr(self.specto.watch_db.plugin_dict[watch_type], 'get_add_gui_info'): |
194 | + values = self.specto.watch_db.plugin_dict[watch_type].get_add_gui_info() |
195 | + else: |
196 | + values = [] |
197 | + |
198 | + try: |
199 | + if self.specto.watch_db.plugin_dict[watch_type].dbus_watch == True: |
200 | + self.refresh.hide() |
201 | + self.refresh_unit.hide() |
202 | + self.builder.get_object("label_refresh1").hide() |
203 | + except: |
204 | + pass |
205 | + |
206 | + #create the options gui |
207 | + if len(values) > 0: |
208 | + self.table = gtk.Table(rows=len(values), columns=1, homogeneous=False) |
209 | + self.table.set_row_spacings(6) |
210 | + self.table.set_col_spacings(6) |
211 | + self.watch_options[watch_type] = {} |
212 | + |
213 | + i = 0 |
214 | + for value, widget in values: |
215 | + table, _widget = widget.get_object() |
216 | + self.table.attach(table, 0, 1, i, i + 1) |
217 | + self.watch_options[watch_type].update({value: widget}) |
218 | + i += 1 |
219 | + |
220 | + self.table.show() |
221 | + vbox = self.builder.get_object("vbox_watch_options") |
222 | + vbox.pack_start(self.table, False, False, 0) |
223 | + |
224 | + def set_refresh_values(self, widget): |
225 | + """ Set the max and min values for the refresh unit. """ |
226 | + digits = 0 |
227 | + climb_rate = 1.0 |
228 | + refresh_unit = self.refresh_unit.get_active() |
229 | + self.old_refresh_value = self.refresh.get_value_as_int() # Grab the current value for reuse after the scale changes |
230 | + |
231 | + # Set the new ranges for the refresh value spinbutton |
232 | + if refresh_unit == 0 or refresh_unit == 1: |
233 | + adjustment = gtk.Adjustment(value=1, lower=1, upper=60, step_incr=1, page_incr=10, page_size=0) |
234 | + if refresh_unit == 2: |
235 | + adjustment = gtk.Adjustment(value=1, lower=1, upper=24, step_incr=1, page_incr=10, page_size=0) |
236 | + if refresh_unit == 3: |
237 | + adjustment = gtk.Adjustment(value=1, lower=1, upper=365, step_incr=1, page_incr=30, page_size=0) |
238 | + |
239 | + self.refresh.configure(adjustment, climb_rate, digits) |
240 | + self.refresh.set_value(self.old_refresh_value) # Reuse the previous value, otherwise setting the new scales will reset it to 1 |
241 | + |
242 | + def add_clicked(self, widget): |
243 | + """ |
244 | + Add the watch to the watches repository. |
245 | + """ |
246 | + values = {} |
247 | + #get the standard options from a watch |
248 | + values['name'] = self.name.get_text() |
249 | + |
250 | + #check if the watch is unique |
251 | + if self.specto.watch_io.is_unique_watch(values['name']): |
252 | + unique_dialog = Unique_Dialog(self.specto) |
253 | + result = unique_dialog.run() |
254 | + |
255 | + if result ==1: |
256 | + self.name.grab_focus() |
257 | + else: #edit the existing watch |
258 | + self.add_watch.hide_all() |
259 | + name = values['name'] |
260 | + self.notifier.show_edit_watch(-1, name) |
261 | + |
262 | + else: |
263 | + values['refresh'] = self.specto.watch_db.set_interval(self.refresh.get_value_as_int(), self.refresh_unit.get_active()) |
264 | + values['type'] = self.watch_type |
265 | + values['active'] = True |
266 | + values['last_changed'] = "" |
267 | + values['changed'] = False |
268 | + if self.builder.get_object("check_command").get_active() == True: |
269 | + values['command'] = self.builder.get_object("entry_changed_command").get_text() |
270 | + |
271 | + if self.builder.get_object("check_open").get_active() == True: |
272 | + values['open_command'] = self.builder.get_object("entry_open_command").get_text() |
273 | + use_standard_command = False |
274 | + else: |
275 | + values['open_command'] = "" |
276 | + use_standard_command = True |
277 | + |
278 | + if hasattr(self.specto.watch_db.plugin_dict[values['type']], 'get_add_gui_info'): |
279 | + gui_values = self.specto.watch_db.plugin_dict[values['type']].get_add_gui_info() |
280 | + window_options = self.watch_options[values['type']] |
281 | + |
282 | + for key in window_options: |
283 | + values[key] = window_options[key].get_value() |
284 | + window_options[key].set_color(0xFFFF, 0xFFFF, 0xFFFF) |
285 | + |
286 | + self.builder.get_object("name").modify_base(gtk.STATE_NORMAL, gtk.gdk.Color(0xFFFF, 0xFFFF, 0xFFFF)) |
287 | + |
288 | + try: |
289 | + id = self.specto.watch_db.create({0: values})[0] #write the options in the configuration file |
290 | + except AttributeError, error_fields: |
291 | + fields = str(error_fields).split(",") |
292 | + i = 1 |
293 | + for field in fields: |
294 | + if field == " name": |
295 | + self.builder.get_object("name").modify_base(gtk.STATE_NORMAL, gtk.gdk.Color(65535, 0, 0)) |
296 | + self.builder.get_object("name").grab_focus() |
297 | + else: |
298 | + field = window_options[field.strip()] |
299 | + if i == 1: |
300 | + field.grab_focus() |
301 | + i = 0 |
302 | + field.set_color(65535, 0, 0) |
303 | + else: |
304 | + self.add_watch.destroy() |
305 | + if use_standard_command: |
306 | + try: |
307 | + self.specto.watch_db[id].open_command = self.specto.watch_db[id].standard_open_command |
308 | + except: |
309 | + self.specto.watch_db[id].open_command = "" |
310 | + #very simple dialog to display, there is no smtp server in the gconf and block any try to send mail |
311 | + if (self.specto.specto_gconf.get_entry("smtp_entry") == "") and ( values['mail'] != ""): |
312 | + boite = gtk.Dialog("Attention !", self.add_watch, |
313 | + gtk.DIALOG_MODAL, |
314 | + (gtk.STOCK_OK, gtk.RESPONSE_OK)) |
315 | + |
316 | + label2 = gtk.Label() |
317 | + label2.set_text("Veuillez renseigner les paramètres d'envoi d'email dans préférences \n L'envoi de mail n'est pas possible pour l'instant, les autres fonctionnalités fonctionnent normalement") |
318 | + boite.vbox.pack_start(label2, True, False, 0) |
319 | + boite.vbox.show_all() |
320 | + boite.run() |
321 | + boite.destroy() |
322 | + |
323 | + |
324 | + self.specto.watch_io.write_watch(values) |
325 | + self.notifier.add_notifier_entry(id) |
326 | + self.specto.watch_db[id].start() |
327 | + |
328 | + def help_clicked(self, widget): |
329 | + """ Call the show help function. """ |
330 | + self.specto.util.show_webpage("http://code.google.com/p/specto/wiki/AddingWatches") |
331 | + |
332 | + def cancel_clicked(self, widget): |
333 | + """ Destroy the add watch window. """ |
334 | + self.add_watch.destroy() |
335 | + |
336 | + def delete_event(self, widget, event, data=None): |
337 | + """ Destroy the window. """ |
338 | + self.add_watch.destroy() |
339 | + return True |
340 | + |
341 | + def command_toggled(self, widget): |
342 | + sensitive = self.builder.get_object("check_command").get_active() |
343 | + self.builder.get_object("entry_changed_command").set_sensitive(sensitive) |
344 | + |
345 | + def open_toggled(self, widget): |
346 | + sensitive = self.builder.get_object("check_open").get_active() |
347 | + self.builder.get_object("entry_open_command").set_sensitive(sensitive) |
348 | + |
349 | + |
350 | +class Unique_Dialog: |
351 | + """ |
352 | + Class to create a message when you add a watch with an existing name. |
353 | + """ |
354 | + |
355 | + def __init__(self, specto): |
356 | + self.specto = specto |
357 | + self.uifile = os.path.join(self.specto.PATH, "uis/dialog_add_watch.ui") |
358 | + self.dialogname = "dialog" |
359 | + self.builder = gtk.Builder() |
360 | + self.builder.set_translation_domain("specto") |
361 | + self.builder.add_from_file(self.uifile) |
362 | + self.unique_dialog = self.builder.get_object("dialog") |
363 | + |
364 | + def run(self): |
365 | + """ Show the unique dialog. """ |
366 | + icon = gtk.gdk.pixbuf_new_from_file(os.path.join(self.specto.PATH, "icons/specto_window_icon.png")) |
367 | + self.unique_dialog.set_icon(icon) |
368 | + self.unique_dialog.set_resizable(False) |
369 | + result = self.unique_dialog.run() |
370 | + |
371 | + self.unique_dialog.destroy() |
372 | + |
373 | + return result |
374 | + |
375 | + |
376 | +if __name__ == "__main__": |
377 | + #run the gui |
378 | + app = Add_watch() |
379 | + gtk.main() |
380 | |
381 | === added file 'build/lib.linux-i686-2.6/spectlib/balloons.py' |
382 | --- build/lib.linux-i686-2.6/spectlib/balloons.py 1970-01-01 00:00:00 +0000 |
383 | +++ build/lib.linux-i686-2.6/spectlib/balloons.py 2012-03-14 09:03:18 +0000 |
384 | @@ -0,0 +1,102 @@ |
385 | +# -*- coding: utf-8 -*- |
386 | + |
387 | +# Specto , Unobtrusive event notifier |
388 | +# |
389 | +# balloons.py |
390 | +# |
391 | +# See the AUTHORS file for copyright ownership information |
392 | + |
393 | +# This program is free software; you can redistribute it and/or |
394 | +# modify it under the terms of the GNU General Public |
395 | +# License as published by the Free Software Foundation; either |
396 | +# version 2 of the License, or (at your option) any later version. |
397 | +# |
398 | +# This program is distributed in the hope that it will be useful, |
399 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
400 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
401 | +# General Public License for more details. |
402 | +# |
403 | +# You should have received a copy of the GNU General Public |
404 | +# License along with this program; if not, write to the |
405 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
406 | +# Boston, MA 02111-1307, USA. |
407 | + |
408 | +import pygtk |
409 | +pygtk.require('2.0') |
410 | +import pynotify |
411 | +import sys |
412 | +import gtk |
413 | +import spectlib.util |
414 | +from time import sleep |
415 | + |
416 | +notifyInitialized = False |
417 | + |
418 | + |
419 | +class NotificationToast: |
420 | + _notifyRealm = 'Specto' |
421 | + _Urgencies = {'low': pynotify.URGENCY_LOW, |
422 | + 'critical': pynotify.URGENCY_CRITICAL, |
423 | + 'normal': pynotify.URGENCY_NORMAL} |
424 | + |
425 | + def __open_watch(self, n, action, id): |
426 | + if self.specto.notifier.open_watch(id): |
427 | + self.specto.notifier.mark_watch_as_read('', id) |
428 | + |
429 | + def __init__(self, specto, notifier): |
430 | + global notifyInitialized |
431 | + self.specto = specto |
432 | + self.notifier = notifier |
433 | + |
434 | + if not notifyInitialized: |
435 | + pynotify.init(self._notifyRealm) |
436 | + notifyInitialized = True |
437 | + |
438 | + # Check the features available from the notification daemon |
439 | + self.capabilities = {'actions': False, |
440 | + 'body': False, |
441 | + 'body-hyperlinks': False, |
442 | + 'body-images': False, |
443 | + 'body-markup': False, |
444 | + 'icon-multi': False, |
445 | + 'icon-static': False, |
446 | + 'sound': False, |
447 | + 'image/svg+xml': False, |
448 | + 'append': False} |
449 | + caps = pynotify.get_server_caps() |
450 | + if caps is None: |
451 | + print "Failed to receive server caps." |
452 | + sys.exit(1) |
453 | + for cap in caps: |
454 | + self.capabilities[cap] = True |
455 | + |
456 | + def show_toast(self, body, icon=None, urgency="low", summary=_notifyRealm, name=None): |
457 | + tray_x = 0 |
458 | + tray_y = 0 |
459 | + |
460 | + if notifyInitialized: |
461 | + sleep(0.5) # FIXME: issue #43, associate the balloon with the notification icon properly. Currently, this is a hack to leave time for the tray icon to appear before getting its coordinates |
462 | + if self.notifier.tray: |
463 | + tray_x = self.notifier.tray.get_x() |
464 | + tray_y = self.notifier.tray.get_y() |
465 | + else: |
466 | + tray_x = 0 |
467 | + tray_y = 0 |
468 | + self.toast = pynotify.Notification(summary, body) |
469 | + if name: |
470 | + # If name is not None and exists in specto.watch_db, a button is added to the notification |
471 | + w = self.specto.watch_db.find_watch(name) |
472 | + if w != -1 and self.capabilities["actions"]: # Don't request action buttons if the notification daemon (ex: notify-osd) rejects them |
473 | + self.toast.add_action("clicked", gtk.stock_lookup(gtk.STOCK_JUMP_TO)[1].replace('_', ''), self.__open_watch, w) |
474 | + self.toast.set_urgency(self._Urgencies[urgency]) |
475 | + if icon: |
476 | + #self.toast.set_property('icon-name', icon) # We now use a pixbuf in the line below to allow themable icons |
477 | + self.toast.set_icon_from_pixbuf(icon) |
478 | + |
479 | + if tray_x != 0 and tray_y != 0: # grab the x and y position of the tray icon and make the balloon emerge from it |
480 | + self.toast.set_hint("x", tray_x) |
481 | + self.toast.set_hint("y", tray_y) |
482 | + |
483 | + try: |
484 | + self.toast.show() |
485 | + except: |
486 | + self.specto.logger.log(_("Cannot display notification message. Make sure that libnotify and D-Bus are available on your system."), "error", self.specto) |
487 | |
488 | === added file 'build/lib.linux-i686-2.6/spectlib/bdd.py' |
489 | --- build/lib.linux-i686-2.6/spectlib/bdd.py 1970-01-01 00:00:00 +0000 |
490 | +++ build/lib.linux-i686-2.6/spectlib/bdd.py 2012-03-14 09:03:18 +0000 |
491 | @@ -0,0 +1,317 @@ |
492 | +# -*- coding: utf-8 -*- |
493 | + |
494 | +# Specto , Unobtrusive event notifier |
495 | +# |
496 | +# bdd.py |
497 | +# |
498 | +# See the AUTHORS file for copyright ownership information |
499 | + |
500 | +# This program is free software; you can redistribute it and/or |
501 | +# modify it under the terms of the GNU General Public |
502 | +# License as published by the Free Software Foundation; either |
503 | +# version 2 of the License, or (at your option) any later version. |
504 | +# |
505 | +# This program is distributed in the hope that it will be useful, |
506 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
507 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
508 | +# General Public License for more details. |
509 | +# |
510 | +# You should have received a copy of the GNU General Public |
511 | +# License along with this program; if not, write to the |
512 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
513 | +# Boston, MA 02111-1307, USA. |
514 | + |
515 | +from sqlalchemy import MetaData, create_engine, Column, Integer, String, Text, Boolean, Float, DateTime |
516 | +from sqlalchemy.orm import scoped_session, sessionmaker, mapper, column_property |
517 | +from sqlalchemy.schema import Table |
518 | +import datetime |
519 | + |
520 | +class Group(object): |
521 | + """ This class represents the group information """ |
522 | + def __init__(self, name="", description=""): |
523 | + self.name = name |
524 | + self.description = description |
525 | + self.listmail = [] |
526 | + |
527 | + def adduser(self, mail): |
528 | + self.listmail.append(mail) |
529 | + |
530 | + def deluser(self, mail): |
531 | + pass |
532 | + |
533 | + def getinfo(self): |
534 | + return [self.name, self.description] |
535 | + |
536 | + def getmail(self): |
537 | + return self.listmail |
538 | + |
539 | +class Mail(object): |
540 | + """This class represents all the mail information""" |
541 | + |
542 | + def __init__(self, name="", firstname="", mail="", group=""): |
543 | + |
544 | + self.name = name |
545 | + self.firstname = firstname |
546 | + self.mail = mail |
547 | + self.group = group |
548 | + |
549 | + def getinfo(self): |
550 | + return [self.name, self.firstname, self.mail, self.group] |
551 | + |
552 | + def setinfo(self, name, firstname, mail, group): |
553 | + self.name = name |
554 | + self.firstname = firstname |
555 | + self.mail = mail |
556 | + self.group = group |
557 | + |
558 | +class List_rss(object): |
559 | + """ class to save alert in rss page """ |
560 | + def __init__(self,title,link,description,page,pattern,mail,observateur): |
561 | + self.title = title |
562 | + self.link = link |
563 | + self.description = description |
564 | + self.page = page.decode('utf-8') |
565 | + self.pattern = pattern |
566 | + self.mail = mail |
567 | + self.obs = observateur |
568 | + |
569 | + |
570 | +class List_html(object): |
571 | + """ class to save alert in html page """ |
572 | + def __init__(self,txt,link,page,pattern,mail,observateur): |
573 | + self.txt = txt |
574 | + self.link = link |
575 | + self.page = page |
576 | + self.pattern = pattern |
577 | + self.mail = mail |
578 | + self.obs = observateur |
579 | + |
580 | +class Crawl(object): |
581 | + """ class to save already crawled webpage """ |
582 | + def __init__(self,pid, curl, title): |
583 | + self.parentid = pid |
584 | + self.url = curl |
585 | + self.title = title |
586 | + |
587 | +#class Save_watch(object): |
588 | +# pass |
589 | + |
590 | +class Cache(object): |
591 | + """ class to save capture of page """ |
592 | + def __init__(self, name, page, size): |
593 | + self.name = name |
594 | + self.page = page |
595 | + self.size = size |
596 | + |
597 | +class Queue(object): |
598 | + """ class to get a queue to crawl """ |
599 | + def __init__(self,parent,depth,url): |
600 | + self.parent = parent |
601 | + self.depth = depth |
602 | + self.url = url |
603 | + |
604 | +class Bdd( object ): |
605 | + """this is an sql handler""" |
606 | + def __init__(self,**datas): |
607 | + url = self.url(**datas) |
608 | + self.metadata = MetaData(url) |
609 | + self.table_contact = Table('contact', self.metadata, |
610 | + Column('id', Integer, primary_key=True), |
611 | + Column('name', String(40)), |
612 | + Column('firstname', String(40)), |
613 | + Column('mail', String(40)), |
614 | + Column('group', String(40)), |
615 | + ) |
616 | + self.table_group = Table('groupe', self.metadata, |
617 | + Column('id_g', Integer, primary_key=True), |
618 | + Column('name', String(40)), |
619 | + Column('description', String(40)), |
620 | + ) |
621 | + self.table_list_rss = Table('list_rss', self.metadata, |
622 | + Column('id', Integer, primary_key=True), |
623 | + Column('title', String(1000)), |
624 | + Column('link', Text), |
625 | + Column('description', Text), |
626 | + Column('page', Text), |
627 | + Column('pattern', Text), |
628 | + Column('mail', String(60)), |
629 | + Column('watch', String(40)), |
630 | + Column('date', DateTime(timezone=True), default=datetime.datetime.now()) |
631 | + ) |
632 | + self.table_list_html = Table('list_html', self.metadata, |
633 | + Column('id', Integer, primary_key=True), |
634 | + Column('txt', String(1000)), |
635 | + Column('link', Text), |
636 | + Column('page', Text), |
637 | + Column('pattern', Text), |
638 | + Column('mail', String(60)), |
639 | + Column('watch', String(40)), |
640 | + Column('date', DateTime(timezone=True), default=datetime.datetime.now()) |
641 | + ) |
642 | + """self.table_watch = Table('watch', self.metadata, |
643 | + Column('id', Integer, primary_key=True), |
644 | + Column('name', String(60)), |
645 | + Column('username', String(60)), |
646 | + Column('redirect', Boolean), |
647 | + Column('error_margin', Float), |
648 | + Column('pattern', Text), |
649 | + Column('open_command', Text), |
650 | + Column('changed', Boolean), |
651 | + Column('last_changed', Text), |
652 | + Column('refresh', Integer), |
653 | + Column('uri', Text), |
654 | + Column('command', Text), |
655 | + Column('mail', String(60)), |
656 | + Column('active', Boolean), |
657 | + Column('password', String(60)), |
658 | + Column('type', String(60)), |
659 | + Column('crawl', Boolean), |
660 | + Column('deep', Integer), |
661 | + )don't work""" |
662 | + """self.table_crawl = Table('crawl', self.metadata, |
663 | + Column('id', Integer, primary_key=True), |
664 | + Column('parent_id', Integer), |
665 | + Column('depth', Integer), |
666 | + Column('url', String(60)), |
667 | + Column('title', Text), |
668 | + Column('date', DateTime), |
669 | + Column('id_watch', Integer), |
670 | + Column('name_watch', String(60)), |
671 | + Column('page', Text), |
672 | + Column('size', Integer), |
673 | + ) for now don't work with this table but more intersting for future""" |
674 | + self.table_cache = Table('cache', self.metadata, |
675 | + Column('id', Integer, primary_key=True), |
676 | + Column('name', String(60)), |
677 | + Column('page', Text), |
678 | + Column('size', Integer), |
679 | + ) |
680 | + self.table_crawl = Table('crawl', self.metadata, |
681 | + Column('id',Integer,primary_key=True), |
682 | + Column('parentid',Integer), |
683 | + Column('url',Text), |
684 | + Column('title',Text), |
685 | + Column('date', DateTime(timezone=True), default=datetime.datetime.now()), |
686 | + ) |
687 | + self.table_queue = Table('queue', self.metadata, |
688 | + Column('id',Integer,primary_key=True), |
689 | + Column('parent',Integer), |
690 | + Column('depth',Integer), |
691 | + Column('url',Text), |
692 | + ) |
693 | + |
694 | + engine = create_engine(url) |
695 | + self.Session = scoped_session(sessionmaker(bind=engine,autoflush=True,autocommit=True)) |
696 | + self.session = self.Session() |
697 | + #if table don't exist we create them |
698 | + try: |
699 | + if not engine.engine.has_table('contact'): |
700 | + engine.create(self.table_contact) |
701 | + if not engine.engine.has_table('groupe'): |
702 | + engine.create(self.table_group) |
703 | + if not engine.engine.has_table('list_rss'): |
704 | + engine.create(self.table_list_rss) |
705 | + if not engine.engine.has_table('list_html'): |
706 | + engine.create(self.table_list_html) |
707 | + if not engine.engine.has_table('watch'): |
708 | + engine.create(self.table_watch) |
709 | + if not engine.engine.has_table('cache'): |
710 | + engine.create(self.table_cache) |
711 | + if not engine.engine.has_table('crawl'): |
712 | + engine.create(self.table_crawl) |
713 | + if not engine.engine.has_table('queue'): |
714 | + engine.create(self.table_queue) |
715 | + except Exception, err: |
716 | + print err |
717 | + #Map class with table |
718 | + contact_mapper = mapper(Mail,self.table_contact) |
719 | + group_mapper = mapper(Group,self.table_group) |
720 | + list_rss_mapper = mapper(List_rss,self.table_list_rss) |
721 | + list_html_mapper = mapper(List_html,self.table_list_html) |
722 | + #list_watch_mapper = mapper(Save_watch,self.table_watch) |
723 | + cache_mapper = mapper(Cache,self.table_cache) |
724 | + crawl_mapper = mapper(Crawl,self.table_crawl) |
725 | + queue_mapper = mapper(Queue,self.table_queue) |
726 | + |
727 | + def url( self, **datas): |
728 | + if datas["type"]=="sqlite": |
729 | + return "%(type)s:///%(directory)s"%datas |
730 | + else: |
731 | + return "%(type)s://%(user)s:%(pass)s@%(host)s:%(port)s/%(name)s"%datas |
732 | + |
733 | + def getAll(self,obj): |
734 | + return self.session.query(obj).all() |
735 | + |
736 | + def get(self, obj, name): |
737 | + try: |
738 | + return self.session.query(obj).filter(getattr(Cache,"name") == "%s"%name).one() |
739 | + except Exception, err: |
740 | + print err |
741 | + return 'True' |
742 | + |
743 | + def getlink(self, obj, name): |
744 | + try: |
745 | + return self.session.query(obj).filter(getattr(Queue,"url") == "%s"%name).one() |
746 | + except: |
747 | + return 'True' |
748 | + |
749 | + def getqueue(self, obj): |
750 | + try: |
751 | + return self.session.query(obj).first() |
752 | + except Exception, err: |
753 | + print err |
754 | + return 'False' |
755 | + |
756 | + def add(self, obj): |
757 | + """ Add a row in the table matching with object type """ |
758 | + try: |
759 | + self.session.begin(subtransactions=True) |
760 | + self.session.add(obj) |
761 | + self.session.flush() |
762 | + self.session.commit() |
763 | + except Exception,err: |
764 | + self.session.rollback() |
765 | + print err |
766 | + finally: |
767 | + try: |
768 | + pass |
769 | + #self.session.close() |
770 | + except: |
771 | + pass |
772 | + |
773 | + def delete(self,obj): |
774 | + """ delete the row in table matching with object """ |
775 | + try: |
776 | + self.session.begin(subtransactions=True) |
777 | + self.session.delete(obj) |
778 | + self.session.flush() |
779 | + self.session.commit() |
780 | + #self.session.close() |
781 | + except Exception, err: |
782 | + #print "probleme suppression" |
783 | + print err |
784 | + |
785 | + def updatecontact(self,obj,newname): |
786 | + self.session.begin(subtransactions=True) |
787 | + for c in self.session.query(type(obj)): |
788 | + if c.group == obj.group: |
789 | + c.group = newname |
790 | + self.session.flush() |
791 | + self.session.commit() |
792 | + |
793 | + def updatepage(self, obj, new): |
794 | + self.session.begin(subtransactions=True) |
795 | + for c in self.session.query(type(obj)): |
796 | + if c.page == obj.page: |
797 | + c.page = new |
798 | + self.session.flush() |
799 | + self.session.commit() |
800 | + |
801 | + def update(self,obj,column,new): |
802 | + self.session.begin(subtransactions=True) |
803 | + for c in self.session.query(type(obj)): |
804 | + if c.column == obj.column: |
805 | + c.column = new |
806 | + self.session.flush() |
807 | + self.session.commit() |
808 | +#can be in the same method but i didn't find the correct syntax |
809 | |
810 | === added file 'build/lib.linux-i686-2.6/spectlib/config.py' |
811 | --- build/lib.linux-i686-2.6/spectlib/config.py 1970-01-01 00:00:00 +0000 |
812 | +++ build/lib.linux-i686-2.6/spectlib/config.py 2012-03-14 09:03:18 +0000 |
813 | @@ -0,0 +1,104 @@ |
814 | +# -*- coding: utf-8 -*- |
815 | + |
816 | +# Specto , Unobtrusive event notifier |
817 | +# |
818 | +# config.py |
819 | +# |
820 | +# See the AUTHORS file for copyright ownership information |
821 | + |
822 | +# This program is free software; you can redistribute it and/or |
823 | +# modify it under the terms of the GNU General Public |
824 | +# License as published by the Free Software Foundation; either |
825 | +# version 2 of the License, or (at your option) any later version. |
826 | +# |
827 | +# This program is distributed in the hope that it will be useful, |
828 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
829 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
830 | +# General Public License for more details. |
831 | +# |
832 | +# You should have received a copy of the GNU General Public |
833 | +# License along with this program; if not, write to the |
834 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
835 | +# Boston, MA 02111-1307, USA. |
836 | + |
837 | +class Integer(): |
838 | + """A config node containing a integer value. |
839 | + Supports restricting the valid values to a range. |
840 | + """ |
841 | + |
842 | + def __init__(self, mandatory, low=None, high=None): |
843 | + self.mandatory = mandatory |
844 | + self.low = low |
845 | + self.high = high |
846 | + |
847 | + def checkRestrictions(self, value): |
848 | + try: |
849 | + val = int(value) |
850 | + except ValueError: |
851 | + return False, -1 |
852 | + return True, val |
853 | + |
854 | + def getStandardValue(self): |
855 | + return -1 |
856 | + |
857 | + |
858 | +class String(): |
859 | + """A config node containing a string value.""" |
860 | + |
861 | + def __init__(self, mandatory): |
862 | + self.mandatory = mandatory |
863 | + |
864 | + def checkRestrictions(self, value): |
865 | + try: |
866 | + val = str(value) |
867 | + except ValueError: |
868 | + return False |
869 | + return True, val |
870 | + |
871 | + def getStandardValue(self): |
872 | + return "" |
873 | + |
874 | + |
875 | +class Dec(): |
876 | + """ |
877 | + A config node containing a decimal value. |
878 | + """ |
879 | + |
880 | + def __init__(self, mandatory): |
881 | + self.mandatory = mandatory |
882 | + |
883 | + def checkRestrictions(self, value): |
884 | + try: |
885 | + val = float(value) |
886 | + except ValueError: |
887 | + return False |
888 | + return True, val |
889 | + |
890 | + def getStandardValue(self): |
891 | + return -1 |
892 | + |
893 | + |
894 | +class Boolean(): |
895 | + """ |
896 | + A config node containing a boolean value. |
897 | + """ |
898 | + |
899 | + def __init__(self, mandatory): |
900 | + self.mandatory = mandatory |
901 | + |
902 | + def checkRestrictions(self, value): |
903 | + valid = False |
904 | + if value == "True" or value == 1 or value == True: |
905 | + val = True |
906 | + valid = True |
907 | + if value == "False" or value == 0 or value == False: |
908 | + val = False |
909 | + valid = True |
910 | + |
911 | + if valid == False: |
912 | + return False, "" |
913 | + else: |
914 | + return True, val |
915 | + |
916 | + def getStandardValue(self): |
917 | + return False |
918 | |
919 | === added file 'build/lib.linux-i686-2.6/spectlib/console.py' |
920 | --- build/lib.linux-i686-2.6/spectlib/console.py 1970-01-01 00:00:00 +0000 |
921 | +++ build/lib.linux-i686-2.6/spectlib/console.py 2012-03-14 09:03:18 +0000 |
922 | @@ -0,0 +1,54 @@ |
923 | +# -*- coding: utf-8 -*- |
924 | + |
925 | +# Specto , Unobtrusive event notifier |
926 | +# |
927 | +# notifier.py |
928 | +# |
929 | +# See the AUTHORS file for copyright ownership information |
930 | + |
931 | +# This program is free software; you can redistribute it and/or |
932 | +# modify it under the terms of the GNU General Public |
933 | +# License as published by the Free Software Foundation; either |
934 | +# version 2 of the License, or (at your option) any later version. |
935 | +# |
936 | +# This program is distributed in the hope that it will be useful, |
937 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
938 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
939 | +# General Public License for more details. |
940 | +# |
941 | +# You should have received a copy of the GNU General Public |
942 | +# License along with this program; if not, write to the |
943 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
944 | +# Boston, MA 02111-1307, USA. |
945 | + |
946 | + |
947 | +class Console: |
948 | + |
949 | + def __init__(self, specto, args): |
950 | + self.specto = specto |
951 | + self.only_changed = False |
952 | + |
953 | + if args: |
954 | + if args == "--only-changed": |
955 | + self.only_changed = True |
956 | + |
957 | + def start_watches(self): |
958 | + self.specto.watch_db.restart_all_watches() |
959 | + |
960 | + def mark_watch_status(self, status, id): |
961 | + """ show the right icon for the status from the watch. """ |
962 | + watch = self.specto.watch_db[id] |
963 | + |
964 | + if status == "changed": |
965 | + print watch.name, "-", _("Watch has changed.") |
966 | + print watch.get_extra_information() |
967 | + elif self.only_changed: |
968 | + return |
969 | + elif status == "checking": |
970 | + print watch.name, "-", _("Watch started checking.") |
971 | + elif status == "idle": |
972 | + print watch.name, "-", _("Watch is idle.") |
973 | + elif status == "no-network": |
974 | + print _("No network connection detected") |
975 | + elif status == "error": |
976 | + print watch.name, "-", _("There was an error checking the watch") |
977 | |
978 | === added file 'build/lib.linux-i686-2.6/spectlib/constants.py' |
979 | --- build/lib.linux-i686-2.6/spectlib/constants.py 1970-01-01 00:00:00 +0000 |
980 | +++ build/lib.linux-i686-2.6/spectlib/constants.py 2012-03-14 09:03:18 +0000 |
981 | @@ -0,0 +1,7 @@ |
982 | +# -*- coding: utf-8 -*- |
983 | + |
984 | +# The Specto version |
985 | +VERSION = "0.3.1" |
986 | + |
987 | +# The prefix were Specto is installed to. |
988 | +PREFIX = "/usr/local" |
989 | |
990 | === added file 'build/lib.linux-i686-2.6/spectlib/contact.py' |
991 | --- build/lib.linux-i686-2.6/spectlib/contact.py 1970-01-01 00:00:00 +0000 |
992 | +++ build/lib.linux-i686-2.6/spectlib/contact.py 2012-03-14 09:03:18 +0000 |
993 | @@ -0,0 +1,330 @@ |
994 | +# -*- coding: utf-8 -*- |
995 | + |
996 | +# Specto , Unobtrusive event notifier |
997 | +# |
998 | +# contact.py |
999 | +# |
1000 | +# See the AUTHORS file for copyright ownership information |
1001 | + |
1002 | +# This program is free software; you can redistribute it and/or |
1003 | +# modify it under the terms of the GNU General Public |
1004 | +# License as published by the Free Software Foundation; either |
1005 | +# version 2 of the License, or (at your option) any later version. |
1006 | +# |
1007 | +# This program is distributed in the hope that it will be useful, |
1008 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1009 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1010 | +# General Public License for more details. |
1011 | +# |
1012 | +# You should have received a copy of the GNU General Public |
1013 | +# License along with this program; if not, write to the |
1014 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
1015 | +# Boston, MA 02111-1307, USA. |
1016 | + |
1017 | +import os |
1018 | +import gobject |
1019 | +from spectlib.bdd import Group, Mail |
1020 | +try: |
1021 | + import pygtk |
1022 | + pygtk.require("2.0") |
1023 | +except: |
1024 | + pass |
1025 | + |
1026 | +try: |
1027 | + import gtk |
1028 | +except: |
1029 | + pass |
1030 | + |
1031 | + |
1032 | +class Contact: |
1033 | + """ Display the contact window. """ |
1034 | + def __init__(self, specto, notifier): |
1035 | + |
1036 | + self.specto = specto |
1037 | + self.notifier = notifier |
1038 | + self.base = self.specto.base |
1039 | + |
1040 | + uifile = os.path.join(self.specto.PATH, "uis/contact.ui") |
1041 | + windowname = "contact" |
1042 | + self.builder = gtk.Builder() |
1043 | + self.builder.set_translation_domain("specto") |
1044 | + self.builder.add_from_file(uifile) |
1045 | + |
1046 | + #catch some events |
1047 | + dic = {"on_add_contact_clicked": self.add_contact_clicked, |
1048 | + "on_add_group_clicked": self.add_group_clicked, |
1049 | + "on_modify_button_clicked": self.modify_button_clicked, |
1050 | + "on_delete_button_clicked": self.delete_button_clicked, |
1051 | + "on_contact_view_button_press_event": self.contact_view_button_press_event} |
1052 | + |
1053 | + #attach the events |
1054 | + self.builder.connect_signals(dic) |
1055 | + self.contact = self.builder.get_object("contact") |
1056 | + self.contact.set_size_request(500,300) |
1057 | + |
1058 | + self.groupes = gtk.TreeViewColumn() |
1059 | + self.groupes.set_title("Groups") |
1060 | + |
1061 | + self.cell = gtk.CellRendererText() |
1062 | + self.groupes.pack_start(self.cell, True) |
1063 | + self.groupes.add_attribute(self.cell, "text", 0) |
1064 | + #Get the treeView from the widget Tree |
1065 | + self.contactview = self.builder.get_object("contact_view") |
1066 | + self.contactview.props.has_tooltip = True |
1067 | + self.contactview.connect("query-tooltip", self.query_tooltip_tree_view_cb) |
1068 | + self.contactview.get_selection().connect("changed", |
1069 | + self.selection_changed_cb, self.contactview) |
1070 | + |
1071 | + self.liststore1 = gtk.TreeStore(str, gobject.TYPE_PYOBJECT) |
1072 | + self.contactview.append_column(self.groupes) |
1073 | + self.contactview.set_model(self.liststore1) |
1074 | + self.gettree() |
1075 | + |
1076 | + def add_group_clicked(self, widget): |
1077 | + """Called when the use wants to add a group""" |
1078 | + #Create the dialog, show it, and store the results |
1079 | + groupDlg = Group_Dialog(self.specto) |
1080 | + result,newgroup = groupDlg.run() |
1081 | + self.already_exist = 0 |
1082 | + if (result == gtk.RESPONSE_OK): |
1083 | + it = self.liststore1.append(None, [newgroup.name, newgroup]) |
1084 | + self.base.add(newgroup) |
1085 | + |
1086 | + def add_contact_clicked(self, widget): |
1087 | + """ Open contact dialog """ |
1088 | + #Create the dialog, show it, and store the results |
1089 | + contactDlg = Contact_Dialog(self.specto, self.liststore1) |
1090 | + result,self.newuser = contactDlg.run() |
1091 | + if (result == gtk.RESPONSE_OK): |
1092 | + self.liststore1.foreach(self.add, self.newuser) |
1093 | + self.base.add(self.newuser) |
1094 | + |
1095 | + def add(self, model, path, iter, user): |
1096 | + """ add a user """ |
1097 | + value = model.get(iter, 1) |
1098 | + if value[0].name == user.group:#FIXME specto got trouble when a group got same name with a mail |
1099 | + model.append(iter, [(user.name+" "+user.firstname), user]) |
1100 | + |
1101 | + def modify_button_clicked(self, widget): |
1102 | + """ Open contact dialog for modify""" |
1103 | + #récupère les valeurs de l'élement selectionné |
1104 | + try: |
1105 | + model, iter = self.contactview.get_selection().get_selected() |
1106 | + value = model.get(iter, 1) |
1107 | + except: |
1108 | + quit |
1109 | + |
1110 | + if isinstance(value[0], Group): |
1111 | + groupDlg = Group_Dialog(self.specto) |
1112 | + groupDlg.setvalue(value[0].name, value[0].description) |
1113 | + result,self.newgroup = groupDlg.run() |
1114 | + if (result == gtk.RESPONSE_OK): |
1115 | + dest = model.append(None,[self.newgroup.name, self.newgroup]) |
1116 | + if value[0].name != self.newgroup.name: |
1117 | + nb = model.iter_n_children(iter) |
1118 | + n = 0 |
1119 | + while n < nb: |
1120 | + it = model.iter_children(iter) |
1121 | + valeurs1 = model.get(it, 1)[0] |
1122 | + valeurs0 = model.get(it, 0)[0] |
1123 | + model.remove(it) |
1124 | + #self.base.delete(valeurs1) |
1125 | + model.append(dest, [valeurs0, valeurs1]) |
1126 | + #self.base.add(Mail(valeurs1.name, valeurs1.firstname, valeurs1.mail, self.newgroup.name)) |
1127 | + #self.base.update(valeurs1,"contact",self.newgroup.name) |
1128 | + self.base.updatecontact(valeurs1,self.newgroup.name) |
1129 | + n = n + 1 |
1130 | + model.remove(iter) |
1131 | + self.base.delete(value[0]) |
1132 | + self.base.add(self.newgroup) |
1133 | + else: |
1134 | + nb = model.iter_n_children(iter) |
1135 | + n = 0 |
1136 | + while n < nb: |
1137 | + it = model.iter_children(iter) |
1138 | + valeurs1 = model.get(it, 1)[0] |
1139 | + valeurs0 = model.get(it, 0)[0] |
1140 | + model.remove(it) |
1141 | + model.append(dest, [valeurs0, valeurs1]) |
1142 | + n = n + 1 |
1143 | + model.remove(iter) |
1144 | + self.base.delete(value[0]) |
1145 | + self.base.add(self.newgroup) |
1146 | + #model.set_value(iter, 0, [self.newgroup.name, self.newgroup][0]) |
1147 | + |
1148 | + if isinstance(value[0], Mail): |
1149 | + contactDlg = Contact_Dialog(self.specto, self.liststore1) |
1150 | + contactDlg.setvalue(value[0].name, value[0].firstname, value[0].mail) |
1151 | + result,self.newuser = contactDlg.run() |
1152 | + if (result == gtk.RESPONSE_OK): |
1153 | + model.remove(iter) |
1154 | + self.base.delete(value[0]) |
1155 | + self.base.add(self.newuser) |
1156 | + self.liststore1.foreach(self.add, self.newuser) |
1157 | + |
1158 | + def delete_button_clicked(self, widget): |
1159 | + """ delete item selected """ |
1160 | + try: |
1161 | + model, iter = self.contactview.get_selection().get_selected() |
1162 | + value = model.get(iter, 1) |
1163 | + if isinstance(value[0], Group): |
1164 | + nb = model.iter_n_children(iter) |
1165 | + n = 0 |
1166 | + while n < nb: |
1167 | + it = model.iter_children(iter) |
1168 | + valeurs1 = model.get(it, 1)[0] |
1169 | + valeurs0 = model.get(it, 0)[0] |
1170 | + model.remove(it) |
1171 | + self.base.delete(valeurs1) |
1172 | + n = n + 1 |
1173 | + model.remove(iter) |
1174 | + self.base.delete(value[0]) |
1175 | + else: |
1176 | + self.base.delete(value[0]) |
1177 | + model.remove(iter) |
1178 | + except: |
1179 | + pass |
1180 | + |
1181 | + def query_tooltip_tree_view_cb(self, widget, x, y, keyboard_tip, tooltip): |
1182 | + """ show tooltip """ |
1183 | + if not widget.get_tooltip_context(x, y, keyboard_tip): |
1184 | + return False |
1185 | + else: |
1186 | + model, path, iter = widget.get_tooltip_context(x, y, keyboard_tip) |
1187 | + value = model.get(iter, 1) |
1188 | + if isinstance(value[0], Group): |
1189 | + tooltip.set_markup("%s" %(value[0].description)) |
1190 | + else: |
1191 | + tooltip.set_markup("%s" %(value[0].mail)) |
1192 | + widget.set_tooltip_row(tooltip, path) |
1193 | + return True |
1194 | + |
1195 | + def selection_changed_cb(self, selection, tree_view): |
1196 | + tree_view.trigger_tooltip_query() |
1197 | + |
1198 | + def contact_view_button_press_event(self, treeview, event): |
1199 | + """clic sur un element""" |
1200 | + if event.button == 3: |
1201 | + x = int(event.x) |
1202 | + y = int(event.y) |
1203 | + pthinfo = treeview.get_path_at_pos(x, y) |
1204 | + if pthinfo != None: |
1205 | + path, col, cellx, celly = pthinfo |
1206 | + treeview.grab_focus() |
1207 | + treeview.set_cursor( path, col, 0) |
1208 | + model = treeview.get_model() |
1209 | + iter = model.get_iter(path) |
1210 | + #Je récupère la troisième valeur |
1211 | + content = model[iter][0] |
1212 | + |
1213 | + def gettree(self): |
1214 | + listg = self.base.getAll(Group) |
1215 | + listm = self.base.getAll(Mail) |
1216 | + for group in listg: |
1217 | + it = self.liststore1.append(None, [group.name, group]) |
1218 | + |
1219 | + for mail in listm: |
1220 | + self.liststore1.foreach(self.add, mail) |
1221 | + |
1222 | +class Group_Dialog: |
1223 | + """ This class is used to show Group dialog """ |
1224 | + |
1225 | + def __init__(self, specto): |
1226 | + |
1227 | + self.specto = specto |
1228 | + uifile = os.path.join(self.specto.PATH, "uis/group_contact_dialog.ui") |
1229 | + windowname = "group_dialog" |
1230 | + self.builder = gtk.Builder() |
1231 | + self.builder.set_translation_domain("specto") |
1232 | + self.builder.add_from_file(uifile) |
1233 | + |
1234 | + def run(self): |
1235 | + self.group_dlg = self.builder.get_object("group_dialog") |
1236 | + self.result = self.group_dlg.run() |
1237 | + self.getparam() |
1238 | + self.group_dlg.destroy() |
1239 | + return self.result,self.group |
1240 | + |
1241 | + def getparam(self): |
1242 | + self.name = self.builder.get_object("groupname_entry") |
1243 | + self.n = self.name.get_text() |
1244 | + self.description = self.builder.get_object("description_entry") |
1245 | + self.d = self.description.get_text() |
1246 | + self.group = Group(self.n,self.d) |
1247 | + |
1248 | + def setvalue(self, name, description): |
1249 | + self.name = self.builder.get_object("groupname_entry") |
1250 | + self.name.set_text(name) |
1251 | + self.description = self.builder.get_object("description_entry") |
1252 | + self.description.set_text(description) |
1253 | + |
1254 | +class Contact_Dialog: |
1255 | + """ This class is used to show Contact dialog """ |
1256 | + |
1257 | + def __init__(self, specto, model): |
1258 | + |
1259 | + self.specto = specto |
1260 | + self.model = model |
1261 | + uifile = os.path.join(self.specto.PATH, "uis/contact_dialog.ui") |
1262 | + windowname = "contact_dialog" |
1263 | + self.builder = gtk.Builder() |
1264 | + self.builder.set_translation_domain("specto") |
1265 | + self.builder.add_from_file(uifile) |
1266 | + #catch some events |
1267 | + dic = {"on_combo_changed": self.combo_changed} |
1268 | + #attach the events |
1269 | + self.builder.connect_signals(dic) |
1270 | + |
1271 | + def run(self): |
1272 | + self.setparam() |
1273 | + self.contact_dlg = self.builder.get_object("contact_dialog") |
1274 | + self.result = self.contact_dlg.run() |
1275 | + self.getparam() |
1276 | + self.contact_dlg.destroy() |
1277 | + return self.result,self.email |
1278 | + |
1279 | + def combo_changed(self, widget): |
1280 | + model = self.group.get_model() |
1281 | + index = self.group.get_active() |
1282 | + if index: |
1283 | + self.groupname = model[index][0] |
1284 | + else: |
1285 | + self.groupname = "pas recu" |
1286 | + |
1287 | + def getparam(self): |
1288 | + self.name = self.builder.get_object("name_entry") |
1289 | + self.n = self.name.get_text() |
1290 | + self.firstname = self.builder.get_object("firstname_entry") |
1291 | + self.f = self.firstname.get_text() |
1292 | + self.mail = self.builder.get_object("mail_entry") |
1293 | + self.m = self.mail.get_text() |
1294 | + self.email = Mail(self.n,self.f,self.m,self.groupname) |
1295 | + |
1296 | + def setparam(self): |
1297 | + self.group = self.builder.get_object("combo") |
1298 | + self.liststore1 = gtk.ListStore(str) |
1299 | + self.case = gtk.CellRendererText() |
1300 | + self.group.pack_start(self.case, True) |
1301 | + self.group.add_attribute(self.case, 'text', 0) |
1302 | + self.liststore1.append(['Vous pouvez choisir un groupe:']) |
1303 | + self.model.foreach(self.addcombo) |
1304 | + self.group.set_model(self.liststore1) |
1305 | + self.group.set_active(0) |
1306 | + |
1307 | + def setvalue(self, name, firstname, mail): |
1308 | + self.name = self.builder.get_object("name_entry") |
1309 | + self.name.set_text(name) |
1310 | + self.firstname = self.builder.get_object("firstname_entry") |
1311 | + self.firstname.set_text(firstname) |
1312 | + self.mail = self.builder.get_object("mail_entry") |
1313 | + self.mail.set_text(mail) |
1314 | + |
1315 | + def addcombo(self, model, path, iter): |
1316 | + value = model.get(iter, 1) |
1317 | + if isinstance(value[0], Group): |
1318 | + self.liststore1.append([value[0].name]) |
1319 | + |
1320 | +if __name__ == "__main__": |
1321 | + #run the gui |
1322 | + app = Contact() |
1323 | + gtk.main() |
1324 | |
1325 | === added file 'build/lib.linux-i686-2.6/spectlib/crawl.py' |
1326 | --- build/lib.linux-i686-2.6/spectlib/crawl.py 1970-01-01 00:00:00 +0000 |
1327 | +++ build/lib.linux-i686-2.6/spectlib/crawl.py 2012-03-14 09:03:18 +0000 |
1328 | @@ -0,0 +1,149 @@ |
1329 | +# -*- coding: utf-8 -*- |
1330 | + |
1331 | +# Specto , Unobtrusive event notifier |
1332 | +# |
1333 | +# crawl.py |
1334 | +# |
1335 | +# See the AUTHORS file for copyright ownership information |
1336 | + |
1337 | +# This program is free software; you can redistribute it and/or |
1338 | +# modify it under the terms of the GNU General Public |
1339 | +# License as published by the Free Software Foundation; either |
1340 | +# version 2 of the License, or (at your option) any later version. |
1341 | +# |
1342 | +# This program is distributed in the hope that it will be useful, |
1343 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1344 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1345 | +# General Public License for more details. |
1346 | +# |
1347 | +# You should have received a copy of the GNU General Public |
1348 | +# License along with this program; if not, write to the |
1349 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
1350 | +# Boston, MA 02111-1307, USA. |
1351 | + |
1352 | +import urllib2 |
1353 | +##import lxml.html |
1354 | +from spectlib.bdd import Bdd, Crawl, Queue |
1355 | +import robotparser |
1356 | +import threading |
1357 | +import urlparse |
1358 | +import sys, re |
1359 | +import time |
1360 | + |
1361 | +class Crawler(threading.Thread): |
1362 | + """ class to crawl webpage """ |
1363 | + def __init__(self, depth, domain, base, starturl): |
1364 | + threading.Thread.__init__(self) |
1365 | + self.rp = robotparser.RobotFileParser() |
1366 | + self.crawled = [] |
1367 | + self.base = base |
1368 | + #add url to the queue |
1369 | + try: |
1370 | + self.base.add(Queue(0, 0, starturl)) |
1371 | + except Exception,err: |
1372 | + print err |
1373 | + self.crawldepth = depth |
1374 | + self.domain = domain |
1375 | + def run(self): |
1376 | + while 1: |
1377 | + try: |
1378 | + # Get the first item from the queue |
1379 | + crawling = self.base.getqueue(Queue) |
1380 | + |
1381 | + # if theres nothing in the que, then set the status to done and exit |
1382 | + # Remove the item from the queue |
1383 | + if crawling: |
1384 | + try: |
1385 | + self.base.delete(crawling) |
1386 | + except Exception,err: |
1387 | + print err |
1388 | + else: |
1389 | + return |
1390 | + except Exception, err: |
1391 | + print err |
1392 | + |
1393 | + # Crawl the link |
1394 | + self.crawl(crawling) |
1395 | + |
1396 | + def crawl(self, obj): |
1397 | + print "Crawling.........." |
1398 | + cid = obj.id |
1399 | + # parent id. 0 if start url |
1400 | + pid = obj.parent |
1401 | + # current depth |
1402 | + curdepth = obj.depth |
1403 | + # crawling url |
1404 | + curl = obj.url |
1405 | + # Split the link into its sections |
1406 | + url = urlparse.urlparse(curl) |
1407 | + |
1408 | + try: |
1409 | + # Have our robot parser grab the robots.txt file and read it |
1410 | + self.rp.set_url('http://' + url[1] + '/robots.txt') |
1411 | + self.rp.read() |
1412 | + |
1413 | + # If we're not allowed to open a url, return the function to skip it |
1414 | + if not self.rp.can_fetch('specto', curl): |
1415 | + print curl + " not allowed by robots.txt" |
1416 | + return |
1417 | + except: |
1418 | + pass |
1419 | + |
1420 | + try: |
1421 | + # Add the link to the already crawled list |
1422 | + self.crawled.append(curl) |
1423 | + except MemoryError: |
1424 | + # If the crawled array is too big, deleted it and start over |
1425 | + del self.crawled[:] |
1426 | + try: |
1427 | + request = urllib2.Request(curl) |
1428 | + request.add_header("User-Agent", "specto") |
1429 | + opener = urllib2.build_opener() |
1430 | + msg = opener.open(request).read() |
1431 | + except: |
1432 | + return |
1433 | + |
1434 | + # Find what's between the title tags |
1435 | + title = "" |
1436 | + startPos = msg.find('<title>') |
1437 | + if startPos != -1: |
1438 | + endPos = msg.find('</title>', startPos+7) |
1439 | + if endPos != -1: |
1440 | + title = msg[startPos+7:endPos] |
1441 | + |
1442 | + #with lxml library, find all link in a page |
1443 | + if curdepth < self.crawldepth: |
1444 | + html = urllib2.urlopen(curl).read() |
1445 | + etree = lxml.html.fromstring(html) |
1446 | + for href in etree.xpath("//a/@href"): |
1447 | + row = self.base.getlink(Queue, href) #check if link don't exist already |
1448 | + if row != 'True': |
1449 | + continue |
1450 | + if not href.startswith("http://"): |
1451 | + if href.startswith('/'): |
1452 | + href = 'http://' + url[1] + href #complete the url |
1453 | + elif href.startswith('#'): |
1454 | + continue |
1455 | + elif not href.startswith('http'): |
1456 | + href = urlparse.urljoin(url.geturl(),href) |
1457 | + print href #to debug |
1458 | + if href not in self.crawled: #.decode('utf-8') |
1459 | + if self.domain == True and re.search("http://"+url[1],href):#check if url is in domain |
1460 | + try: |
1461 | + self.base.add(Queue(pid, curdepth+1, href)) |
1462 | + except Exception, err: |
1463 | + print err |
1464 | + continue |
1465 | + else: |
1466 | + try: |
1467 | + self.base.add(Queue(pid, curdepth+1, href)) |
1468 | + except Exception, err: |
1469 | + print err |
1470 | + continue |
1471 | + try: |
1472 | + # Put now crawled link into the db |
1473 | + self.base.add(Crawl(pid, curl, title)) |
1474 | + except Exception, err: |
1475 | + print err |
1476 | + else: |
1477 | + pass |
1478 | |
1479 | === added file 'build/lib.linux-i686-2.6/spectlib/edit_watch.py' |
1480 | --- build/lib.linux-i686-2.6/spectlib/edit_watch.py 1970-01-01 00:00:00 +0000 |
1481 | +++ build/lib.linux-i686-2.6/spectlib/edit_watch.py 2012-03-14 09:03:18 +0000 |
1482 | @@ -0,0 +1,316 @@ |
1483 | +# -*- coding: utf-8 -*- |
1484 | + |
1485 | +# Specto , Unobtrusive event notifier |
1486 | +# |
1487 | +# add_watch.py |
1488 | +# |
1489 | +# See the AUTHORS file for copyright ownership information |
1490 | + |
1491 | +# This program is free software; you can redistribute it and/or |
1492 | +# modify it under the terms of the GNU General Public |
1493 | +# License as published by the Free Software Foundation; either |
1494 | +# version 2 of the License, or (at your option) any later version. |
1495 | +# |
1496 | +# This program is distributed in the hope that it will be useful, |
1497 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1498 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1499 | +# General Public License for more details. |
1500 | +# |
1501 | +# You should have received a copy of the GNU General Public |
1502 | +# License along with this program; if not, write to the |
1503 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
1504 | +# Boston, MA 02111-1307, USA. |
1505 | + |
1506 | +import os |
1507 | +try: |
1508 | + import pygtk |
1509 | + pygtk.require("2.0") |
1510 | +except: |
1511 | + pass |
1512 | + |
1513 | +try: |
1514 | + import gtk |
1515 | + import spectlib.gtkconfig |
1516 | +except: |
1517 | + pass |
1518 | + |
1519 | + |
1520 | +class Edit_watch: |
1521 | + """Class to create the edit watch dialog.""" |
1522 | + # Please do not use confusing widget names such as 'lbl' and 'tbl', |
1523 | + # use full names like 'label' and 'table'. |
1524 | + def __init__(self, specto, notifier, id): |
1525 | + self.specto = specto |
1526 | + self.notifier = notifier |
1527 | + self.watch = self.specto.watch_db[id] |
1528 | + # Create the tree |
1529 | + uifile = os.path.join(self.specto.PATH, "uis/edit_watch.ui") |
1530 | + windowname = "edit_watch" |
1531 | + self.builder = gtk.Builder() |
1532 | + self.builder.set_translation_domain("specto") |
1533 | + self.builder.add_from_file(uifile) |
1534 | + |
1535 | + # Catch some events |
1536 | + dic = {"on_button_cancel_clicked": self.cancel_clicked, |
1537 | + "on_button_save_clicked": self.save_clicked, |
1538 | + "on_button_remove_clicked": self.remove_clicked, |
1539 | + #"on_button_clear_clicked": self.clear_clicked, # clear error_log textfield |
1540 | + "on_button_save_as_clicked": self.save_as_clicked, # save error_log text |
1541 | + "on_edit_watch_delete_event": self.delete_event, |
1542 | + "check_command_toggled": self.command_toggled, |
1543 | + "check_open_toggled": self.open_toggled, |
1544 | + "on_refresh_unit_changed": self.set_refresh_values} |
1545 | + |
1546 | + # Attach the events |
1547 | + self.builder.connect_signals(dic) |
1548 | + |
1549 | + # Set the info from the watch |
1550 | + self.edit_watch = self.builder.get_object("edit_watch") |
1551 | + self.edit_watch.set_title(_("Edit watch: ") + self.watch.name) |
1552 | + self.builder.get_object("name").set_text(self.watch.name) |
1553 | + icon = gtk.gdk.pixbuf_new_from_file(os.path.join(self.specto.PATH, "icons/specto_window_icon.png")) |
1554 | + self.edit_watch.set_icon(icon) |
1555 | + self.edit_watch.set_resizable(False) |
1556 | + |
1557 | + refresh, refresh_unit = self.specto.watch_db.get_interval(self.watch.refresh) |
1558 | + self.builder.get_object("refresh_unit").set_active(refresh_unit) |
1559 | + self.builder.get_object("refresh").set_value(refresh) |
1560 | + |
1561 | + # Create the gui |
1562 | + self.watch_options = {} |
1563 | + self.create_edit_gui() |
1564 | + |
1565 | + if not self.specto.DEBUG: |
1566 | + self.builder.get_object("notebook1").remove_page(2) |
1567 | + else: |
1568 | + if self.builder.get_object("notebook1").get_n_pages() == 3: |
1569 | + # Put the logfile in the textview |
1570 | + log_text = self.specto.logger.watch_log(self.watch.name) |
1571 | + self.log_buffer = self.builder.get_object("error_log").get_buffer() |
1572 | + self.log_buffer.create_tag("ERROR", foreground="#a40000") |
1573 | + self.log_buffer.create_tag("INFO", foreground="#4e9a06") |
1574 | + self.log_buffer.create_tag("WARNING", foreground="#c4a000") |
1575 | + iter = self.log_buffer.get_iter_at_offset(0) |
1576 | + for line in log_text: |
1577 | + self.log_buffer.insert_with_tags_by_name(iter, line[1], line[0]) |
1578 | + |
1579 | + def cancel_clicked(self, widget): |
1580 | + """ Destroy the edit watch dialog. """ |
1581 | + self.edit_watch.destroy() |
1582 | + |
1583 | + def set_refresh_values(self, widget): |
1584 | + """ Set the max and min values for the refresh unit. """ |
1585 | + digits = 0 |
1586 | + climb_rate = 1.0 |
1587 | + refresh_unit = self.builder.get_object("refresh_unit").get_active() |
1588 | + |
1589 | + if refresh_unit == 0 or refresh_unit == 1: |
1590 | + adjustment = gtk.Adjustment(value=1, lower=1, upper=60, step_incr=1, page_incr=10, page_size=0) |
1591 | + if refresh_unit == 2: |
1592 | + adjustment = gtk.Adjustment(value=1, lower=1, upper=24, step_incr=1, page_incr=10, page_size=0) |
1593 | + if refresh_unit == 3: |
1594 | + adjustment = gtk.Adjustment(value=1, lower=1, upper=365, step_incr=1, page_incr=30, page_size=0) |
1595 | + |
1596 | + self.builder.get_object("refresh").configure(adjustment, climb_rate, digits) |
1597 | + |
1598 | + def save_clicked(self, widget): |
1599 | + """ Save the new options from the edited watch. """ |
1600 | + values = {} |
1601 | + #get the standard options from a watch |
1602 | + values['name'] = self.builder.get_object("name").get_text()#FIXME: cfgparse cannot have single quotes (') it seems. We must watch out for the watch name or arguments not to have them. |
1603 | + |
1604 | + values['type'] = self.watch.type |
1605 | + refresh_value = self.builder.get_object("refresh").get_value_as_int() |
1606 | + refresh_unit = self.builder.get_object("refresh_unit").get_active() |
1607 | + values['refresh'] = self.specto.watch_db.set_interval(refresh_value, refresh_unit) |
1608 | + values['active'] = self.watch.active |
1609 | + values['last_changed'] = self.watch.last_changed |
1610 | + |
1611 | + if self.builder.get_object("check_command").get_active() == True: |
1612 | + values['command'] = self.builder.get_object("entry_changed_command").get_text() |
1613 | + |
1614 | + if self.builder.get_object("check_open").get_active() == True: |
1615 | + values['open_command'] = self.builder.get_object("entry_open_command").get_text() |
1616 | + else: |
1617 | + values['open_command'] = "" |
1618 | + |
1619 | + if hasattr(self.specto.watch_db.plugin_dict[values['type']], 'get_add_gui_info'): |
1620 | + gui_values = self.specto.watch_db.plugin_dict[values['type']].get_add_gui_info() |
1621 | + window_options = self.watch_options[values['type']] |
1622 | + |
1623 | + for key in window_options: |
1624 | + values[key] = window_options[key].get_value() |
1625 | + window_options[key].set_color(0xFFFF, 0xFFFF, 0xFFFF) |
1626 | + |
1627 | + self.builder.get_object("name").modify_base(gtk.STATE_NORMAL, gtk.gdk.Color(0xFFFF, 0xFFFF, 0xFFFF)) |
1628 | + |
1629 | + try: |
1630 | + self.specto.watch_db[self.watch.id].set_values(values, True) |
1631 | + except AttributeError, error_fields: |
1632 | + fields = str(error_fields).split(",") |
1633 | + i = 1 |
1634 | + for field in fields: |
1635 | + if field == " name": |
1636 | + self.builder.get_object("name").modify_base(gtk.STATE_NORMAL, gtk.gdk.Color(65535, 0, 0)) |
1637 | + self.builder.get_object("name").grab_focus() |
1638 | + else: |
1639 | + field = window_options[field.strip()] |
1640 | + if i == 1: |
1641 | + field.grab_focus() |
1642 | + i = 0 |
1643 | + field.set_color(65535, 0, 0) |
1644 | + else: |
1645 | + if not self.specto.watch_io.is_unique_watch(values['name']): |
1646 | + self.specto.watch_io.replace_name(self.watch.name, values['name']) |
1647 | + # Change the name in the notifier window |
1648 | + self.specto.notifier.change_name(values['name'], self.watch.id) |
1649 | + |
1650 | + self.specto.watch_db[self.watch.id].set_values(values) |
1651 | + |
1652 | + self.specto.watch_io.write_watch(values) |
1653 | + self.specto.notifier.show_watch_info() |
1654 | + self.edit_watch.destroy() |
1655 | + |
1656 | + if self.watch.active == True: |
1657 | + self.specto.watch_db[self.watch.id].restart() |
1658 | + |
1659 | + def remove_clicked(self, widget): |
1660 | + """ Remove the watch. """ |
1661 | + dialog = spectlib.gtkconfig.RemoveDialog(_("Remove a watch"), |
1662 | + (_('<big>Remove the watch "%s"?</big>\nThis operation cannot be undone.') % self.watch.name)) |
1663 | + answer = dialog.show() |
1664 | + if answer == True: |
1665 | + self.edit_watch.destroy() |
1666 | + self.notifier.remove_notifier_entry(self.watch.id) |
1667 | + self.specto.watch_db.remove(self.watch.id) #remove the watch |
1668 | + self.specto.watch_io.remove_watch(self.watch.name) |
1669 | + if self.notifier.tray: |
1670 | + self.notifier.tray.show_tooltip() |
1671 | + |
1672 | + def clear_clicked(self, widget): |
1673 | + """ Clear the log window. """ |
1674 | + self.specto.logger.remove_watch_log(self.watch.name) |
1675 | + self.log = self.specto.logger.watch_log(self.watch.name) |
1676 | + self.logwindow.set_text(self.log) |
1677 | + |
1678 | + def save_as_clicked(self, widget): |
1679 | + """ Open the Save as dialog window. """ |
1680 | + Save_dialog(self, self.log) |
1681 | + |
1682 | + def delete_event(self, widget, event, data=None): |
1683 | + """ Destroy the window. """ |
1684 | + self.edit_watch.destroy() |
1685 | + return True |
1686 | + |
1687 | + def create_edit_gui(self): |
1688 | + """ Create the gui for the different kinds of watches. """ |
1689 | + vbox_options = self.builder.get_object("vbox_watch_options") |
1690 | + watch_type = self.watch.type |
1691 | + self.watch_options[watch_type] = [] |
1692 | + try: |
1693 | + self.table.destroy() |
1694 | + except: |
1695 | + pass |
1696 | + |
1697 | + try: |
1698 | + if self.specto.watch_db.plugin_dict[watch_type].dbus_watch == True: |
1699 | + self.builder.get_object("refresh").hide() |
1700 | + self.builder.get_object("refresh_unit").hide() |
1701 | + self.builder.get_object("label_refresh1").hide() |
1702 | + except: |
1703 | + pass |
1704 | + |
1705 | + if hasattr(self.specto.watch_db.plugin_dict[watch_type], 'get_add_gui_info'): |
1706 | + values = self.specto.watch_db.plugin_dict[watch_type].get_add_gui_info() |
1707 | + else: |
1708 | + values = [] |
1709 | + |
1710 | + watch_values = self.watch.get_values() |
1711 | + |
1712 | + if watch_values['command'] != "": |
1713 | + self.builder.get_object("entry_changed_command").set_text(watch_values['command']) |
1714 | + self.builder.get_object("check_command").set_active(True) |
1715 | + else: |
1716 | + self.builder.get_object("entry_changed_command").set_text("") |
1717 | + self.builder.get_object("check_command").set_active(False) |
1718 | + |
1719 | + if watch_values['open_command'] != "": |
1720 | + self.builder.get_object("entry_open_command").set_text(watch_values['open_command']) |
1721 | + self.builder.get_object("check_open").set_active(True) |
1722 | + else: |
1723 | + self.builder.get_object("entry_open_command").set_text("") |
1724 | + self.builder.get_object("check_open").set_active(False) |
1725 | + |
1726 | + |
1727 | + # Create the options gui |
1728 | + if len(values) > 0: |
1729 | + self.table = gtk.Table(rows=len(values), columns=2, homogeneous=False) |
1730 | + self.table.set_row_spacings(6) |
1731 | + self.table.set_col_spacings(6) |
1732 | + self.watch_options[watch_type] = {} |
1733 | + |
1734 | + i = 0 |
1735 | + for value, widget in values: |
1736 | + table, _widget = widget.get_object() |
1737 | + widget.set_value(watch_values[value]) |
1738 | + self.table.attach(table, 0, 1, i, i + 1) |
1739 | + self.watch_options[watch_type].update({value: widget}) |
1740 | + i += 1 |
1741 | + |
1742 | + self.table.show() |
1743 | + vbox_options.pack_start(self.table, False, False, 0) |
1744 | + |
1745 | + def command_toggled(self, widget): |
1746 | + sensitive = self.builder.get_object("check_command").get_active() |
1747 | + self.builder.get_object("entry_changed_command").set_sensitive(sensitive) |
1748 | + |
1749 | + def open_toggled(self, widget): |
1750 | + sensitive = self.builder.get_object("check_open").get_active() |
1751 | + self.builder.get_object("entry_open_command").set_sensitive(sensitive) |
1752 | + |
1753 | + |
1754 | +class Save_dialog: |
1755 | + """ |
1756 | + Class to create the save dialog. |
1757 | + """ |
1758 | + |
1759 | + def __init__(self, specto, *args): |
1760 | + """ Display the save as dialog. """ |
1761 | + self.specto = specto |
1762 | + self.text = args[0] |
1763 | + # Create the tree |
1764 | + uifile = os.path.join(self.specto.PATH, "uis/edit_watch.ui") |
1765 | + windowname = "file_chooser" |
1766 | + self.builder = gtk.Builder() |
1767 | + self.builder.set_translation_domain("specto") |
1768 | + self.builder.add_from_file(uifile) |
1769 | + self.save_dialog = self.builder.get_object("file_chooser") |
1770 | + |
1771 | + dic = {"on_button_cancel_clicked": self.cancel, |
1772 | + "on_button_save_clicked": self.save} |
1773 | + # Attach the events |
1774 | + self.builder.connect_signals(dic) |
1775 | + |
1776 | + icon = gtk.gdk.pixbuf_new_from_file(os.path.join(self.specto.PATH, "icons/specto_window_icon.png")) |
1777 | + self.save_dialog.set_icon(icon) |
1778 | + self.save_dialog.set_filename(os.environ['HOME'] + "/ ") |
1779 | + |
1780 | + def cancel(self, *args): |
1781 | + """ Destroy the window. """ |
1782 | + self.save_dialog.destroy() |
1783 | + |
1784 | + def save(self, *args): |
1785 | + """ Save the file. """ |
1786 | + file_name = self.save_dialog.get_filename() |
1787 | + |
1788 | + f = open(file_name, "w") |
1789 | + f.write(self.text) |
1790 | + f.close() |
1791 | + |
1792 | + self.save_dialog.destroy() |
1793 | + |
1794 | + |
1795 | +if __name__ == "__main__": |
1796 | + # Run the gui |
1797 | + app = Edit_watch() |
1798 | + gtk.main() |
1799 | |
1800 | === added file 'build/lib.linux-i686-2.6/spectlib/export_watch.py' |
1801 | --- build/lib.linux-i686-2.6/spectlib/export_watch.py 1970-01-01 00:00:00 +0000 |
1802 | +++ build/lib.linux-i686-2.6/spectlib/export_watch.py 2012-03-14 09:03:18 +0000 |
1803 | @@ -0,0 +1,231 @@ |
1804 | +# -*- coding: utf-8 -*- |
1805 | + |
1806 | +# Specto , Unobtrusive event notifier |
1807 | +# |
1808 | +# import_export.py |
1809 | +# |
1810 | +# See the AUTHORS file for copyright ownership information |
1811 | + |
1812 | +# This program is free software; you can redistribute it and/or |
1813 | +# modify it under the terms of the GNU General Public |
1814 | +# License as published by the Free Software Foundation; either |
1815 | +# version 2 of the License, or (at your option) any later version. |
1816 | +# |
1817 | +# This program is distributed in the hope that it will be useful, |
1818 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
1819 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1820 | +# General Public License for more details. |
1821 | +# |
1822 | +# You should have received a copy of the GNU General Public |
1823 | +# License along with this program; if not, write to the |
1824 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
1825 | +# Boston, MA 02111-1307, USA. |
1826 | + |
1827 | +import os |
1828 | +from spectlib.watch import Watch_io |
1829 | +from spectlib.gtkconfig import SaveDialog |
1830 | + |
1831 | +try: |
1832 | + import pygtk |
1833 | + pygtk.require("2.0") |
1834 | +except: |
1835 | + pass |
1836 | + |
1837 | +try: |
1838 | + import gtk |
1839 | + import gobject |
1840 | +except: |
1841 | + pass |
1842 | + |
1843 | + |
1844 | +class Export_watch: |
1845 | + """ |
1846 | + Class to create the import/export watch dialog. |
1847 | + """ |
1848 | + |
1849 | + def __init__(self, specto, notifier): |
1850 | + self.specto = specto |
1851 | + self.notifier = notifier |
1852 | + |
1853 | + #create tree |
1854 | + uifile = os.path.join(self.specto.PATH, "uis/import_export.ui") |
1855 | + windowname = "import_export" |
1856 | + self.builder = gtk.Builder() |
1857 | + self.builder.set_translation_domain("specto") |
1858 | + self.builder.add_from_file(uifile) |
1859 | + self.export_watch = self.builder.get_object("import_export") |
1860 | + self.export_watch.set_title(_("Export watches")) |
1861 | + self.builder.get_object("button_action").set_label(_("Export watches")) |
1862 | + |
1863 | + self.model = gtk.ListStore(gobject.TYPE_BOOLEAN, gtk.gdk.Pixbuf, \ |
1864 | + gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_STRING) |
1865 | + self.new_watch_db = {} |
1866 | + |
1867 | + #catch some events |
1868 | + dic = {"on_button_select_all_clicked": self.select_all, |
1869 | + "on_button_deselect_all_clicked": self.deselect_all, |
1870 | + "on_button_action_clicked": self.do_action, |
1871 | + "on_button_close_clicked": self.delete_event} |
1872 | + |
1873 | + #attach the events |
1874 | + self.builder.connect_signals(dic) |
1875 | + |
1876 | + icon = gtk.gdk.pixbuf_new_from_file(os.path.join(self.specto.PATH, "icons/specto_window_icon.png")) |
1877 | + self.export_watch.set_icon(icon) |
1878 | + |
1879 | + self.treeview = self.builder.get_object("treeview") |
1880 | + self.treeview.set_model(self.model) |
1881 | + self.treeview.set_flags(gtk.TREE_MODEL_ITERS_PERSIST) |
1882 | + self.iter = {} |
1883 | + |
1884 | + ### Checkbox |
1885 | + self.renderer = gtk.CellRendererToggle() |
1886 | + self.renderer.set_property("activatable", True) |
1887 | + self.renderer.connect("toggled", self.check_clicked, self.model) |
1888 | + self.columnCheck = gtk.TreeViewColumn(_("Select"), \ |
1889 | + self.renderer, active=0) |
1890 | + self.treeview.append_column(self.columnCheck) |
1891 | + |
1892 | + ### Icon |
1893 | + self.renderer = gtk.CellRendererPixbuf() |
1894 | + self.columnIcon = gtk.TreeViewColumn(_("Type"), \ |
1895 | + self.renderer, pixbuf=1) |
1896 | + self.treeview.append_column(self.columnIcon) |
1897 | + |
1898 | + ### Titre |
1899 | + self.renderer = gtk.CellRendererText() |
1900 | + self.columnTitel = gtk.TreeViewColumn(_("Name"), \ |
1901 | + self.renderer, markup=2) |
1902 | + self.columnTitel.set_expand(True) |
1903 | + self.columnTitel.set_resizable(True) |
1904 | + self.treeview.append_column(self.columnTitel) |
1905 | + |
1906 | + ### ID |
1907 | + self.renderer = gtk.CellRendererText() |
1908 | + self.column = gtk.TreeViewColumn(_("ID"), self.renderer, markup=3) |
1909 | + self.column.set_visible(False) |
1910 | + #self.column.set_sort_column_id(3) |
1911 | + self.treeview.append_column(self.column) |
1912 | + |
1913 | + ### type |
1914 | + self.renderer = gtk.CellRendererText() |
1915 | + self.columnType = gtk.TreeViewColumn(_("TYPE"), \ |
1916 | + self.renderer, markup=4) |
1917 | + self.columnType.set_visible(False) |
1918 | + #self.columnType.set_sort_column_id(4) |
1919 | + self.treeview.append_column(self.columnType) |
1920 | + |
1921 | + for watch in self.specto.watch_db: |
1922 | + if watch.deleted == False: |
1923 | + self.add_watch_entry(watch.id) |
1924 | + |
1925 | + def select_all(self, widget): |
1926 | + db = self.specto.watch_db |
1927 | + |
1928 | + for watch in db: |
1929 | + if watch.deleted == False: |
1930 | + self.model.set_value(self.iter[watch.id], 0, 1) |
1931 | + |
1932 | + def deselect_all(self, widget): |
1933 | + db = self.specto.watch_db |
1934 | + |
1935 | + for watch in db: |
1936 | + if watch.deleted == False: |
1937 | + self.model.set_value(self.iter[watch.id], 0, 0) |
1938 | + |
1939 | + def do_action(self, widget): |
1940 | + self.export_watch.hide_all() |
1941 | + export_save_dialog = ExportSaveDialog(self.specto, None, False, \ |
1942 | + self.get_selected_watches()) |
1943 | + response = export_save_dialog.run() |
1944 | + if response == gtk.RESPONSE_OK: |
1945 | + export_save_dialog.save() |
1946 | + else: |
1947 | + export_save_dialog.cancel() |
1948 | + |
1949 | + def delete_event(self, widget, *args): |
1950 | + """ Destroy the window. """ |
1951 | + self.export_watch.destroy() |
1952 | + return True |
1953 | + |
1954 | + def get_selected_watches(self): |
1955 | + selected_watches_db = {} |
1956 | + i = 0 |
1957 | + watch_db = self.specto.watch_db |
1958 | + |
1959 | + for watch in watch_db: |
1960 | + if watch.deleted == False: |
1961 | + if self.model.get_value(self.iter[watch.id], 0) == True: |
1962 | + selected_watches_db[i] = watch |
1963 | + i += 1 |
1964 | + return selected_watches_db |
1965 | + |
1966 | + def add_watch_entry(self, id): |
1967 | + """ Add an entry to the notifier list. """ |
1968 | + watch = self.specto.watch_db[id] |
1969 | + entry_name = watch.name.replace("&", "&") |
1970 | + icon = self.notifier.get_icon(watch.icon, 50, False) |
1971 | + self.iter[id] = self.model.insert_before(None, None) |
1972 | + self.model.set_value(self.iter[id], 0, 0) |
1973 | + self.model.set_value(self.iter[id], 1, icon) |
1974 | + self.model.set_value(self.iter[id], 2, entry_name) |
1975 | + self.model.set_value(self.iter[id], 3, watch.id) |
1976 | + self.model.set_value(self.iter[id], 4, watch.type) |
1977 | + |
1978 | + def set_new_watch_db(self, watch_db): |
1979 | + self.new_watch_db = watch_db |
1980 | + |
1981 | + def check_clicked(self, object, path, model): |
1982 | + """ Call the main function to start/stop the selected watch. """ |
1983 | + sel = self.treeview.get_selection() |
1984 | + sel.select_path(path) |
1985 | + model, iter = self.treeview.get_selection().get_selected() |
1986 | + |
1987 | + if model.get_value(iter, 0): |
1988 | + model.set_value(iter, 0, 0) |
1989 | + else: |
1990 | + model.set_value(iter, 0, 1) |
1991 | + |
1992 | + |
1993 | +class ExportSaveDialog(SaveDialog): |
1994 | + """ |
1995 | + Class for displaying the save as dialog. |
1996 | + """ |
1997 | + |
1998 | + def __init__(self, specto, _import, action_type, watches_db): |
1999 | + SaveDialog.__init__(self, specto) |
2000 | + self.specto = specto |
2001 | + self._export = _import |
2002 | + windowname = "export_file_chooser" |
2003 | + self.action_type = action_type |
2004 | + self.watches_db = watches_db |
2005 | + |
2006 | + def save(self, *args): |
2007 | + """ Save the file. """ |
2008 | + file_name = self.get_filename() |
2009 | + |
2010 | + for i in self.watches_db.keys(): |
2011 | + values = {} |
2012 | + values['name'] = self.watches_db[i].name |
2013 | + values['type'] = self.watches_db[i].type |
2014 | + values['refresh'] = self.watches_db[i].refresh |
2015 | + values.update(self.watches_db[i].get_values()) |
2016 | + self.write_options(file_name, values) |
2017 | + |
2018 | + self.destroy() |
2019 | + |
2020 | + def write_options(self, file_name, values): |
2021 | + """ |
2022 | + Write or change the watch options in a configuration file. |
2023 | + Values has to be a dictionary with the name from the options |
2024 | + and the value. example: { 'name':'value', 'name':'value' } |
2025 | + If the name is not found, a new watch will be added, |
2026 | + else the excisting watch will be changed. |
2027 | + """ |
2028 | + watch_io = Watch_io(self.specto, file_name) |
2029 | + watch_io.write_watch(values) |
2030 | + |
2031 | +if __name__ == "__main__": |
2032 | + #run the gui |
2033 | + app = Export_watch() |
2034 | + gtk.main() |
2035 | |
2036 | === added file 'build/lib.linux-i686-2.6/spectlib/gtkconfig.py' |
2037 | --- build/lib.linux-i686-2.6/spectlib/gtkconfig.py 1970-01-01 00:00:00 +0000 |
2038 | +++ build/lib.linux-i686-2.6/spectlib/gtkconfig.py 2012-03-14 09:03:18 +0000 |
2039 | @@ -0,0 +1,588 @@ |
2040 | +# -*- coding: utf-8 -*- |
2041 | + |
2042 | +# Specto , Unobtrusive event notifier |
2043 | +# |
2044 | +# gtkutil.py |
2045 | +# |
2046 | +# See the AUTHORS file for copyright ownership information |
2047 | + |
2048 | +# This program is free software; you can redistribute it and/or |
2049 | +# modify it under the terms of the GNU General Public |
2050 | +# License as published by the Free Software Foundation; either |
2051 | +# version 2 of the License, or (at your option) any later version. |
2052 | +# |
2053 | +# This program is distributed in the hope that it will be useful, |
2054 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2055 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2056 | +# General Public License for more details. |
2057 | +# |
2058 | +# You should have received a copy of the GNU General Public |
2059 | +# License along with this program; if not, write to the |
2060 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
2061 | +# Boston, MA 02111-1307, USA. |
2062 | + |
2063 | +import gtk |
2064 | +import os |
2065 | + |
2066 | +import spectlib.util |
2067 | + |
2068 | + |
2069 | +class Entry(): |
2070 | + |
2071 | + def __init__(self, label, text=None): |
2072 | + self.table = gtk.Table(rows=1, columns=2) |
2073 | + self.gtkLabel = gtk.Label((label + ":")) |
2074 | + self.gtkLabel.set_alignment(xalign=0.0, yalign=0.5) |
2075 | + self.gtkLabel.show() |
2076 | + self.table.attach(self.gtkLabel, 0, 1, 0, 1) |
2077 | + |
2078 | + self.entry = gtk.Entry() |
2079 | + if text != None: |
2080 | + self.entry.set_text(text) |
2081 | + self.entry.show() |
2082 | + self.table.attach(self.entry, 1, 2, 0, 1, xoptions=gtk.FILL) |
2083 | + self.table.show() |
2084 | + |
2085 | + def set_value(self, value): |
2086 | + self.entry.set_text(value) |
2087 | + |
2088 | + def get_value(self): |
2089 | + return self.entry.get_text() |
2090 | + |
2091 | + def get_object(self): |
2092 | + return self.table, self.entry |
2093 | + |
2094 | + def set_color(self, red, blue, green): |
2095 | + self.entry.modify_base(gtk.STATE_NORMAL, \ |
2096 | + gtk.gdk.Color(red, blue, green)) |
2097 | + |
2098 | + def grab_focus(self): |
2099 | + self.entry.grab_focus() |
2100 | + |
2101 | + |
2102 | +class PasswordEntry(): |
2103 | + |
2104 | + def __init__(self, label, text=None): |
2105 | + self.table = gtk.Table(rows=1, columns=2) |
2106 | + self.gtkLabel = gtk.Label((label + ":")) |
2107 | + self.gtkLabel.set_alignment(xalign=0.0, yalign=0.5) |
2108 | + self.gtkLabel.show() |
2109 | + self.table.attach(self.gtkLabel, 0, 1, 0, 1) |
2110 | + |
2111 | + self.entry = gtk.Entry() |
2112 | + self.entry.set_visibility(False) |
2113 | + if text != None: |
2114 | + self.entry.set_text(text) |
2115 | + self.entry.show() |
2116 | + self.table.attach(self.entry, 1, 2, 0, 1, xoptions=gtk.FILL) |
2117 | + self.table.show() |
2118 | + |
2119 | + def set_value(self, value): |
2120 | + self.entry.set_text(value) |
2121 | + |
2122 | + def get_value(self): |
2123 | + return self.entry.get_text() |
2124 | + |
2125 | + def get_object(self): |
2126 | + return self.table, self.entry |
2127 | + |
2128 | + def set_color(self, red, blue, green): |
2129 | + self.entry.modify_base(gtk.STATE_NORMAL, \ |
2130 | + gtk.gdk.Color(red, blue, green)) |
2131 | + |
2132 | + def grab_focus(self): |
2133 | + self.entry.grab_focus() |
2134 | + |
2135 | + |
2136 | +class Spinbutton(): |
2137 | + |
2138 | + def __init__(self, label, value=1, lower=1, upper=100, \ |
2139 | + step_incr=1, page_incr=10, page_size=0): |
2140 | + self.table = gtk.Table(rows=1, columns=2) |
2141 | + self.gtkLabel = gtk.Label((label + ":")) |
2142 | + self.gtkLabel.set_alignment(xalign=0.0, yalign=0.5) |
2143 | + self.gtkLabel.show() |
2144 | + self.table.attach(self.gtkLabel, 0, 1, 0, 1) |
2145 | + |
2146 | + adjustment = gtk.Adjustment(value, lower, upper, \ |
2147 | + step_incr, page_incr, page_size) |
2148 | + self.spinbutton = gtk.SpinButton(adjustment) |
2149 | + self.spinbutton.show() |
2150 | + self.table.attach(self.spinbutton, 1, 2, 0, 1, xoptions=gtk.FILL) |
2151 | + self.table.show() |
2152 | + |
2153 | + def set_value(self, value): |
2154 | + self.spinbutton.set_value(value) |
2155 | + |
2156 | + def get_value(self): |
2157 | + return self.spinbutton.get_value() |
2158 | + |
2159 | + def get_object(self): |
2160 | + return self.table, self.spinbutton |
2161 | + |
2162 | + def set_color(self, red, blue, green): |
2163 | + self.spinbutton.modify_base(gtk.STATE_NORMAL, \ |
2164 | + gtk.gdk.Color(red, blue, green)) |
2165 | + |
2166 | + def grab_focus(self): |
2167 | + self.spinbutton.grab_focus() |
2168 | + |
2169 | + |
2170 | +class CheckButton(): |
2171 | + |
2172 | + def __init__(self, label, value=False): |
2173 | + self.table = gtk.Table(rows=1, columns=2) |
2174 | + self.gtkLabel = gtk.Label((label + ":")) |
2175 | + self.gtkLabel.set_alignment(xalign=0.0, yalign=0.5) |
2176 | + self.gtkLabel.show() |
2177 | + self.table.attach(self.gtkLabel, 0, 1, 0, 1) |
2178 | + |
2179 | + self.checkbutton = gtk.CheckButton() |
2180 | + self.checkbutton.set_active(value) |
2181 | + self.checkbutton.set_alignment(xalign=1.0, yalign=0.0) |
2182 | + self.checkbutton.show() |
2183 | + self.table.attach(self.checkbutton, 1, 2, 0, 1, xoptions=gtk.FILL) |
2184 | + self.table.show() |
2185 | + |
2186 | + def set_value(self, value): |
2187 | + self.checkbutton.set_active(value) |
2188 | + |
2189 | + def get_value(self): |
2190 | + return self.checkbutton.get_active() |
2191 | + |
2192 | + def get_object(self): |
2193 | + return self.table, self.checkbutton |
2194 | + |
2195 | + def set_color(self, red, blue, green): |
2196 | + self.checkbutton.modify_base(gtk.STATE_NORMAL, \ |
2197 | + gtk.gdk.Color(red, blue, green)) |
2198 | + |
2199 | + def grab_focus(self): |
2200 | + self.checkbutton.grab_focus() |
2201 | + |
2202 | + |
2203 | +class FileChooser(): |
2204 | + |
2205 | + def __init__(self, label, value=False): |
2206 | + self.table = gtk.Table(rows=2, columns=1) |
2207 | + self.gtkLabel = gtk.Label((label + ":")) |
2208 | + self.gtkLabel.set_alignment(xalign=0.0, yalign=0.5) |
2209 | + self.gtkLabel.show() |
2210 | + self.table.attach(self.gtkLabel, 0, 1, 0, 1) |
2211 | + |
2212 | + self.filechooser = gtk.FileChooserButton(_("Choose a file")) |
2213 | +## filter = gtk.FileFilter() |
2214 | +## filter.set_name("PDF files") |
2215 | +## filter.add_pattern("*.pdf") |
2216 | +## self.filechooser.add_filter(filter) |
2217 | + |
2218 | + self.filechooser.set_action(gtk.FILE_CHOOSER_ACTION_OPEN) |
2219 | + self.filechooser.set_filename(os.environ['HOME']) |
2220 | + self.filechooser.show() |
2221 | + self.table.attach(self.filechooser, 0, 1, 1, 2, xoptions=gtk.FILL) |
2222 | + self.table.show() |
2223 | + |
2224 | + def set_value(self, value): |
2225 | + self.filechooser.set_filename(value) |
2226 | + |
2227 | + def get_value(self): |
2228 | + return self.filechooser.get_filename() |
2229 | + |
2230 | + def get_object(self): |
2231 | + return self.table, self.filechooser |
2232 | + |
2233 | + def set_color(self, red, blue, green): |
2234 | + self.filechooser.modify_base(gtk.STATE_NORMAL, \ |
2235 | + gtk.gdk.Color(red, blue, green)) |
2236 | + |
2237 | + def grab_focus(self): |
2238 | + self.filechooser.grab_focus() |
2239 | + |
2240 | +class FileChooserpdf(): |
2241 | + |
2242 | + def __init__(self, label, value=False): |
2243 | + self.table = gtk.Table(rows=2, columns=1) |
2244 | + self.gtkLabel = gtk.Label((label + ":")) |
2245 | + self.gtkLabel.set_alignment(xalign=0.0, yalign=0.5) |
2246 | + self.gtkLabel.show() |
2247 | + self.table.attach(self.gtkLabel, 0, 1, 0, 1) |
2248 | + |
2249 | + self.filechooser = gtk.FileChooserButton(_("Choose a file")) |
2250 | + filter = gtk.FileFilter() |
2251 | + filter.set_name("PDF files") |
2252 | + filter.add_pattern("*.pdf") |
2253 | + self.filechooser.add_filter(filter) |
2254 | + |
2255 | + self.filechooser.set_action(gtk.FILE_CHOOSER_ACTION_OPEN) |
2256 | + self.filechooser.set_filename(os.environ['HOME']) |
2257 | + self.filechooser.show() |
2258 | + self.table.attach(self.filechooser, 0, 1, 1, 2, xoptions=gtk.FILL) |
2259 | + self.table.show() |
2260 | + |
2261 | + def set_value(self, value): |
2262 | + self.filechooser.set_filename(value) |
2263 | + |
2264 | + def get_value(self): |
2265 | + return self.filechooser.get_filename() |
2266 | + |
2267 | + def get_object(self): |
2268 | + return self.table, self.filechooser |
2269 | + |
2270 | + def set_color(self, red, blue, green): |
2271 | + self.filechooser.modify_base(gtk.STATE_NORMAL, \ |
2272 | + gtk.gdk.Color(red, blue, green)) |
2273 | + |
2274 | + def grab_focus(self): |
2275 | + self.filechooser.grab_focus() |
2276 | + |
2277 | + |
2278 | +class FolderChooser(): |
2279 | + |
2280 | + def __init__(self, label, value=False): |
2281 | + self.table = gtk.Table(rows=2, columns=1) |
2282 | + self.gtkLabel = gtk.Label((label + ":")) |
2283 | + self.gtkLabel.set_alignment(xalign=0.0, yalign=0.5) |
2284 | + self.gtkLabel.show() |
2285 | + self.table.attach(self.gtkLabel, 0, 1, 0, 1) |
2286 | + |
2287 | + self.dirchooser = gtk.FileChooserButton(_("Choose a directory")) |
2288 | + self.dirchooser.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) |
2289 | + self.dirchooser.set_filename(os.environ['HOME']) |
2290 | + self.dirchooser.show() |
2291 | + self.table.attach(self.dirchooser, 0, 1, 1, 2, xoptions=gtk.FILL) |
2292 | + self.table.show() |
2293 | + |
2294 | + def set_value(self, value): |
2295 | + self.dirchooser.set_filename(value) |
2296 | + |
2297 | + def get_value(self): |
2298 | + return self.dirchooser.get_filename() |
2299 | + |
2300 | + def get_object(self): |
2301 | + return self.table, self.dirchooser |
2302 | + |
2303 | + def set_color(self, red, blue, green): |
2304 | + self.dirchooser.modify_base(gtk.STATE_NORMAL, \ |
2305 | + gtk.gdk.Color(red, blue, green)) |
2306 | + |
2307 | + def grab_focus(self): |
2308 | + self.dirchooser.grab_focus() |
2309 | + |
2310 | + |
2311 | +class Scale(): |
2312 | + |
2313 | + def __init__(self, label, value=0, lower=0, upper=100, \ |
2314 | + step_incr=1.0, page_incr=1.0, page_size=10): |
2315 | + self.table = gtk.Table(rows=2, columns=1) |
2316 | + |
2317 | + self.gtkLabel = gtk.Label((label + ":")) |
2318 | + self.gtkLabel.set_alignment(xalign=0.0, yalign=0.5) |
2319 | + self.gtkLabel.show() |
2320 | + self.table.attach(self.gtkLabel, 0, 1, 0, 1) |
2321 | + |
2322 | + self.value = value |
2323 | + self.lower = lower |
2324 | + self.upper = upper |
2325 | + self.step_incr = step_incr |
2326 | + self.page_incr = page_incr |
2327 | + self.page_size = page_size |
2328 | + |
2329 | + _adjustment = gtk.Adjustment(value, lower, upper, \ |
2330 | + step_incr, page_incr, page_size) |
2331 | + self.scale = gtk.HScale(adjustment=_adjustment) |
2332 | + self.scale.set_digits(1) |
2333 | + self.scale.set_value_pos(gtk.POS_RIGHT) |
2334 | + self.scale.show() |
2335 | + self.table.attach(self.scale, 0, 1, 1, 2, xoptions=gtk.FILL) |
2336 | + self.table.show() |
2337 | + |
2338 | + def set_value(self, value): |
2339 | + _adjustment = gtk.Adjustment(value, self.lower, self.upper, \ |
2340 | + self.step_incr, self.page_incr, self.page_size) |
2341 | + self.scale.set_adjustment(_adjustment) |
2342 | + |
2343 | + def get_value(self): |
2344 | + return self.scale.get_value() |
2345 | + |
2346 | + def get_object(self): |
2347 | + return self.table, self.scale |
2348 | + |
2349 | + def set_color(self, red, blue, green): |
2350 | + self.scale.modify_base(gtk.STATE_NORMAL, \ |
2351 | + gtk.gdk.Color(red, blue, green)) |
2352 | + |
2353 | + def grab_focus(self): |
2354 | + self.scale.grab_focus() |
2355 | + |
2356 | + |
2357 | +class RemoveDialog(): |
2358 | + |
2359 | + def __init__(self, title, text): |
2360 | + dialog = gtk.Dialog(title, None, gtk.DIALOG_MODAL | \ |
2361 | + gtk.DIALOG_NO_SEPARATOR | gtk.DIALOG_DESTROY_WITH_PARENT, None) |
2362 | + #HIG tricks |
2363 | + dialog.set_has_separator(False) |
2364 | + |
2365 | + dialog.add_button(gtk.STOCK_CANCEL, -1) |
2366 | + dialog.add_button(gtk.STOCK_REMOVE, 3) |
2367 | + |
2368 | + dialog.label_hbox = gtk.HBox(spacing=6) |
2369 | + |
2370 | + icon = gtk.Image() |
2371 | + icon.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_DIALOG) |
2372 | + dialog.label_hbox.pack_start(icon, True, True, 6) |
2373 | + icon.show() |
2374 | + |
2375 | + text = text.replace("&", "&") |
2376 | + label = gtk.Label(text) |
2377 | + label.set_use_markup(True) |
2378 | + dialog.label_hbox.pack_start(label, True, True, 6) |
2379 | + label.show() |
2380 | + |
2381 | + dialog.vbox.pack_start(dialog.label_hbox, True, True, 12) |
2382 | + dialog.label_hbox.show() |
2383 | + |
2384 | + icon = gtk.gdk.pixbuf_new_from_file(spectlib.util.get_path() \ |
2385 | + + 'icons/specto_window_icon.svg') |
2386 | + dialog.set_icon(icon) |
2387 | + self.dialog = dialog |
2388 | + |
2389 | + def show(self): |
2390 | + answer = self.dialog.run() |
2391 | + if answer == 3: |
2392 | + self.dialog.destroy() |
2393 | + return True |
2394 | + else: |
2395 | + self.dialog.destroy() |
2396 | + return False |
2397 | + |
2398 | + |
2399 | +class ErrorDialog(): |
2400 | + |
2401 | + def __init__(self, specto, error_message): |
2402 | + self.specto = specto |
2403 | + uifile = os.path.join(self.specto.PATH, "uis/notifier.ui") |
2404 | + windowname = "error_dialog" |
2405 | + self.builder = gtk.Builder() |
2406 | + self.builder.set_translation_domain("specto") |
2407 | + self.builder.add_from_file(uifile) |
2408 | + |
2409 | + self.builder.get_object("ok").connect("clicked", self.delete_event) |
2410 | + self.builder.get_object("send").connect("clicked", self.send) |
2411 | + |
2412 | + self.error_dialog = self.builder.get_object("error_dialog") |
2413 | + self.error_dialog.show() |
2414 | + icon = gtk.gdk.pixbuf_new_from_file(os.path.join(self.specto.PATH, "icons/specto_window_icon.png")) |
2415 | + self.error_dialog.set_icon(icon) |
2416 | + |
2417 | + self.errorwindow = gtk.TextBuffer(None) |
2418 | + self.builder.get_object("error_message").set_buffer(self.errorwindow) |
2419 | + self.errorwindow.set_text(error_message) |
2420 | + |
2421 | + self.builder.get_object("image").set_from_stock(gtk.STOCK_DIALOG_ERROR, \ |
2422 | + gtk.ICON_SIZE_DIALOG) |
2423 | + |
2424 | + self.builder.get_object("label4").set_use_markup(True) |
2425 | + self.builder.get_object("label4").set_label(_("<b>Specto encountered an error</b>\nPlease verify if this bug has been entered in our issue tracker, and if not, file a bug report so we can fix it.")) |
2426 | + |
2427 | + def send(self, *args): |
2428 | + url = "http://code.google.com/p/specto/issues/list" |
2429 | + os.system(spectlib.util.return_webpage(url) + " &") |
2430 | + |
2431 | + def delete_event(self, widget, *args): |
2432 | + """ Destroy the window. """ |
2433 | + self.error_dialog.destroy() |
2434 | + return True |
2435 | + |
2436 | + |
2437 | +class SaveDialog(gtk.FileChooserDialog): |
2438 | + """ |
2439 | + Class for displaying a generic save dialog for Specto. |
2440 | + """ |
2441 | + |
2442 | + def __init__(self, specto): |
2443 | + gtk.FileChooserDialog.__init__(self, _("Save file as"), None, |
2444 | + gtk.FILE_CHOOSER_ACTION_SAVE, |
2445 | + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, |
2446 | + gtk.STOCK_SAVE, gtk.RESPONSE_OK)) |
2447 | + self.specto = specto |
2448 | + windowname = "filechooser" |
2449 | + |
2450 | + self.set_icon(gtk.gdk.pixbuf_new_from_file(os.path.join(self.specto.PATH, "icons/specto_window_icon.png"))) |
2451 | + self.set_filename(os.environ['HOME'] + "/ ") |
2452 | + |
2453 | + def cancel(self, *args): |
2454 | + """ Close the dialog. """ |
2455 | + self.destroy() |
2456 | + |
2457 | + def save(self, *args): |
2458 | + raise NotImplementedError |
2459 | + |
2460 | +class OpenDialog(gtk.FileChooserDialog): |
2461 | + """ |
2462 | + Class for displaying a generic open dialog for Specto. |
2463 | + """ |
2464 | + |
2465 | + def __init__(self, specto): |
2466 | + gtk.FileChooserDialog.__init__(self, _("Open file"), None, |
2467 | + gtk.FILE_CHOOSER_ACTION_OPEN, |
2468 | + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, |
2469 | + gtk.STOCK_OPEN, gtk.RESPONSE_OK)) |
2470 | + self.specto = specto |
2471 | + windowname = "open_file_chooser" |
2472 | + |
2473 | + icon = gtk.gdk.pixbuf_new_from_file(os.path.join(self.specto.PATH, "icons/specto_window_icon.png")) |
2474 | + self.set_icon(icon) |
2475 | + self.set_filename(os.environ['HOME'] + "/ ") |
2476 | + |
2477 | + def cancel(self, *args): |
2478 | + """ Close the save as dialog. """ |
2479 | + self.destroy() |
2480 | + |
2481 | + def open(self, *args): |
2482 | + raise NotImplementedError |
2483 | + |
2484 | + |
2485 | +def create_widget(table, widget_type, value, label, position): |
2486 | + i = position |
2487 | + watch_options = {} |
2488 | + |
2489 | + if not widget_type == "scale": |
2490 | + gtkLabel = gtk.Label((label + ":")) |
2491 | + gtkLabel.set_alignment(xalign=0.0, yalign=0.5) |
2492 | + gtkLabel.show() |
2493 | + table.attach(gtkLabel, 0, 1, i, i + 1) |
2494 | + |
2495 | + if widget_type == "entry": |
2496 | + entry = gtk.Entry() |
2497 | + entry.show() |
2498 | + watch_options.update({value: entry}) |
2499 | + table.attach(entry, 1, 2, i, i + 1) |
2500 | + elif widget_type == "password": |
2501 | + entry = gtk.Entry() |
2502 | + entry.set_visibility(False) |
2503 | + entry.show() |
2504 | + watch_options.update({value: entry}) |
2505 | + table.attach(entry, 1, 2, i, i + 1) |
2506 | + elif widget_type == "scale": |
2507 | + scale_table = gtk.Table(rows=2, columns=1, homogeneous=False) |
2508 | + |
2509 | + adjustment_label = gtk.Label((label + ":")) |
2510 | + adjustment_label.set_alignment(xalign=0.0, yalign=0.5) |
2511 | + adjustment_label.show() |
2512 | + scale_table.attach(adjustment_label, 0, 1, 0, 1) |
2513 | + |
2514 | + _adjustment = gtk.Adjustment(value=2.0, lower=0, upper=50, \ |
2515 | + step_incr=0.1, page_incr=1.0, page_size=10) |
2516 | + scale = gtk.HScale(adjustment=_adjustment) |
2517 | + scale.set_digits(1) |
2518 | + scale.set_value_pos(gtk.POS_RIGHT) |
2519 | + scale.show() |
2520 | + scale_table.attach(scale, 0, 1, 1, 2) |
2521 | + |
2522 | + watch_options.update({value: scale}) |
2523 | + scale_table.show() |
2524 | + table.attach(scale_table, 0, 2, i, i + 1) |
2525 | + elif widget_type == "checkbox": |
2526 | + checkbox = gtk.CheckButton() |
2527 | + checkbox.show() |
2528 | + watch_options.update({value: checkbox}) |
2529 | + table.attach(checkbox, 1, 2, i, i + 1) |
2530 | + elif widget_type == "filechooser": |
2531 | + filechooser = gtk.FileChooserButton(_("Choose a file")) |
2532 | + filechooser.set_action(gtk.FILE_CHOOSER_ACTION_OPEN) |
2533 | + filechooser.show() |
2534 | + watch_options.update({value: filechooser}) |
2535 | + table.attach(filechooser, 1, 2, i, i + 1) |
2536 | + elif widget_type == "dirchooser": |
2537 | + dirchooser = gtk.FileChooserButton(_("Choose a directory")) |
2538 | + dirchooser.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) |
2539 | + dirchooser.show() |
2540 | + watch_options.update({value: dirchooser}) |
2541 | + table.attach(dirchooser, 1, 2, i, i + 1) |
2542 | + elif widget_type == "calendar": |
2543 | + calendar = gtk.Calendar() |
2544 | + #calendar.show() |
2545 | + watch_options.update({value: calendar}) |
2546 | + table.attach(calendar, 1, 2, i, i + 1) |
2547 | + elif widget_type == "time": |
2548 | + time_table = gtk.Table(rows=1, columns=2, homogeneous=False) |
2549 | + minutes_adjustment = gtk.Adjustment(value=1, lower=1, upper=60, \ |
2550 | + step_incr=1, page_incr=10, page_size=0) |
2551 | + hours_adjustment = gtk.Adjustment(value=1, lower=1, upper=24, \ |
2552 | + step_incr=1, page_incr=10, page_size=0) |
2553 | + hours = gtk.SpinButton(hours_adjustment) |
2554 | + hours.show() |
2555 | + minutes = gtk.SpinButton(minutes_adjustment) |
2556 | + minutes.show() |
2557 | + time_table.attach(hours, 1, 2, 1, 2) |
2558 | + time_table.attach(minutes, 2, 3, 1, 2) |
2559 | + #time_table.show() |
2560 | + watch_options.update({value: (hours, minutes)}) |
2561 | + table.attach(time_table, 1, 2, i, i + 1) |
2562 | + |
2563 | + return watch_options, table |
2564 | + |
2565 | + |
2566 | +def set_widget_value(widget_type, widget, value): |
2567 | + if widget_type == "entry" or widget_type == "password": |
2568 | + widget.set_text(value) |
2569 | + elif widget_type == "scale": |
2570 | + _adjustment = gtk.Adjustment(value=value * 100, lower=0, \ |
2571 | + upper=50, step_incr=0.1, page_incr=1.0, page_size=10) |
2572 | + widget.set_adjustment(_adjustment) |
2573 | + elif widget_type == "checkbox": |
2574 | + if value == "True" or value == True: |
2575 | + widget.set_active(1) |
2576 | + else: |
2577 | + widget.set_active(0) |
2578 | + elif widget_type == "filechooser" or widget_type == "dirchooser": |
2579 | + widget.set_filename(value) |
2580 | + elif widget_type == "calendar": |
2581 | + try: #if value = string |
2582 | + value = value.replace("(", "") |
2583 | + value = value.replace(")", "") |
2584 | + value = value.split(",") |
2585 | + except: # value = tuple |
2586 | + pass |
2587 | + widget.select_month(int(value[1]), int(value[0])) |
2588 | + widget.select_day(int(value[2])) |
2589 | + elif widget_type == "time": |
2590 | + widget[0].set_value(int(value[0])) |
2591 | + widget[1].set_value(int(value[1])) |
2592 | + |
2593 | + |
2594 | +def get_object_value(widget_type, value): |
2595 | + result = "" |
2596 | + if widget_type == "entry" or widget_type == "password": |
2597 | + result = value.values()[0].get_text() |
2598 | + elif widget_type == "scale": |
2599 | + result = value.values()[0].get_value() |
2600 | + elif widget_type == "checkbox": |
2601 | + result = value.values()[0].get_active() |
2602 | + elif widget_type == "filechooser" or widget_type == "dirchooser": |
2603 | + result = value.values()[0].get_filename() |
2604 | + elif widget_type == "calendar": |
2605 | + result = value.values()[0].get_date() |
2606 | + elif widget_type == "time": |
2607 | + result = (value.values()[0][0].get_value(), \ |
2608 | + value.values()[0][1].get_value()) |
2609 | + |
2610 | + return result |
2611 | + |
2612 | +def create_menu_item(label, callback=None, icon=None): |
2613 | + menuItem = gtk.MenuItem(label, True) |
2614 | + if icon: |
2615 | + menuItem = gtk.ImageMenuItem(label) |
2616 | + image = gtk.Image() |
2617 | + # handle the icon as a stock icon. |
2618 | + try: |
2619 | + image.set_from_stock(icon, gtk.ICON_SIZE_MENU) |
2620 | + except TypeError: |
2621 | + # err, icon is a string, do nothing. |
2622 | + image = icon |
2623 | + menuItem.set_image(image) |
2624 | + image.show() |
2625 | + if callback: |
2626 | + menuItem.connect('activate', callback) |
2627 | + return menuItem |
2628 | |
2629 | === added file 'build/lib.linux-i686-2.6/spectlib/i18n.py' |
2630 | --- build/lib.linux-i686-2.6/spectlib/i18n.py 1970-01-01 00:00:00 +0000 |
2631 | +++ build/lib.linux-i686-2.6/spectlib/i18n.py 2012-03-14 09:03:18 +0000 |
2632 | @@ -0,0 +1,50 @@ |
2633 | +# -*- coding: utf-8 -*- |
2634 | + |
2635 | +# Specto , Unobtrusive event notifier |
2636 | +# |
2637 | +# il8n.py |
2638 | +# |
2639 | +# See the AUTHORS file for copyright ownership information |
2640 | + |
2641 | +# This program is free software; you can redistribute it and/or |
2642 | +# modify it under the terms of the GNU General Public |
2643 | +# License as published by the Free Software Foundation; either |
2644 | +# version 2 of the License, or (at your option) any later version. |
2645 | +# |
2646 | +# This program is distributed in the hope that it will be useful, |
2647 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2648 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2649 | +# General Public License for more details. |
2650 | +# |
2651 | +# You should have received a copy of the GNU General Public |
2652 | +# License along with this program; if not, write to the |
2653 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
2654 | +# Boston, MA 02111-1307, USA. |
2655 | + |
2656 | +import os |
2657 | +import gettext |
2658 | +import locale |
2659 | + |
2660 | +# If Specto is installed read prefix from constants module |
2661 | +MESSAGES_DIR = '' |
2662 | +try: |
2663 | + from spectlib.constants import PREFIX |
2664 | + MESSAGES_DIR = "%s/share/locale" % PREFIX |
2665 | +except ImportError: |
2666 | + pass |
2667 | + |
2668 | +def setup_locale_and_gettext(): |
2669 | + package_name = 'specto' |
2670 | + # Install _() builtin for gettext; always returning unicode objects |
2671 | + # also install ngettext() |
2672 | + gettext.install(package_name, localedir=MESSAGES_DIR, unicode=True, |
2673 | + names=("ngettext",)) |
2674 | + locale.bindtextdomain(package_name, MESSAGES_DIR) |
2675 | + locale.bind_textdomain_codeset(package_name, "UTF-8") |
2676 | + |
2677 | + try: |
2678 | + locale.setlocale(locale.LC_ALL, "") |
2679 | + except locale.Error, e: |
2680 | + pass |
2681 | + |
2682 | +setup_locale_and_gettext() |
2683 | |
2684 | === added file 'build/lib.linux-i686-2.6/spectlib/i18n_safedict.py' |
2685 | --- build/lib.linux-i686-2.6/spectlib/i18n_safedict.py 1970-01-01 00:00:00 +0000 |
2686 | +++ build/lib.linux-i686-2.6/spectlib/i18n_safedict.py 2012-03-14 09:03:18 +0000 |
2687 | @@ -0,0 +1,70 @@ |
2688 | +# Copyright (C) 1998,1999,2000,2001,2002 by the Free Software Foundation, Inc. |
2689 | +# |
2690 | +# This program is free software; you can redistribute it and/or |
2691 | +# modify it under the terms of the GNU General Public License |
2692 | +# as published by the Free Software Foundation; either version 2 |
2693 | +# of the License, or (at your option) any later version. |
2694 | +# |
2695 | +# This program is distributed in the hope that it will be useful, |
2696 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2697 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
2698 | +# GNU General Public License for more details. |
2699 | +# |
2700 | +# You should have received a copy of the GNU General Public License |
2701 | +# along with this program; if not, write to the Free Software |
2702 | +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
2703 | + |
2704 | +"""A `safe' dictionary for string interpolation.""" |
2705 | + |
2706 | +from types import StringType |
2707 | +from UserDict import UserDict |
2708 | + |
2709 | +COMMASPACE = ', ' |
2710 | + |
2711 | + |
2712 | +class SafeDict(UserDict): |
2713 | + """Dictionary which returns a default value for unknown keys. |
2714 | + |
2715 | + This is used in maketext so that editing templates is a bit more robust. |
2716 | + """ |
2717 | + |
2718 | + def __getitem__(self, key): |
2719 | + try: |
2720 | + return self.data[key] |
2721 | + except KeyError: |
2722 | + if isinstance(key, StringType): |
2723 | + return '%('+key+')s' |
2724 | + else: |
2725 | + return '<Missing key: %s>' % `key` |
2726 | + |
2727 | + def interpolate(self, template): |
2728 | + return template % self |
2729 | + |
2730 | + |
2731 | +class MsgSafeDict(SafeDict): |
2732 | + |
2733 | + def __init__(self, msg, dict=None): |
2734 | + self.__msg = msg |
2735 | + SafeDict.__init__(self, dict) |
2736 | + |
2737 | + def __getitem__(self, key): |
2738 | + if key.startswith('msg_'): |
2739 | + return self.__msg.get(key[4:], 'n/a') |
2740 | + elif key.startswith('allmsg_'): |
2741 | + missing = [] |
2742 | + all = self.__msg.get_all(key[7:], missing) |
2743 | + if all is missing: |
2744 | + return 'n/a' |
2745 | + return COMMASPACE.join(all) |
2746 | + else: |
2747 | + return SafeDict.__getitem__(self, key) |
2748 | + |
2749 | + def copy(self): |
2750 | + d = self.data.copy() |
2751 | + for k in self.__msg.keys(): |
2752 | + vals = self.__msg.get_all(k) |
2753 | + if len(vals) == 1: |
2754 | + d['msg_'+k.lower()] = vals[0] |
2755 | + else: |
2756 | + d['allmsg_'+k.lower()] = COMMASPACE.join(vals) |
2757 | + return d |
2758 | |
2759 | === added file 'build/lib.linux-i686-2.6/spectlib/imail.py' |
2760 | --- build/lib.linux-i686-2.6/spectlib/imail.py 1970-01-01 00:00:00 +0000 |
2761 | +++ build/lib.linux-i686-2.6/spectlib/imail.py 2012-03-14 09:03:18 +0000 |
2762 | @@ -0,0 +1,294 @@ |
2763 | +# -*- coding: utf-8 -*- |
2764 | + |
2765 | +# Specto , Unobtrusive event notifier |
2766 | +# |
2767 | +# imail.py |
2768 | +# |
2769 | +# See the AUTHORS file for copyright ownership information |
2770 | + |
2771 | +# This program is free software; you can redistribute it and/or |
2772 | +# modify it under the terms of the GNU General Public |
2773 | +# License as published by the Free Software Foundation; either |
2774 | +# version 2 of the License, or (at your option) any later version. |
2775 | +# |
2776 | +# This program is distributed in the hope that it will be useful, |
2777 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
2778 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2779 | +# General Public License for more details. |
2780 | +# |
2781 | +# You should have received a copy of the GNU General Public |
2782 | +# License along with this program; if not, write to the |
2783 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
2784 | +# Boston, MA 02111-1307, USA. |
2785 | + |
2786 | +import smtplib |
2787 | +import sys |
2788 | + |
2789 | +keyring = True |
2790 | +try: |
2791 | + from spectlib.tools.keyringmanager import Keyring |
2792 | +except: |
2793 | + keyring = False |
2794 | + |
2795 | +from email.mime.multipart import MIMEMultipart |
2796 | +from email.mime.text import MIMEText |
2797 | +from spectlib.bdd import Group, Mail |
2798 | + |
2799 | +class Imail(): |
2800 | + """Class who send email alert """ |
2801 | + def __init__(self,adresse,specto,name,values,item): |
2802 | + self.specto_adr = "specto@mail.com" |
2803 | + self.adr = adresse |
2804 | +## print values |
2805 | + # Create message container - the correct MIME type is multipart/alternative. |
2806 | + self.msg = MIMEMultipart('alternative') |
2807 | + self.msg['Subject'] = "Alerte specto" |
2808 | + self.msg['From'] = self.specto_adr |
2809 | + self.msg['To'] = self.adr |
2810 | + self.specto = specto |
2811 | + self.name = name |
2812 | + #get settings |
2813 | + self.smtp = self.specto.specto_gconf.get_entry("smtp_entry") |
2814 | +## print self.smtp |
2815 | + self.User = self.specto.specto_gconf.get_entry("login_entry") |
2816 | + if self.specto.use_keyring == True and keyring == True: |
2817 | + try: |
2818 | + k = Keyring("password_entry", "Specto " + "password_entry", "network") |
2819 | + self.Password = k.get_credentials()[1] |
2820 | + except: |
2821 | + self.Password = self.specto.specto_gconf.get_entry("password_entry") |
2822 | + self.tls = self.specto.specto_gconf.get_entry("button_tls") |
2823 | + |
2824 | + listgroup = self.specto.base.getAll(Group) |
2825 | + listmail = self.specto.base.getAll(Mail) |
2826 | + self.list = self.get_mail_tosend(listmail,listgroup) |
2827 | +## self.alert_html(name,values['pattern'],item,values['uri']) |
2828 | + |
2829 | + def alert_rss(self,name,pattern,title,link,description): |
2830 | + """ Send Email for rss alert""" |
2831 | + description = '"'+description+'"' |
2832 | + # Create the body of the message (a plain-text and an HTML version). |
2833 | + text = "Bonjour,\nUne alerte a été générée par l'observateur "+name+" suite à l'apparition du motif "+pattern+"\n"+title+"\n"+link+"\n"+description+"" |
2834 | + html = """\ |
2835 | + <html> |
2836 | + <head></head> |
2837 | + <body> |
2838 | + <p>Bonjour,<br><br> |
2839 | + Une alerte a été générée par l'observateur <u>"""+name+"""</u> suite à l'apparition du motif <i>"""+pattern+"""</i><br><br> |
2840 | + <a href="""+link+""">"""+title+"""</a><br> |
2841 | + """+description+""" |
2842 | + </p> |
2843 | + </body> |
2844 | + </html> |
2845 | + """ |
2846 | + |
2847 | + # Record the MIME types of both parts - text/plain and text/html. |
2848 | + part1 = MIMEText(text, 'plain') |
2849 | + part2 = MIMEText(html, 'html') |
2850 | + |
2851 | + # Attach parts into message container. |
2852 | + # According to RFC 2046, the last part of a multipart message, in this case |
2853 | + # the HTML message, is best and preferred. |
2854 | + self.msg.attach(part1) |
2855 | + self.msg.attach(part2) |
2856 | + |
2857 | + try: |
2858 | + if (self.smtp != ""): |
2859 | + for m in self.list: |
2860 | + self.s = smtplib.SMTP(self.smtp) |
2861 | + if self.tls == True: |
2862 | + self.s.ehlo() |
2863 | + self.s.starttls() |
2864 | + self.s.ehlo() |
2865 | + if (self.User != "") and (self.Password != ""): |
2866 | + self.s.login(self.User, self.Password) |
2867 | + self.s.sendmail(self.specto_adr, m, self.msg.as_string()) |
2868 | + self.s.quit() |
2869 | + except: |
2870 | + self.set_error() |
2871 | + |
2872 | + def alert_html(self,name,pattern,item,link): |
2873 | +## print "bonjour alerte html dans imail" |
2874 | +## print name,pattern,item,link |
2875 | + """ Send Email for html alert """ |
2876 | + # Create the body of the message (a plain-text and an HTML version). |
2877 | + text = "Bonjour,\nUne alerte a ete generee par l'observateur "+name+" suite a l'apparition du motif "+pattern+"\n Lien vers la page : "+link+"\n"+item+"\n" |
2878 | + html = """\ |
2879 | + <html> |
2880 | + <head></head> |
2881 | + <body> |
2882 | + <p>Bonjour,<br><br> |
2883 | + Une alerte a été générée par l'observateur <u>"""+name+"""</u> suite à l'apparition du motif <i>"""+pattern+"""</i><br><br> |
2884 | + <a href="""+link+""">Lien vers la page</a><br> |
2885 | + """+item+""" |
2886 | + </p> |
2887 | + </body> |
2888 | + </html> |
2889 | + """ |
2890 | + # Record the MIME types of both parts - text/plain and text/html. |
2891 | + part1 = MIMEText(text, 'plain') |
2892 | + #part2 = MIMEText(html, 'html') |
2893 | + |
2894 | + # Attach parts into message container. |
2895 | + # According to RFC 2046, the last part of a multipart message, in this case |
2896 | + # the HTML message, is best and preferred. |
2897 | + self.msg.attach(part1) |
2898 | + #self.msg.attach(part2) |
2899 | + |
2900 | + try: |
2901 | + if (self.smtp != ""): |
2902 | + for m in self.list: |
2903 | + self.s = smtplib.SMTP(self.smtp) |
2904 | + if self.tls == True: |
2905 | + self.s.ehlo() |
2906 | + self.s.starttls() |
2907 | + self.s.ehlo() |
2908 | + if (self.User != "") and (self.Password != ""): |
2909 | + self.s.login(self.User, self.Password) |
2910 | +## print "before" |
2911 | + self.s.sendmail(self.specto_adr, m, self.msg.as_string()) |
2912 | +## print "Message send" |
2913 | + self.s.quit() |
2914 | + except: |
2915 | + self.set_error() |
2916 | + |
2917 | + def alert_pdfhtml(self,name,pattern,item,link): |
2918 | +## print "bonjour alerte pdfhtml dans imail" |
2919 | +## print name,pattern,item,link |
2920 | + """ Send Email for html alert """ |
2921 | + # Create the body of the message (a plain-text and an HTML version). |
2922 | + text = "Bonjour,\nUne alerte a ete generee par l'observateur "+name+" suite a l'apparition du motif "+pattern+"\n dans le document PDF : "+link+"\n"+item+"\n" |
2923 | + html = """\ |
2924 | + <html> |
2925 | + <head></head> |
2926 | + <body> |
2927 | + <p>Bonjour,<br><br> |
2928 | + Une alerte a été générée par l'observateur <u>"""+name+"""</u> suite à l'apparition du motif <i>"""+pattern+"""</i><br><br> |
2929 | + <a href="""+link+""">Document PDF</a><br> |
2930 | + """+item+""" |
2931 | + </p> |
2932 | + </body> |
2933 | + </html> |
2934 | + """ |
2935 | + # Record the MIME types of both parts - text/plain and text/html. |
2936 | + part1 = MIMEText(text, 'plain') |
2937 | + #part2 = MIMEText(html, 'html') |
2938 | + |
2939 | + # Attach parts into message container. |
2940 | + # According to RFC 2046, the last part of a multipart message, in this case |
2941 | + # the HTML message, is best and preferred. |
2942 | + self.msg.attach(part1) |
2943 | + #self.msg.attach(part2) |
2944 | +## print html |
2945 | + try: |
2946 | + if (self.smtp != ""): |
2947 | + for m in self.list: |
2948 | + self.s = smtplib.SMTP(self.smtp) |
2949 | + if self.tls == True: |
2950 | + self.s.ehlo() |
2951 | + self.s.starttls() |
2952 | + self.s.ehlo() |
2953 | + if (self.User != "") and (self.Password != ""): |
2954 | + self.s.login(self.User, self.Password) |
2955 | +## print "before" |
2956 | + self.s.sendmail(self.specto_adr, m, self.msg.as_string()) |
2957 | +## print "Message send" |
2958 | + self.s.quit() |
2959 | + except: |
2960 | + self.set_error() |
2961 | + |
2962 | + def get_adr(self): |
2963 | + """ return adress """ |
2964 | + return self.adr |
2965 | + |
2966 | + def set_error(self, message=""): |
2967 | + self.error = True |
2968 | + if message != "": |
2969 | + self.error_message = str(message).replace('\n',' ') |
2970 | + self.specto.logger.log(('%s') % self.error_message, "error", self.name) |
2971 | + else: |
2972 | + self.error_message = _("Unexpected error:") + " " + str(sys.exc_info()[1]) |
2973 | + self.specto.logger.log(self.error_message, "error", self.name) |
2974 | + |
2975 | + def check_mail_conf(self): |
2976 | + """ check if something change in mail settings """ |
2977 | + if (self.specto.specto_gconf.get_entry("smtp_entry") != self.smtp): |
2978 | + self.smtp = self.specto.specto_gconf.get_entry("smtp_entry") |
2979 | + self.User = self.specto.specto_gconf.get_entry("login_entry") |
2980 | + |
2981 | + if self.specto.use_keyring == True and keyring == True: |
2982 | + try: |
2983 | + k = Keyring("password_entry", "Specto " + "password_entry", "network") |
2984 | + self.Password = k.get_credentials()[1] |
2985 | + except: |
2986 | + self.Password = self.specto.specto_gconf.get_entry("password_entry") |
2987 | + |
2988 | + def get_mail_tosend(self,listmail,listgroup): |
2989 | + tosend = [] |
2990 | + for g in listgroup: |
2991 | + if g.name == self.adr: |
2992 | + for m in listmail: |
2993 | + if m.group == self.adr: |
2994 | + tosend.append(m.mail) |
2995 | + if len(tosend) == 0: |
2996 | + tosend.append(self.adr) |
2997 | + return tosend |
2998 | + |
2999 | +class Mail_test(): |
3000 | + """ class to test mail settings""" |
3001 | + def __init__(self,specto,tmp_smtp,tmp_log,tmp_pass,tmp_mail,tmp_tls): |
3002 | + self.specto_adr = "specto@mail.com" |
3003 | + self.adr = tmp_mail |
3004 | + |
3005 | + self.msg = MIMEMultipart('alternative') |
3006 | + self.msg['Subject'] = "Message de test" |
3007 | + self.msg['From'] = self.specto_adr |
3008 | + self.msg['To'] = self.adr |
3009 | + self.specto = specto |
3010 | + self.error_message = "Un message de test a été envoyé sur votre adresse" |
3011 | + |
3012 | + self.smtp = tmp_smtp |
3013 | + self.User = tmp_log |
3014 | + self.Password = tmp_pass |
3015 | + self.tls = tmp_tls |
3016 | + |
3017 | + def test_settings(self): |
3018 | + """ method to test mail settings """ |
3019 | + text = "Bonjour,\nSi vous voyez ce message c'est que vos paramètres sont bien configurés\n Enjoy!" |
3020 | + html = """\ |
3021 | + <html> |
3022 | + <head></head> |
3023 | + <body> |
3024 | + <p>Bonjour,<br><br> |
3025 | + Si vous voyez ce message c'est que vos paramètres sont bien configurés\n<br><br> |
3026 | + Enjoy ! |
3027 | + </p> |
3028 | + </body> |
3029 | + </html> |
3030 | + """ |
3031 | + |
3032 | + part1 = MIMEText(text, 'plain') |
3033 | + part2 = MIMEText(html, 'html') |
3034 | + |
3035 | + self.msg.attach(part1) |
3036 | + self.msg.attach(part2) |
3037 | + |
3038 | + if (self.smtp != ""): |
3039 | + try: |
3040 | + self.s = smtplib.SMTP(self.smtp) |
3041 | + if self.tls == True: |
3042 | + self.s.ehlo() |
3043 | + self.s.starttls() |
3044 | + self.s.ehlo() |
3045 | + if (self.User != "") and (self.Password != ""): |
3046 | + self.s.login(self.User, self.Password) |
3047 | + self.s.sendmail(self.specto_adr, self.adr, self.msg.as_string()) |
3048 | + self.s.quit() |
3049 | + except: |
3050 | + self.set_error() |
3051 | + |
3052 | + def set_error(self, message=""): |
3053 | + self.error_message = _("Unexpected error:")+ str(sys.exc_info()[1]) |
3054 | + |
3055 | + def get_error(self): |
3056 | + return self.error_message |
3057 | |
3058 | === added file 'build/lib.linux-i686-2.6/spectlib/import_watch.py' |
3059 | --- build/lib.linux-i686-2.6/spectlib/import_watch.py 1970-01-01 00:00:00 +0000 |
3060 | +++ build/lib.linux-i686-2.6/spectlib/import_watch.py 2012-03-14 09:03:18 +0000 |
3061 | @@ -0,0 +1,281 @@ |
3062 | +# -*- coding: utf-8 -*- |
3063 | + |
3064 | +# Specto , Unobtrusive event notifier |
3065 | +# |
3066 | +# import_export.py |
3067 | +# |
3068 | +# See the AUTHORS file for copyright ownership information |
3069 | + |
3070 | +# This program is free software; you can redistribute it and/or |
3071 | +# modify it under the terms of the GNU General Public |
3072 | +# License as published by the Free Software Foundation; either |
3073 | +# version 2 of the License, or (at your option) any later version. |
3074 | +# |
3075 | +# This program is distributed in the hope that it will be useful, |
3076 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3077 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
3078 | +# General Public License for more details. |
3079 | +# |
3080 | +# You should have received a copy of the GNU General Public |
3081 | +# License along with this program; if not, write to the |
3082 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
3083 | +# Boston, MA 02111-1307, USA. |
3084 | + |
3085 | +import os |
3086 | +from spectlib.watch import Watch_io |
3087 | +from spectlib.watch import Watch_collection |
3088 | +from spectlib.gtkconfig import OpenDialog |
3089 | + |
3090 | +try: |
3091 | + import pygtk |
3092 | + pygtk.require("2.0") |
3093 | +except: |
3094 | + pass |
3095 | + |
3096 | +try: |
3097 | + import gtk |
3098 | + import gobject |
3099 | +except: |
3100 | + pass |
3101 | + |
3102 | + |
3103 | +class Import_watch: |
3104 | + """ |
3105 | + Class to create the import/export watch dialog. |
3106 | + """ |
3107 | + |
3108 | + def __init__(self, specto, notifier): |
3109 | + self.specto = specto |
3110 | + self.notifier = notifier |
3111 | + |
3112 | + self.import_open_dialog = ImportOpenDialog(self.specto, self, None) |
3113 | + response = self.import_open_dialog.run() |
3114 | + if response == gtk.RESPONSE_OK: |
3115 | + self.import_open_dialog.open() |
3116 | + else: |
3117 | + self.import_open_dialog.cancel() |
3118 | + |
3119 | + def create_import_window(self): |
3120 | + #create tree |
3121 | + uifile = os.path.join(self.specto.PATH, "uis/import_export.ui") |
3122 | + windowname = "import_export" |
3123 | + self.builder = gtk.Builder() |
3124 | + self.builder.set_translation_domain("specto") |
3125 | + self.builder.add_from_file(uifile) |
3126 | + self.import_watch = self.builder.get_object("import_export") |
3127 | + |
3128 | + self.import_watch.set_title(_("Import watches")) |
3129 | + self.builder.get_object("button_action").set_label(_("Import watches")) |
3130 | + |
3131 | + self.model = gtk.ListStore(gobject.TYPE_BOOLEAN, gtk.gdk.Pixbuf, gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_STRING) |
3132 | + self.new_watch_db = {} |
3133 | + |
3134 | + #catch some events |
3135 | + dic = {"on_button_select_all_clicked": self.select_all, |
3136 | + "on_button_deselect_all_clicked": self.deselect_all, |
3137 | + "on_button_action_clicked": self.import_watches, |
3138 | + "on_button_close_clicked": self.delete_event} |
3139 | + |
3140 | + #attach the events |
3141 | + self.builder.connect_signals(dic) |
3142 | + |
3143 | + icon = gtk.gdk.pixbuf_new_from_file(os.path.join(self.specto.PATH, "icons/specto_window_icon.png")) |
3144 | + self.import_watch.set_icon(icon) |
3145 | + |
3146 | + self.treeview = self.builder.get_object("treeview") |
3147 | + self.treeview.set_model(self.model) |
3148 | + self.treeview.set_flags(gtk.TREE_MODEL_ITERS_PERSIST) |
3149 | + self.iter = {} |
3150 | + |
3151 | + ### Checkbox |
3152 | + self.renderer = gtk.CellRendererToggle() |
3153 | + self.renderer.set_property("activatable", True) |
3154 | + self.renderer.connect("toggled", self.check_clicked, self.model) |
3155 | + self.columnCheck = gtk.TreeViewColumn(_("Select"), self.renderer, active=0) |
3156 | + self.treeview.append_column(self.columnCheck) |
3157 | + |
3158 | + ### Icon |
3159 | + self.renderer = gtk.CellRendererPixbuf() |
3160 | + self.columnIcon = gtk.TreeViewColumn(_("Type"), self.renderer, pixbuf=1) |
3161 | + self.treeview.append_column(self.columnIcon) |
3162 | + |
3163 | + ### Titre |
3164 | + self.renderer = gtk.CellRendererText() |
3165 | + self.columnTitel = gtk.TreeViewColumn(_("Name"), self.renderer, markup=2) |
3166 | + self.columnTitel.set_expand(True) |
3167 | + self.columnTitel.set_resizable(True) |
3168 | + self.treeview.append_column(self.columnTitel) |
3169 | + |
3170 | + ### ID |
3171 | + self.renderer = gtk.CellRendererText() |
3172 | + self.column = gtk.TreeViewColumn(_("ID"), self.renderer, markup=3) |
3173 | + self.column.set_visible(False) |
3174 | + #self.column.set_sort_column_id(3) |
3175 | + self.treeview.append_column(self.column) |
3176 | + |
3177 | + ### type |
3178 | + self.renderer = gtk.CellRendererText() |
3179 | + self.columnType = gtk.TreeViewColumn(_("TYPE"), self.renderer, markup=4) |
3180 | + self.columnType.set_visible(False) |
3181 | + #self.columnType.set_sort_column_id(4) |
3182 | + self.treeview.append_column(self.columnType) |
3183 | + |
3184 | + def select_all(self, widget): |
3185 | + db = self.new_watch_db |
3186 | + for watch in db: |
3187 | + if watch.deleted == False: |
3188 | + self.model.set_value(self.iter[watch.id], 0, 1) |
3189 | + |
3190 | + def deselect_all(self, widget): |
3191 | + db = self.new_watch_db |
3192 | + for watch in db: |
3193 | + if watch.deleted == False: |
3194 | + self.model.set_value(self.iter[watch.id], 0, 0) |
3195 | + |
3196 | + def import_watches(self, widget): |
3197 | + self.import_watch.hide_all() |
3198 | + |
3199 | + watches = self.get_selected_watches() |
3200 | + all_values = {} |
3201 | + for i in watches: |
3202 | + values = {} |
3203 | + watch = self.new_watch_db[watches[i].id] |
3204 | + values.update(self.new_watch_db[watches[i].id].get_values()) |
3205 | + |
3206 | + values['name'] = watch.name |
3207 | + if self.specto.watch_io.is_unique_watch(values['name']): |
3208 | + y = 1 |
3209 | + while self.specto.watch_io.is_unique_watch(values['name'] + str(y)): |
3210 | + y += 1 |
3211 | + values['name'] = values['name'] + str(y) |
3212 | + |
3213 | + values['type'] = watch.type |
3214 | + values['refresh'] = watch.refresh |
3215 | + values['active'] = True |
3216 | + values['last_changed'] = watch.last_changed |
3217 | + values['changed'] = False |
3218 | + all_values[i] = values |
3219 | + _id = self.specto.watch_db.create(all_values) |
3220 | + |
3221 | + for values in all_values.values(): |
3222 | + self.specto.watch_io.write_watch(values) |
3223 | + |
3224 | + for id in _id: # Create notifier entries |
3225 | + self.specto.notifier.add_notifier_entry(id) |
3226 | + |
3227 | + for id in _id: # Start the new watches |
3228 | + self.specto.watch_db[id].start() |
3229 | + |
3230 | + def delete_event(self, widget, *args): |
3231 | + """ Destroy the window. """ |
3232 | + self.import_watch.destroy() |
3233 | + return True |
3234 | + |
3235 | + def get_selected_watches(self): |
3236 | + selected_watches_db = {} |
3237 | + i = 0 |
3238 | + watch_db = self.new_watch_db |
3239 | + for watch in watch_db: |
3240 | + if watch.deleted == False: |
3241 | + if self.model.get_value(self.iter[watch.id], 0) == True: |
3242 | + selected_watches_db[i] = watch |
3243 | + i += 1 |
3244 | + return selected_watches_db |
3245 | + |
3246 | + def add_watch_entry(self, id): |
3247 | + """ Add an entry to the notifier list. """ |
3248 | + watch = self.new_watch_db[id] |
3249 | + entry_name = watch.name.replace("&", "&") |
3250 | + icon = self.notifier.get_icon(watch.icon, 50, False) |
3251 | + self.iter[id] = self.model.insert_before(None, None) |
3252 | + self.model.set_value(self.iter[id], 0, 0) |
3253 | + self.model.set_value(self.iter[id], 1, icon)#self.specto.notifier.make_transparent(icon, 50))#does not need transparency here |
3254 | + self.model.set_value(self.iter[id], 2, entry_name) |
3255 | + self.model.set_value(self.iter[id], 3, watch.id) |
3256 | + self.model.set_value(self.iter[id], 4, watch.type) |
3257 | + |
3258 | + def set_new_watch_db(self, watch_db): |
3259 | + self.new_watch_db = watch_db |
3260 | + |
3261 | + def check_clicked(self, object, path, model): |
3262 | + """ Call the main function to start/stop the selected watch. """ |
3263 | + sel = self.treeview.get_selection() |
3264 | + sel.select_path(path) |
3265 | + model, iter = self.treeview.get_selection().get_selected() |
3266 | + |
3267 | + if model.get_value(iter, 0): |
3268 | + model.set_value(iter, 0, 0) |
3269 | + else: |
3270 | + model.set_value(iter, 0, 1) |
3271 | + |
3272 | + |
3273 | +class ImportOpenDialog(OpenDialog): |
3274 | + """ |
3275 | + Class for displaying the open dialog. |
3276 | + """ |
3277 | + |
3278 | + def __init__(self, specto, _import, watches_db): |
3279 | + OpenDialog.__init__(self, specto) |
3280 | + self.specto = specto |
3281 | + self._import = _import |
3282 | + windowname = "import_file_chooser" |
3283 | + |
3284 | + def open(self, *args): |
3285 | + """ Save the file. """ |
3286 | + self.hide_all() |
3287 | + self._import.create_import_window() |
3288 | + file_name = self.get_filename() |
3289 | + self.read_options(file_name) |
3290 | + self._import.import_watch.show() |
3291 | + self.destroy() |
3292 | + |
3293 | + def read_options(self, file_name): |
3294 | + watch_io = Watch_io(self.specto, file_name) |
3295 | + if watch_io.valid == False: |
3296 | + return False |
3297 | + |
3298 | + values = watch_io.read_all_watches() |
3299 | + for i in values: |
3300 | + try: |
3301 | + int(values[i]['type']) |
3302 | + except: |
3303 | + pass |
3304 | + else: |
3305 | + values[i]['open_command'] = "" |
3306 | + values[i]['last_changed'] = "" |
3307 | + |
3308 | + # Import from Specto 0.2 |
3309 | + # FIXME: wouldn't this code be more efficient with a case/switch? |
3310 | + if values[i]['type'] == "0": |
3311 | + values[i]['type'] = "Watch_web_static" |
3312 | + elif values[i]['type'] == "1": |
3313 | + if values[i]['prot'] == "0": |
3314 | + values[i]['type'] = "Watch_mail_pop3" |
3315 | + if values[i]['prot'] == "1": |
3316 | + values[i]['type'] = "Watch_mail_imap" |
3317 | + if values[i]['prot'] == "2": |
3318 | + values[i]['type'] = "Watch_mail_gmail" |
3319 | + del values[i]['prot'] |
3320 | + elif values[i]['type'] == "2": |
3321 | + if values[i]['mode'] == "file": |
3322 | + values[i]['type'] = "Watch_system_file" |
3323 | + else: |
3324 | + values[i]['type'] = "Watch_system_folder" |
3325 | + del values[i]['mode'] |
3326 | + elif values[i]['type'] == "3": |
3327 | + values[i]['type'] = "Watch_system_process" |
3328 | + elif values[i]['type'] == "4": |
3329 | + values[i]['type'] = "Watch_system_port" |
3330 | + elif values[i]['type'] == "5": |
3331 | + values[i]['type'] = "Watch_web_greader" |
3332 | + watch_collection = Watch_collection(self.specto) |
3333 | + watch_collection.create(values) |
3334 | + self._import.set_new_watch_db(watch_collection) |
3335 | + for watch in watch_collection: |
3336 | + self._import.add_watch_entry(watch.id) |
3337 | + |
3338 | + |
3339 | +if __name__ == "__main__": |
3340 | + # Run the gui |
3341 | + app = Import_watch() |
3342 | + gtk.main() |
3343 | |
3344 | === added file 'build/lib.linux-i686-2.6/spectlib/logger.py' |
3345 | --- build/lib.linux-i686-2.6/spectlib/logger.py 1970-01-01 00:00:00 +0000 |
3346 | +++ build/lib.linux-i686-2.6/spectlib/logger.py 2012-03-14 09:03:18 +0000 |
3347 | @@ -0,0 +1,344 @@ |
3348 | +# -*- coding: utf-8 -*- |
3349 | + |
3350 | +# Specto , Unobtrusive event notifier |
3351 | +# |
3352 | +# logger.py |
3353 | +# |
3354 | +# See the AUTHORS file for copyright ownership information |
3355 | + |
3356 | +# This program is free software; you can redistribute it and/or |
3357 | +# modify it under the terms of the GNU General Public |
3358 | +# License as published by the Free Software Foundation; either |
3359 | +# version 2 of the License, or (at your option) any later version. |
3360 | +# |
3361 | +# This program is distributed in the hope that it will be useful, |
3362 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3363 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
3364 | +# General Public License for more details. |
3365 | +# |
3366 | +# You should have received a copy of the GNU General Public |
3367 | +# License along with this program; if not, write to the |
3368 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
3369 | +# Boston, MA 02111-1307, USA. |
3370 | +import logging |
3371 | +import sys |
3372 | +import os |
3373 | +import re |
3374 | +from datetime import datetime |
3375 | +import traceback |
3376 | +import shutil |
3377 | + |
3378 | +try: |
3379 | + import pygtk |
3380 | + pygtk.require("2.0") |
3381 | +except: |
3382 | + pass |
3383 | + |
3384 | +try: |
3385 | + import gtk |
3386 | +except: |
3387 | + pass |
3388 | + |
3389 | +from spectlib.gtkconfig import SaveDialog |
3390 | + |
3391 | + |
3392 | +class Log_dialog: |
3393 | + """ |
3394 | + Class to create the log dialog window. |
3395 | + """ |
3396 | + |
3397 | + def __init__(self, specto, notifier): |
3398 | + self.specto = specto |
3399 | + self.notifier = notifier |
3400 | + #create tree |
3401 | + uifile = os.path.join(self.specto.PATH, "uis/log_dialog.ui") |
3402 | + windowname = "log_dialog" |
3403 | + self.builder = gtk.Builder() |
3404 | + self.builder.set_translation_domain("specto") |
3405 | + self.builder.add_from_file(uifile) |
3406 | + |
3407 | + dic = {"on_button_help_clicked": self.show_help, |
3408 | + "on_button_save_clicked": self.save, |
3409 | + "on_button_clear_clicked": self.clear, |
3410 | + "on_button_close_clicked": self.delete_event, |
3411 | + "on_button_find_clicked": self.find} |
3412 | + |
3413 | + #attach the events |
3414 | + self.builder.connect_signals(dic) |
3415 | + |
3416 | + self.log_dialog = self.builder.get_object("log_dialog") |
3417 | + icon = gtk.gdk.pixbuf_new_from_file(os.path.join(self.specto.PATH, "icons/specto_window_icon.png")) |
3418 | + self.log_dialog.set_icon(icon) |
3419 | + |
3420 | + self.builder.get_object("combo_level").set_active(0) |
3421 | + |
3422 | + #read the log file |
3423 | + self.read_log() |
3424 | + |
3425 | + self.logwindow = gtk.TextBuffer(None) |
3426 | + self.log_buffer = self.builder.get_object("log_field").get_buffer() |
3427 | + self.log_buffer.create_tag("ERROR", foreground="#a40000") |
3428 | + self.log_buffer.create_tag("INFO", foreground="#4e9a06") |
3429 | + self.log_buffer.create_tag("WARNING", foreground="#c4a000") |
3430 | + self.log_buffer.create_tag("DEBUG", foreground="#815902") |
3431 | + self.log_buffer.create_tag("CRITICAL", foreground="#2e3436") |
3432 | + |
3433 | + start = self.log_buffer.get_start_iter() |
3434 | + end = self.log_buffer.get_end_iter() |
3435 | + self.log_buffer.delete(start, end) |
3436 | + |
3437 | + iter = self.log_buffer.get_iter_at_offset(0) |
3438 | + self.log = self.log.split("\n") |
3439 | + for line in self.log: |
3440 | + if line != "": |
3441 | + tag = line.split(" - ")[1].strip() |
3442 | + self.log_buffer.insert_with_tags_by_name(iter, \ |
3443 | + line + "\n", tag) |
3444 | + |
3445 | + def save(self, widget): |
3446 | + """ Save the text in the logwindow. """ |
3447 | + text = self.log_buffer.get_text(self.log_buffer.get_start_iter(), \ |
3448 | + self.log_buffer.get_end_iter()) |
3449 | + logger_save_dialog = LoggerSaveDialog(self.specto, text) |
3450 | + response = logger_save_dialog.run() |
3451 | + if response == gtk.RESPONSE_OK: |
3452 | + logger_save_dialog.save() |
3453 | + else: |
3454 | + logger_save_dialog.cancel() |
3455 | + |
3456 | + |
3457 | + def clear(self, widget): |
3458 | + """ Clear the text in the log window and from the log file. """ |
3459 | + start = self.log_buffer.get_start_iter() |
3460 | + end = self.log_buffer.get_end_iter() |
3461 | + self.log_buffer.delete(start, end) |
3462 | + f = open(self.file_name, "w") |
3463 | + f.write("") |
3464 | + f.close() |
3465 | + os.chmod(self.file_name, 0600) |
3466 | + |
3467 | + def find(self, widget): |
3468 | + """ Find the lines in the log file that contain the filter word. """ |
3469 | + self.read_log() |
3470 | + level = self.builder.get_object("combo_level").get_active() |
3471 | + buffer_log = self.log.split("\n") |
3472 | + filtered_log = "" |
3473 | + |
3474 | + if level == 1: |
3475 | + pattern = ("DEBUG") |
3476 | + elif level == 2: |
3477 | + pattern = ("INFO") |
3478 | + elif level == 3: |
3479 | + pattern = ("WARNING") |
3480 | + elif level == 4: |
3481 | + pattern = ("ERROR") |
3482 | + elif level == 5: |
3483 | + pattern = ("CRITICAL") |
3484 | + elif level == -1: |
3485 | + pattern = self.builder.get_object("combo_level").child.get_text() |
3486 | + |
3487 | + start = self.log_buffer.get_start_iter() |
3488 | + end = self.log_buffer.get_end_iter() |
3489 | + self.log_buffer.delete(start, end) |
3490 | + iter = self.log_buffer.get_iter_at_offset(0) |
3491 | + |
3492 | + if level == 0: # Show everything |
3493 | + for line in buffer_log: |
3494 | + if line: # If the line is not empty |
3495 | + tag = line.split(" - ")[1].strip() |
3496 | + self.log_buffer.insert_with_tags_by_name(iter, \ |
3497 | + line + "\n", tag) |
3498 | + else: # Show the filtered log |
3499 | + # Do the filtering |
3500 | + for i in buffer_log: |
3501 | + if re.search(pattern, i, re.IGNORECASE): |
3502 | + filtered_log += i + "\n" |
3503 | + filtered_log = filtered_log.split("\n") |
3504 | + for line in filtered_log: |
3505 | + if line: # If the line is not empty |
3506 | + tag = line.split(" - ")[1].strip() |
3507 | + self.log_buffer.insert_with_tags_by_name(iter, \ |
3508 | + line + "\n", tag) |
3509 | + |
3510 | + def read_log(self): |
3511 | + """ Read the log file. """ |
3512 | + self.file_name = self.specto.SPECTO_DIR + "/specto.log" |
3513 | + if not os.path.exists(self.file_name): |
3514 | + f = open(self.file_name, "w") |
3515 | + f.close() |
3516 | + os.chmod(self.file_name, 0600) |
3517 | + |
3518 | + log_file = open(self.file_name, "r") |
3519 | + self.log = log_file.read().replace("&Separator;", " - ") |
3520 | + log_file.close() |
3521 | + |
3522 | + def show_help(self, widget): |
3523 | + """ Show the help webpage. """ |
3524 | + self.specto.util.show_webpage(\ |
3525 | + "http://code.google.com/p/specto/wiki/Troubleshooting") |
3526 | + |
3527 | + def delete_event(self, widget, *args): |
3528 | + """ Close the window. """ |
3529 | + self.log_dialog.destroy() |
3530 | + return True |
3531 | + |
3532 | + |
3533 | +class LoggerSaveDialog(SaveDialog): |
3534 | + """ |
3535 | + Class for displaying the save as dialog. |
3536 | + """ |
3537 | + |
3538 | + def __init__(self, specto, *args): |
3539 | + SaveDialog.__init__(self, specto) |
3540 | + windowname = "logger_file_chooser" |
3541 | + |
3542 | + self.text = args[0] |
3543 | + |
3544 | + def save(self, *args): |
3545 | + """ Save the file. """ |
3546 | + file_name = self.get_filename() |
3547 | + |
3548 | + if not os.path.exists(file_name): |
3549 | + f = open(file_name, "w") |
3550 | + f.close() |
3551 | + os.chmod(file_name, 0600) |
3552 | + |
3553 | + f = open(file_name, "w") |
3554 | + f.write(self.text) |
3555 | + f.close() |
3556 | + |
3557 | + self.destroy() |
3558 | + |
3559 | + |
3560 | +class Logger: |
3561 | + """ |
3562 | + Class for logging in Specto. |
3563 | + """ |
3564 | + |
3565 | + def __init__(self, specto): |
3566 | + self.specto = specto |
3567 | + self.file_name = self.specto.SPECTO_DIR + "/specto.log" |
3568 | + |
3569 | + if not os.path.exists(self.file_name): |
3570 | + f = open(self.file_name, "a") |
3571 | + f.close() |
3572 | + os.chmod(self.file_name, 0600) |
3573 | + |
3574 | + self.error_file = self.specto.SPECTO_DIR + "/error.log" |
3575 | + if not os.path.exists(self.error_file): |
3576 | + f = open(self.error_file, "a") |
3577 | + f.close() |
3578 | + os.chmod(self.error_file, 0600) |
3579 | + |
3580 | + self.log_rotation() |
3581 | + |
3582 | + #write to log file |
3583 | + #TODO:XXX: Do we need to gettextize it? Maybe just the date. |
3584 | + logging.basicConfig(level=logging.INFO, |
3585 | + format='%(asctime)s &Separator; %(levelname)s &Separator;' \ |
3586 | + + ' %(name)s &Separator; %(message)s', |
3587 | + datefmt='%Y-%m-%d %H:%M:%S', |
3588 | + filename=self.file_name, |
3589 | + filemode='a') |
3590 | + |
3591 | + #write to console |
3592 | + console = logging.StreamHandler() |
3593 | + console.setLevel(logging.DEBUG) |
3594 | + |
3595 | + formatter = logging.Formatter('%(levelname)s - %(name)s - %(message)s') |
3596 | + #formatter = logging.Formatter('%(levelname)s - %(message)s') |
3597 | + console.setFormatter(formatter) |
3598 | + logging.getLogger('').addHandler(console) |
3599 | + |
3600 | + def log(self, message, level, logger): |
3601 | + """ Log a message. """ |
3602 | + log = logging.getLogger(str(logger)) |
3603 | + |
3604 | + if self.specto.DEBUG == True: |
3605 | + if level == "debug": |
3606 | + log.debug(message) |
3607 | + elif level == "info": |
3608 | + log.info(message) |
3609 | + elif level == "warning": |
3610 | + log.warn(message) |
3611 | + elif level == "error": |
3612 | + log.error(message) |
3613 | + self.log_error() |
3614 | + else: |
3615 | + log.critical(message) |
3616 | + self.log_error() |
3617 | + |
3618 | + def read_log(self): |
3619 | + """ Read the log file. """ |
3620 | + #get the info from the log file |
3621 | + log_file = open(self.file_name, "r") |
3622 | + self.logfile = log_file.read() |
3623 | + self.logfile.replace("&Separator;", " - ") |
3624 | + log_file.close() |
3625 | + |
3626 | + def watch_log(self, watch_name): |
3627 | + """ Filter the log for a watch name. """ |
3628 | + self.read_log() |
3629 | + buffer_log = self.logfile.split("\n") |
3630 | + filtered_log = [] |
3631 | + |
3632 | + for line in buffer_log: |
3633 | + if line != "" and line.split("&Separator;")[2].strip() == \ |
3634 | + watch_name: |
3635 | + info = line.split("&Separator;") |
3636 | + filtered_log.append([info[1].strip(), info[0] + " - " \ |
3637 | + + info[3] + "\n"]) |
3638 | + return filtered_log |
3639 | + |
3640 | + def remove_watch_log(self, watch_name): |
3641 | + """ Remove a watch from the log file. """ |
3642 | + self.read_log() |
3643 | + buffer_log = self.logfile.split("\n") |
3644 | + filtered_log = "" |
3645 | + |
3646 | + for i in buffer_log: |
3647 | + if not re.search(watch_name, i) and i != "": |
3648 | + filtered_log += i + "\n" |
3649 | + |
3650 | + f = open(self.file_name, "w") |
3651 | + f.write(filtered_log) |
3652 | + f.close() |
3653 | + |
3654 | + def clear_log(self, *args): |
3655 | + """ Clear the log file. """ |
3656 | + f = open(self.file_name, "w") |
3657 | + f.write("") |
3658 | + f.close() |
3659 | + os.chmod(self.file_name, 0600) |
3660 | + |
3661 | + def log_error(self): |
3662 | + error_message = "Error on: " + \ |
3663 | + datetime.today().strftime("%A %d %b %Y %H:%M") + "\n" |
3664 | + |
3665 | + et, ev, tb = sys.exc_info() |
3666 | + while tb: |
3667 | + co = tb.tb_frame.f_code |
3668 | + error_message += "Filename: " + str(co.co_filename) + "\n" |
3669 | + error_message += "Error Line # : " \ |
3670 | + + str(traceback.tb_lineno(tb)) + "\n" |
3671 | + tb = tb.tb_next |
3672 | + |
3673 | + error_message += "Type: " + str(et) + "\n" + "Error: " + \ |
3674 | + str(ev) + "\n\n" |
3675 | + |
3676 | + f = open(self.error_file, "a") |
3677 | + f.write(error_message) |
3678 | + f.close() |
3679 | + |
3680 | + def log_rotation(self): |
3681 | + if os.path.getsize(self.file_name) > 150000: |
3682 | + shutil.move(self.file_name, self.file_name + ".1") |
3683 | + f = open(self.file_name, "a") |
3684 | + f.close() |
3685 | + os.chmod(self.file_name, 0600) |
3686 | + |
3687 | + if os.path.getsize(self.error_file) > 150000: |
3688 | + shutil.move(self.error_file, self.error_file + ".1") |
3689 | + f = open(self.error_file, "a") |
3690 | + f.close() |
3691 | + os.chmod(self.error_file, 0600) |
3692 | |
3693 | === added file 'build/lib.linux-i686-2.6/spectlib/main.py' |
3694 | --- build/lib.linux-i686-2.6/spectlib/main.py 1970-01-01 00:00:00 +0000 |
3695 | +++ build/lib.linux-i686-2.6/spectlib/main.py 2012-03-14 09:03:18 +0000 |
3696 | @@ -0,0 +1,417 @@ |
3697 | +# -*- coding: utf-8 -*- |
3698 | + |
3699 | +# Specto , Unobtrusive event notifier |
3700 | +# |
3701 | +# main.py |
3702 | +# |
3703 | +# See the AUTHORS file for copyright ownership information |
3704 | + |
3705 | +# This program is free software; you can redistribute it and/or |
3706 | +# modify it under the terms of the GNU General Public |
3707 | +# License as published by the Free Software Foundation; either |
3708 | +# version 2 of the License, or (at your option) any later version. |
3709 | +# |
3710 | +# This program is distributed in the hope that it will be useful, |
3711 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
3712 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
3713 | +# General Public License for more details. |
3714 | +# |
3715 | +# You should have received a copy of the GNU General Public |
3716 | +# License along with this program; if not, write to the |
3717 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
3718 | +# Boston, MA 02111-1307, USA. |
3719 | + |
3720 | +# Definition of the watch_db |
3721 | +# watch_db[0] = instance of the first watch |
3722 | + |
3723 | +global GTK |
3724 | +global DEBUG #the DEBUG constant which controls how much info is output |
3725 | + |
3726 | +# Setup locale and gettext |
3727 | +import spectlib.i18n |
3728 | + |
3729 | +import os |
3730 | +import sys |
3731 | +import signal |
3732 | +import gobject |
3733 | +import gettext |
3734 | + |
3735 | +import spectlib.util as util |
3736 | +from spectlib.watch import Watch_collection |
3737 | +from spectlib.watch import Watch_io |
3738 | +from spectlib.console import Console |
3739 | +from spectlib.logger import Logger |
3740 | +from spectlib.tools.specto_gconf import Specto_gconf |
3741 | +from spectlib.tools import networkmanager as conmgr |
3742 | +from spectlib.bdd import Bdd |
3743 | + |
3744 | + |
3745 | +VERSION = "undefined" |
3746 | +try: |
3747 | + from spectlib.constants import VERSION |
3748 | +except ImportError: |
3749 | + with open("VERSION", 'r') as version_file: |
3750 | + VERSION = version_file.read().strip() |
3751 | + |
3752 | +#create a gconf object |
3753 | +specto_gconf = Specto_gconf("/apps/specto") |
3754 | + |
3755 | +DEBUG = specto_gconf.get_entry("debug_mode") |
3756 | + |
3757 | +try: |
3758 | + import pygtk |
3759 | + pygtk.require("2.0") |
3760 | + import gtk |
3761 | +except: |
3762 | + print _("no GTK, activating console mode") |
3763 | + GTK = False |
3764 | +else: |
3765 | + GTK = True |
3766 | + from spectlib.notifier import Notifier, INDICATOR |
3767 | + |
3768 | +keyring = True |
3769 | +try: |
3770 | + from spectlib.tools.keyringmanager import Keyring |
3771 | +except: |
3772 | + keyring = False |
3773 | + |
3774 | + |
3775 | +class Specto: |
3776 | + """ The main Specto class. """ |
3777 | + |
3778 | + def __init__(self): |
3779 | + self.DEBUG = DEBUG |
3780 | + self.util = util |
3781 | + |
3782 | + self.PATH = self.util.get_path() |
3783 | + self.SRC_PATH = self.util.get_path("src") |
3784 | + self.SPECTO_DIR = self.util.get_path("specto") |
3785 | + self.CACHE_DIR = self.util.get_path("tmp") |
3786 | + self.FILE = self.util.get_file() |
3787 | + |
3788 | + self.logger = Logger(self) |
3789 | + |
3790 | + self.VERSION = VERSION # The Specto version number |
3791 | + |
3792 | + self.GTK = GTK |
3793 | + |
3794 | + if not self.check_instance(): #see if specto is already running |
3795 | + self.specto_gconf = specto_gconf |
3796 | + self.check_default_settings() |
3797 | + |
3798 | + self.connection_manager = conmgr.get_net_listener() |
3799 | + self.use_keyring = self.specto_gconf.get_entry("use_keyring") |
3800 | + |
3801 | + if self.specto_gconf.get_entry("button_mysql"): |
3802 | + print "Mysql" |
3803 | + if self.use_keyring == True and keyring == True: |
3804 | + try: |
3805 | + k = Keyring("entry_passwd", "Specto " + "entry_passwd", "network") |
3806 | + password = k.get_credentials()[1] |
3807 | + except: |
3808 | + password = specto_gconf.get_entry("entry_passwd") |
3809 | + |
3810 | + datas = {"type":"mysql", |
3811 | + "user":self.specto_gconf.get_entry("entry_username"), |
3812 | + "pass":password, |
3813 | + "host":self.specto_gconf.get_entry("entry_server"), |
3814 | + "port":self.specto_gconf.get_entry("entry_port"), |
3815 | + "name":self.specto_gconf.get_entry("entry_database")} |
3816 | + else: |
3817 | + print "sql lite" |
3818 | + datas = {"type":"sqlite", |
3819 | + "directory":"ici.db"} |
3820 | + self.base = Bdd(**datas) |
3821 | + |
3822 | + #create the watch collection and add the watches |
3823 | + self.watch_db = Watch_collection(self) |
3824 | + self.watch_io = Watch_io(self, self.FILE) |
3825 | + |
3826 | + if (sys.argv[1:] and "--console" in sys.argv[1:][0]) or not self.GTK: |
3827 | + self.logger.log(_("Console mode enabled."), "debug", "specto") |
3828 | + self.GTK = False |
3829 | + self.CONSOLE = True |
3830 | + try: |
3831 | + args = sys.argv[1:][1] |
3832 | + except: |
3833 | + args = "" |
3834 | + self.console = Console(self, args) |
3835 | + |
3836 | + elif self.GTK: |
3837 | + self.GTK = True |
3838 | + self.CONSOLE = False |
3839 | + self.icon_theme = gtk.icon_theme_get_default() |
3840 | + |
3841 | + #allow users to hide the window on startup |
3842 | + if sys.argv[1:] and "--no-window" in sys.argv[1:][0]: |
3843 | + self.notifier_hide = True |
3844 | + #always show if there's no icon and no indicator support |
3845 | + elif self.specto_gconf.get_entry("always_show_icon") == False and not INDICATOR: |
3846 | + self.notifier_hide = False |
3847 | + elif self.specto_gconf.get_entry("show_notifier")==True: |
3848 | + self.notifier_hide = False |
3849 | + elif self.specto_gconf.get_entry("show_notifier")==False: |
3850 | + self.notifier_hide = True |
3851 | + else:#just in case the entry was never created in gconf |
3852 | + self.notifier_keep_hidden = False |
3853 | + |
3854 | + self.notifier = Notifier(self) |
3855 | + else: |
3856 | + sys.exit(0) |
3857 | + |
3858 | + #listen for gconf keys |
3859 | + self.specto_gconf.notify_entry("debug_mode", self.key_changed, "debug") |
3860 | + |
3861 | + values = self.watch_io.read_all_watches(True) |
3862 | + try: |
3863 | + self.watch_db.create(values) |
3864 | + except AttributeError, error_fields: |
3865 | + self.logger.log(_("Could not create a watch, because it is corrupt."), \ |
3866 | + "critical", "specto") |
3867 | + |
3868 | + |
3869 | + if self.GTK: |
3870 | + for watch in self.watch_db: |
3871 | + self.notifier.add_notifier_entry(watch.id) |
3872 | + |
3873 | + # Listen for USR1. If received, answer and show the window |
3874 | + def listen_for_USR1(signum, frame): |
3875 | + f = open(self.SPECTO_DIR + "/" + "specto.pid.boot") |
3876 | + pid = int(f.readline()) |
3877 | + f.close() |
3878 | + os.kill(pid, signal.SIGUSR1) |
3879 | + # If window was not shown, make it appear |
3880 | + if not self.notifier.get_state(): |
3881 | + self.logger.log("Showing window, the user ran another instance of specto", "debug", "specto") |
3882 | + self.toggle_notifier() |
3883 | + else: |
3884 | + # Based on http://www.pygtk.org/docs/pygtk/class-gtkwindow.html#method-gtkwindow--present |
3885 | + self.logger.log("Window is already visible! Raising it to the front.", "debug", "specto") |
3886 | + self.notifier.notifier.present() |
3887 | + |
3888 | + signal.signal(signal.SIGUSR1, listen_for_USR1) |
3889 | + |
3890 | + self.notifier.refresh_all_watches() |
3891 | + else: |
3892 | + self.console.start_watches() |
3893 | + |
3894 | + if self.GTK: |
3895 | + gtk.main() |
3896 | + else: |
3897 | + try: |
3898 | + self.go = gobject.MainLoop() |
3899 | + self.go.run() |
3900 | + except (KeyboardInterrupt, SystemExit): |
3901 | + sys.exit(0) |
3902 | + |
3903 | + def key_changed(self, *args): |
3904 | + """ Listen for gconf keys. """ |
3905 | + label = args[3] |
3906 | + |
3907 | + if label == "debug": |
3908 | + self.DEBUG = self.specto_gconf.get_entry("debug_mode") |
3909 | + |
3910 | + def check_default_settings(self): |
3911 | + """ This is used to set the default settings |
3912 | + properly the first time Specto is run, |
3913 | + without using gconf schemas """ |
3914 | + #check if the ekiga sounds exists |
3915 | + if os.path.exists("/usr/share/sounds/ekiga/voicemail.wav"): |
3916 | + changed_sound = "/usr/share/sounds/ekiga/voicemail.wav" |
3917 | + else: |
3918 | + changed_sound = "" |
3919 | + |
3920 | + self.default_settings = ( |
3921 | + ["always_show_icon", False], #True would be against the HIG! |
3922 | + ["debug_mode", False], |
3923 | + ["follow_website_redirects", True], |
3924 | + ["pop_toast", True], |
3925 | + ["show_deactivated_watches", True], |
3926 | + ["show_in_windowlist", True], |
3927 | + ["show_notifier", True], |
3928 | + ["show_toolbar", True], |
3929 | + ["sort_function", "name"], |
3930 | + ["sort_order", "asc"], |
3931 | + ["changed_sound", changed_sound], |
3932 | + ["use_changed_sound", False], |
3933 | + ["window_notifier_height", 500], |
3934 | + ["window_notifier_width", 500], |
3935 | + ["use_keyring", True]) |
3936 | + for default_setting in self.default_settings: |
3937 | + if self.specto_gconf.get_entry(default_setting[0]) == None: |
3938 | + self.specto_gconf.set_entry(default_setting[0], \ |
3939 | + default_setting[1]) |
3940 | + |
3941 | + def check_instance(self): |
3942 | + """ Check if specto is already running. """ |
3943 | + pidfile = self.SPECTO_DIR + "/" + "specto.pid" |
3944 | + if not os.path.exists(pidfile): |
3945 | + f = open(pidfile, "w") |
3946 | + f.close() |
3947 | + os.chmod(pidfile, 0600) |
3948 | + |
3949 | + #see if specto is already running |
3950 | + with open(pidfile, "r") as f: |
3951 | + pid = f.readline() |
3952 | + if pid: |
3953 | + p = os.system("ps --no-heading --pid " + pid) |
3954 | + p_name = os.popen("ps -f --pid " + pid).read() |
3955 | + if p == 0 and "specto" in p_name: |
3956 | + if self.GTK: |
3957 | + # Save our pid and prepare a 'pong' system |
3958 | + f = open(pidfile + ".boot", "w") |
3959 | + f.write(str(os.getpid())) |
3960 | + f.close() |
3961 | + |
3962 | + def not_responding(signum, frame): |
3963 | + """ Launch the already running dialog if the |
3964 | + other instance doesn't respond """ |
3965 | + os.unlink(pidfile + ".boot") |
3966 | + self.already_running_dialog() |
3967 | + |
3968 | + def response_received(signum, frame): |
3969 | + """ Kill this specto if the other one answers """ |
3970 | + signal.alarm(0) |
3971 | + os.unlink(pidfile + ".boot") |
3972 | + self.logger.log("Specto is already running! The old instance will be brought to front.", "debug", "specto") |
3973 | + sys.exit(0) |
3974 | + |
3975 | + signal.signal(signal.SIGALRM, not_responding) |
3976 | + signal.signal(signal.SIGUSR1, response_received) |
3977 | + signal.alarm(5) |
3978 | + |
3979 | + # Send signal to raise window |
3980 | + os.kill(int(pid), signal.SIGUSR1) |
3981 | + |
3982 | + # Wait for signals |
3983 | + signal.pause() |
3984 | + |
3985 | + return True |
3986 | + elif DEBUG: |
3987 | + self.logger.log(_("Specto is already running!"), "critical", "specto") |
3988 | + sys.exit(0) |
3989 | + else: |
3990 | + print _("Specto is already running!") |
3991 | + sys.exit(0) |
3992 | + |
3993 | + #write the pid file |
3994 | + with open(pidfile, "w") as f: |
3995 | + f.write(str(os.getpid())) |
3996 | + |
3997 | + def mark_watch_status(self, status, id): |
3998 | + """ get the watch status (checking, changed, idle) """ |
3999 | + if self.GTK: |
4000 | + self.notifier.mark_watch_status(status, id) |
4001 | + elif self.CONSOLE: |
4002 | + self.console.mark_watch_status(status, id) |
4003 | + |
4004 | + def toggle_notifier(self, *args): |
4005 | + """ |
4006 | + Toggle the state of the notifier, hidden or shown. |
4007 | + It will save the size, position, |
4008 | + and the last state when you closed Specto. |
4009 | + """ |
4010 | + #Creating the notifier window, but keeping it hidden |
4011 | + if self.notifier.get_state() == True and not self.notifier_hide: |
4012 | + self.specto_gconf.set_entry("show_notifier", True) |
4013 | + self.notifier.restore_size_and_position() |
4014 | + self.notifier.notifier.show() |
4015 | + self.notifier_hide = True |
4016 | + elif self.notifier.get_state()==True and self.notifier_hide: |
4017 | + self.notifier.save_size_and_position() |
4018 | + self.specto_gconf.set_entry("show_notifier", False) |
4019 | + self.notifier.notifier.hide() |
4020 | + self.notifier_hide = False |
4021 | + else: |
4022 | + self.specto_gconf.set_entry("show_notifier", True) |
4023 | + self.notifier.restore_size_and_position() |
4024 | + self.notifier.notifier.show() |
4025 | + self.notifier_hide = True |
4026 | + |
4027 | + def quit(self, *args): |
4028 | + """ Save the save and position from the notifier and quit Specto. """ |
4029 | + if self.notifier.get_state() == True and self.notifier_hide: |
4030 | + self.notifier.save_size_and_position() |
4031 | + try: |
4032 | + gtk.main_quit() |
4033 | + except: |
4034 | + #create a close dialog |
4035 | + self.dialog = gtk.Dialog(_("Cannot quit yet"), None, gtk.DIALOG_NO_SEPARATOR | gtk.DIALOG_DESTROY_WITH_PARENT, None) |
4036 | + self.dialog.set_modal(False) # Needed to prevent the notifier UI and refresh process from blocking. Also, do not use dialog.run(), because it automatically sets modal to true. |
4037 | + |
4038 | + #HIG tricks |
4039 | + self.dialog.set_has_separator(False) |
4040 | + |
4041 | + self.dialog.add_button(_("Murder!"), 3) |
4042 | + self.dialog.add_button(gtk.STOCK_CANCEL, -1) |
4043 | + |
4044 | + self.dialog.label_hbox = gtk.HBox(spacing=6) |
4045 | + |
4046 | + icon = gtk.Image() |
4047 | + icon.set_from_pixbuf(self.icon_theme.\ |
4048 | + load_icon("dialog-warning", 64, 0)) |
4049 | + self.dialog.label_hbox.pack_start(icon, True, True, 6) |
4050 | + icon.show() |
4051 | + |
4052 | + label = gtk.Label(_('<b><big>Specto is currently busy and cannot quit yet.</big></b>\n\nThis may be because it is checking for watch changes.\nHowever, you can try forcing it to quit by clicking the murder button.')) |
4053 | + label.set_use_markup(True) |
4054 | + self.dialog.label_hbox.pack_start(label, True, True, 6) |
4055 | + label.show() |
4056 | + |
4057 | + self.dialog.vbox.pack_start(self.dialog.label_hbox, True, True, 12) |
4058 | + self.dialog.label_hbox.show() |
4059 | + |
4060 | + icon = gtk.gdk.pixbuf_new_from_file(self.PATH + \ |
4061 | + 'icons/specto_window_icon.svg') |
4062 | + self.dialog.set_icon(icon) |
4063 | + self.dialog.connect("delete_event", self.quit_dialog_response) |
4064 | + self.dialog.connect("response", self.quit_dialog_response) |
4065 | + self.dialog.show_all() |
4066 | + |
4067 | + def quit_dialog_response(self, widget, answer): |
4068 | + if answer == 3: |
4069 | + try:#go figure, it never works! |
4070 | + self.notifier.stop_refresh = True |
4071 | + sys.exit(0) |
4072 | + except: |
4073 | + #kill the specto process with killall |
4074 | + os.system('killall specto') |
4075 | + else: |
4076 | + self.dialog.hide() |
4077 | + |
4078 | + def already_running_dialog(self, *args): |
4079 | + """ Save the save and position from the notifier and quit Specto. """ |
4080 | + #create a dialog |
4081 | + self.dialog = gtk.Dialog(_("Error"), None, gtk.DIALOG_NO_SEPARATOR | gtk.DIALOG_DESTROY_WITH_PARENT, None) |
4082 | + self.dialog.set_modal(False) # Needed to prevent the notifier UI and refresh process from blocking. Also, do not use dialog.run(), because it automatically sets modal to true. |
4083 | + |
4084 | + #HIG tricks |
4085 | + self.dialog.set_has_separator(False) |
4086 | + |
4087 | + #self.dialog.add_button(_("Murder!"), 3) |
4088 | + self.dialog.add_button(gtk.STOCK_OK, 3) |
4089 | + |
4090 | + self.dialog.label_hbox = gtk.HBox(spacing=6) |
4091 | + |
4092 | + icon = gtk.Image() |
4093 | + icon.set_from_stock(gtk.STOCK_DIALOG_INFO, gtk.ICON_SIZE_DIALOG) |
4094 | + self.dialog.label_hbox.pack_start(icon, True, True, 6) |
4095 | + icon.show() |
4096 | + |
4097 | + label = gtk.Label(_('Specto is already running!')) |
4098 | + label.set_use_markup(True) |
4099 | + self.dialog.label_hbox.pack_start(label, True, True, 6) |
4100 | + label.show() |
4101 | + |
4102 | + self.dialog.vbox.pack_start(self.dialog.label_hbox, True, True, 12) |
4103 | + self.dialog.label_hbox.show() |
4104 | + |
4105 | + icon = gtk.gdk.pixbuf_new_from_file(self.PATH + 'icons/specto_window_icon.svg') |
4106 | + self.dialog.set_icon(icon) |
4107 | + self.dialog.connect("delete_event", self.running_dialog_response) |
4108 | + self.dialog.connect("response", self.running_dialog_response) |
4109 | + self.dialog.show_all() |
4110 | + |
4111 | + def running_dialog_response(self, widget, answer): |
4112 | + if answer == 3: |
4113 | + sys.exit(0) |
4114 | |
4115 | === added file 'build/lib.linux-i686-2.6/spectlib/notifier.py' |
4116 | --- build/lib.linux-i686-2.6/spectlib/notifier.py 1970-01-01 00:00:00 +0000 |
4117 | +++ build/lib.linux-i686-2.6/spectlib/notifier.py 2012-03-14 09:03:18 +0000 |
4118 | @@ -0,0 +1,1080 @@ |
4119 | +# -*- coding: utf-8 -*- |
4120 | + |
4121 | +# Specto , Unobtrusive event notifier |
4122 | +# |
4123 | +# notifier.py |
4124 | +# |
4125 | +# See the AUTHORS file for copyright ownership information |
4126 | + |
4127 | +# This program is free software; you can redistribute it and/or |
4128 | +# modify it under the terms of the GNU General Public |
4129 | +# License as published by the Free Software Foundation; either |
4130 | +# version 2 of the License, or (at your option) any later version. |
4131 | +# |
4132 | +# This program is distributed in the hope that it will be useful, |
4133 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
4134 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4135 | +# General Public License for more details. |
4136 | +# |
4137 | +# You should have received a copy of the GNU General Public |
4138 | +# License along with this program; if not, write to the |
4139 | +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
4140 | +# Boston, MA 02111-1307, USA. |
4141 | + |
4142 | +import os |
4143 | +from random import randrange |
4144 | +from datetime import datetime |
4145 | + |
4146 | +from spectlib.contact import Contact |
4147 | +from spectlib.preferences import Preferences |
4148 | +from spectlib.add_watch import Add_watch |
4149 | +from spectlib.about import About |
4150 | +from spectlib.edit_watch import Edit_watch |
4151 | +from spectlib.logger import Log_dialog |
4152 | +from spectlib.balloons import NotificationToast |
4153 | +from spectlib.import_watch import Import_watch |
4154 | +from spectlib.export_watch import Export_watch |
4155 | +from spectlib.trayicon import Tray |
4156 | +from spectlib.crawl import Crawler |
4157 | + |
4158 | +INDICATOR = True |
4159 | +try: |
4160 | + from spectlib.tools.indicator import Indicator |
4161 | +except: |
4162 | + INDICATOR = False |
4163 | + |
4164 | +SOUND = True |
4165 | +try: |
4166 | + from spectlib.tools.sound import Sound |
4167 | +except: |
4168 | + SOUND = False |
4169 | + |
4170 | + |
4171 | +from spectlib.util import show_webpage |
4172 | +from spectlib.gtkconfig import ErrorDialog, RemoveDialog, create_menu_item |
4173 | + |
4174 | +try: |
4175 | + import pygtk |
4176 | + pygtk.require("2.0") |
4177 | +except: |
4178 | + pass |
4179 | + |
4180 | +try: |
4181 | + import gtk |
4182 | + import gobject |
4183 | + import pango |
4184 | +except: |
4185 | + pass |
4186 | + |
4187 | + |
4188 | +class Notifier: |
4189 | + """ |
4190 | + Class to create the main specto window |
4191 | + """ |
4192 | + add_w = "" |
4193 | + edit_w = "" |
4194 | + error_l = "" |
4195 | + about = "" |
4196 | + export_watch = "" |
4197 | + import_watch = "" |
4198 | + |
4199 | + def __init__(self, specto): |
4200 | + """ |
4201 | + In this init we are going to display the main notifier window. |
4202 | + """ |
4203 | + self.specto = specto |
4204 | + uifile = os.path.join(self.specto.PATH, "uis/notifier.ui") |
4205 | + windowname = "notifier" |
4206 | + self.builder = gtk.Builder() |
4207 | + self.builder.set_translation_domain("specto") |
4208 | + self.builder.add_from_file(uifile) |
4209 | + self.notifier = self.builder.get_object("notifier") |
4210 | + if INDICATOR: |
4211 | + self.indicator = Indicator(specto) |
4212 | + self.tray = None |
4213 | + else: |
4214 | + self.tray = Tray(specto, self) |
4215 | + self.indicator = None |
4216 | + if SOUND: |
4217 | + self.sound = Sound() |
4218 | + else: |
4219 | + self.sound = None |
4220 | + self.balloon = NotificationToast(specto, self) |
4221 | + self.preferences_initialized = False |
4222 | + self.contact_initialized = False |
4223 | + |
4224 | + #create tree |
4225 | + self.iter = {} |
4226 | + self.model = gtk.ListStore(gobject.TYPE_BOOLEAN, gtk.gdk.Pixbuf, gobject.TYPE_STRING, gobject.TYPE_INT, gobject.TYPE_STRING, pango.Weight) |
4227 | + |
4228 | + #catch some events |
4229 | + dic = { |
4230 | + "on_add_activate": self.show_add_watch_menu, |
4231 | + "on_edit_activate": self.show_edit_watch, |
4232 | + "on_clear_all_activate": self.mark_all_as_read, |
4233 | + "on_preferences_activate": self.show_preferences, |
4234 | + "on_contact_activate":self.show_contact, |
4235 | + "on_refresh_activate": self.refresh_all_watches, |
4236 | + "on_close_activate": self.close_event, |
4237 | + "on_quit_activate": self.delete_event, |
4238 | + "on_import_watches_activate": self.import_watches, |
4239 | + "on_export_watches_activate": self.export_watches, |
4240 | + "on_error_log_activate": self.show_error_log, |
4241 | + "on_display_all_watches_activate": self.toggle_show_deactivated_watches, |
4242 | + "on_display_toolbar_activate": self.toggle_display_toolbar, |
4243 | + "on_help_activate": self.show_help, |
4244 | + "on_about_activate": self.show_about, |
4245 | + "on_treeview_row_activated": self.open_watch_callback, |
4246 | + "on_btnOpen_clicked": self.open_watch_callback, |
4247 | + "on_btnClear_clicked": self.mark_watch_as_read, |
4248 | + "on_treeview_cursor_changed": self.show_watch_info, |
4249 | + "on_btnEdit_clicked": self.show_edit_watch, |
4250 | + "on_by_watch_type_activate": self.sort_type, |
4251 | + "on_by_name_activate": self.sort_name, |
4252 | + "on_by_watch_active_activate": self.sort_active, |
4253 | + "on_remove_clicked": self.remove_watch, |
4254 | + "on_clear_activate": self._mark_watch_as_read, |
4255 | + "on_remove_activate": self.remove_watch} |
4256 | + self.builder.connect_signals(dic) |
4257 | + |
4258 | + icon = gtk.gdk.pixbuf_new_from_file(os.path.join(self.specto.PATH, "icons/specto_window_icon.svg")) |
4259 | + self.notifier.set_icon(icon) |
4260 | + self.specto.notifier_initialized = True |
4261 | + self.create_notifier_gui() |
4262 | + self.stop_refresh = False |
4263 | + |
4264 | + def mark_watch_as_read(self, widget, *id): |
4265 | + """ |
4266 | + Call the main function to mark the watch as read and reset the name in the notifier. |
4267 | + If widget == '' then id will be used to mark the watch as read else the selected watch will be marked as read. |
4268 | + """ |
4269 | + try: |
4270 | + id = id[0] |
4271 | + except: |
4272 | + model, iter = self.treeview.get_selection().get_selected() |
4273 | + id = int(model.get_value(iter, 3)) |
4274 | + watch = self.specto.watch_db[id] |
4275 | + watch.mark_as_read() |
4276 | + self.model.set(self.iter[id], 2, watch.name, 5, pango.WEIGHT_NORMAL) |
4277 | + if self.model.iter_is_valid(self.iter[id]) and not watch.error: |
4278 | + self.model.set_value(self.iter[id], 1, self.get_icon(watch.icon, 50, False)) |
4279 | + if watch.changed == False: |
4280 | + self.builder.get_object("btnClear").set_sensitive(False) |
4281 | + else: |
4282 | + self.builder.get_object("btnClear").set_sensitive(True) |
4283 | + #check if all watches has been marked as read |
4284 | + changed_watches = False |
4285 | + changes = self.specto.watch_db.count_changed_watches() |
4286 | + for changed in changes.values(): |
4287 | + if changed > 0: |
4288 | + changed_watches = True |
4289 | + if changed_watches == False: |
4290 | + self.builder.get_object("button_clear_all").set_sensitive(False) |
4291 | + |
4292 | + def mark_all_as_read(self, widget): |
4293 | + """ Call the main function to mark all watches as read and reset the name in the notifier. """ |
4294 | + self.builder.get_object("btnClear").set_sensitive(False) |
4295 | + self.builder.get_object("button_clear_all").set_sensitive(False) |
4296 | + self.builder.get_object("clear_all1").set_sensitive(False) |
4297 | + for watch in self.specto.watch_db: |
4298 | + if self.model.iter_is_valid(self.iter[watch.id]): |
4299 | + self.mark_watch_as_read("", watch.id) |
4300 | + |
4301 | + def refresh_all_watches(self, *widget): |
4302 | + """ Call the main funcion to refresh all active watches and change refresh icon to stop. """ |
4303 | + if self.builder.get_object("button_refresh").get_stock_id() == "gtk-refresh": |
4304 | + self.builder.get_object("button_refresh").set_stock_id("gtk-stop") #menu item, does not allow changing label |
4305 | + self.builder.get_object("button_refresh").set_label(_("Stop")) |
4306 | + self.builder.get_object("button_add").set_sensitive(False) |
4307 | + self.builder.get_object("btnEdit").set_sensitive(False) |
4308 | + for i in self.iter: |
4309 | + if self.stop_refresh == True: |
4310 | + self.stop_refresh = False |
4311 | + break |
4312 | + try: |
4313 | + iter = self.model.get_iter(i) |
4314 | + if self.model.iter_is_valid(iter): |
4315 | + model = self.model |
4316 | + id = int(model.get_value(iter, 3)) |
4317 | + except: |
4318 | + break |
4319 | + if self.specto.watch_db[id].active == True: |
4320 | + try: |
4321 | + self.specto.watch_db[id].stop() |
4322 | + except: |
4323 | + pass |
4324 | + self.specto.watch_db[id].start() |
4325 | + self.builder.get_object("button_refresh").set_stock_id("gtk-refresh") #menu item, does not allow changing label |
4326 | + self.builder.get_object("button_refresh").set_label(_("Refresh All")) |
4327 | + self.builder.get_object("button_add").set_sensitive(True) |
4328 | + self.builder.get_object("btnEdit").set_sensitive(True) |
4329 | + else: |
4330 | + self.stop_refresh = True |
4331 | + |
4332 | + def mark_error(self, error_message): |
4333 | + error_dialog = ErrorDialog(self.specto, error_message) |
4334 | + |
4335 | + def mark_watch_status(self, status, id): |
4336 | + """ show the right icon for the status from the watch. """ |
4337 | + watch = self.specto.watch_db[id] |
4338 | + statusbar = self.builder.get_object("statusbar1") |
4339 | + icon = self.get_icon("error", 50, False) |
4340 | + |
4341 | + try: |
4342 | + if status == "checking": |
4343 | + icon = self.get_icon("reload", 0, False) |
4344 | + statusbar.push(0, (datetime.today().strftime("%H:%M") + " - " + _('The watch "%s" is checking.') % watch.name)) |
4345 | + |
4346 | + elif status == "idle": |
4347 | + if self.tray: |
4348 | + self.tray.show_tooltip() #check if all watches are cleared |
4349 | + if watch.changed == True: |
4350 | + self.model.set(self.iter[id], 2, "%s" % watch.name, 5, pango.WEIGHT_BOLD) |
4351 | + self.builder.get_object("button_clear_all").set_sensitive(True) |
4352 | + self.builder.get_object("clear_all1").set_sensitive(True) |
4353 | + icon = self.get_icon(watch.icon, 0, False) |
4354 | + else: |
4355 | + self.model.set(self.iter[id], 2, "%s" % watch.name, 5, pango.WEIGHT_NORMAL) |
4356 | + self.builder.get_object("clear_all1").set_sensitive(False) |
4357 | + icon = self.get_icon(watch.icon, 50, False) |
4358 | + statusbar.push(0, "") # As per HIG, make the status bar empty when nothing is happening |
4359 | + |
4360 | + elif status == "no-network": |
4361 | + statusbar.push(0, (datetime.today().strftime("%H:%M") + " - " + _('The network connection seems to be down, networked watches will not check until then.'))) |
4362 | + if self.tray: |
4363 | + self.tray.show_tooltip() |
4364 | + icon = self.get_icon(watch.icon, 50, False) |
4365 | + |
4366 | + elif status == "error": |
4367 | + statusbar.push(0, (datetime.today().strftime("%H:%M") + " - " + _('The watch "%s" has a problem.') % watch.name)) |
4368 | + balloon_icon = self.get_icon("error", 0, True) |
4369 | + icon = self.get_icon("error", 50, False) |
4370 | + if self.specto.specto_gconf.get_entry("pop_toast") == True: |
4371 | + body = watch.escape(watch.error_message) |
4372 | + self.balloon.show_toast(body, balloon_icon, urgency="critical", summary=(_("%s encountered a problem") % watch.name)) |
4373 | + if self.specto.specto_gconf.get_entry("use_problem_sound") and self.sound: |
4374 | + problem_sound = self.specto.specto_gconf.get_entry("problem_sound") |
4375 | + self.sound.play(problem_sound) |
4376 | + |
4377 | + elif status == "changed": |
4378 | + if self.indicator: |
4379 | + self.indicator.add_indicator(watch) |
4380 | + statusbar.push(0, (datetime.today().strftime("%H:%M") + " - " + _('The watch "%s" has changed.') % watch.name)) |
4381 | + |
4382 | + self.model.set(self.iter[id], 2, "%s" % watch.name, 5, pango.WEIGHT_BOLD) |
4383 | + |
4384 | + self.builder.get_object("button_clear_all").set_sensitive(True) |
4385 | + self.builder.get_object("clear_all1").set_sensitive(True) |
4386 | + |
4387 | + if self.model.iter_is_valid(self.iter[id]): |
4388 | + icon = self.get_icon(watch.icon, 0, False) |
4389 | + |
4390 | + if self.tray: |
4391 | + self.tray.show_tooltip() |
4392 | + |
4393 | + balloon_icon = self.get_icon(watch.icon, 0, True) |
4394 | + if self.specto.specto_gconf.get_entry("pop_toast") == True: |
4395 | + self.balloon.show_toast(watch.get_balloon_text(), balloon_icon, summary=(_("%s has changed") % watch.name), name=watch.name) |
4396 | + |
4397 | + icon = self.get_icon(watch.icon, 0, False) |
4398 | + if self.specto.specto_gconf.get_entry("use_changed_sound") and self.sound: |
4399 | + changed_sound = self.specto.specto_gconf.get_entry("changed_sound") |
4400 | + self.sound.play(changed_sound) |
4401 | + |
4402 | + elif status == "read": |
4403 | + if self.indicator: |
4404 | + self.indicator.remove_indicator(id) |
4405 | + |
4406 | + self.model.set_value(self.iter[id], 1, icon) |
4407 | + |
4408 | + try: |
4409 | + model, iter = self.treeview.get_selection().get_selected() |
4410 | + id2 = int(model.get_value(iter, 3)) |
4411 | + if id == id2: |
4412 | + self.show_watch_info() |
4413 | + except: |
4414 | + pass |
4415 | + except: |
4416 | + self.specto.logger.log(_("There was an error marking the watch status"), "error", watch.name) |
4417 | + |
4418 | + def deactivate(self, id): |
4419 | + """ Disable the checkbox from the watch. """ |
4420 | + watch = self.specto.watch_db[id] |
4421 | + self.model.set_value(self.iter[id], 0, 0)#TODO: make the text label in the "Name" column and the buttons insensitive |
4422 | + |
4423 | + def activate(self, id): |
4424 | + """ enable the checkbox from the watch. """ |
4425 | + watch = self.specto.watch_db[id] |
4426 | + self.model.set_value(self.iter[id], 0, 1)#TODO: make the text label in the "Name" column and the buttons insensitive |
4427 | + |
4428 | + def get_icon(self, icon, percent, size): |
4429 | + """ Calculate the alpha and return a transparent pixbuf. The input percentage is the 'transparency' percentage. 0 means no transparency. """ |
4430 | + if icon == "": |
4431 | + icon = "dialog-information" |
4432 | + |
4433 | + if size == True: |
4434 | + size = 64 |
4435 | + else: |
4436 | + size = 22 |
4437 | + |
4438 | + try: |
4439 | + icon = self.specto.icon_theme.load_icon(icon, size, 0) |
4440 | + except gobject.GError: |
4441 | + try: |
4442 | + icon = gtk.gdk.pixbuf_new_from_file_at_size(os.path.join(self.specto.PATH, ("icons/" + icon + ".svg")), size, size) |
4443 | + except: |
4444 | + try: |
4445 | + icon = gtk.gdk.pixbuf_new_from_file_at_size(os.path.join(self.specto.PATH, ("icons/" + icon + ".png")), size, size) |
4446 | + except: |
4447 | + return None |
4448 | + |
4449 | + icon = icon.add_alpha(False, '0', '0', '0') |
4450 | + for row in icon.get_pixels_array(): |
4451 | + for pix in row: |
4452 | + pix[3] = min(int(pix[3]), 255 - (percent * 0.01 * 255))#note: we must *0.01, NOT /100, otherwise it won't work |
4453 | + return icon |
4454 | + |
4455 | + def add_notifier_entry(self, id): |
4456 | + """ Add an entry to the notifier list. """ |
4457 | + watch = self.specto.watch_db[id] |
4458 | + if watch.active == True: |
4459 | + active = 1 |
4460 | + else: |
4461 | + active = 0 |
4462 | + |
4463 | + self.iter[id] = self.model.insert_before(None, None) |
4464 | + self.model.set_value(self.iter[id], 0, active) |
4465 | + if watch.changed == True: |
4466 | + self.model.set_value(self.iter[id], 1, self.get_icon(watch.icon, 0, False)) |
4467 | + self.model.set(self.iter[id], 5, pango.WEIGHT_BOLD) |
4468 | + else: |
4469 | + self.model.set_value(self.iter[id], 1, self.get_icon(watch.icon, 50, False)) |
4470 | + self.model.set(self.iter[id], 5, pango.WEIGHT_NORMAL) |
4471 | + self.model.set_value(self.iter[id], 2, watch.name) |
4472 | + self.model.set_value(self.iter[id], 3, watch.id) |
4473 | + self.model.set_value(self.iter[id], 4, watch.type) |
4474 | + |
4475 | + if not self.builder.get_object("display_all_watches").active and active == 0: #dont creat the entry |
4476 | + self.remove_notifier_entry(id) |
4477 | + |
4478 | + def remove_notifier_entry(self, id): |
4479 | + path = self.model.get_path(self.iter[id]) |
4480 | + iter = self.model.get_iter(path) |
4481 | + id = int(self.model.get_value(iter, 3)) |
4482 | + self.model.remove(iter) |
4483 | + |
4484 | + def check_clicked(self, object, path, model): |
4485 | + """ Call the main function to start/stop the selected watch. """ |
4486 | + sel = self.treeview.get_selection() |
4487 | + sel.select_path(path) |
4488 | + |
4489 | + model, iter = self.treeview.get_selection().get_selected() |
4490 | + id = int(model.get_value(iter, 3)) |
4491 | + watch = self.specto.watch_db[id] |
4492 | + |
4493 | + if model.get_value(iter, 0): |
4494 | + model.set_value(iter, 0, 0) |
4495 | + if watch.changed: |
4496 | + self.mark_watch_as_read("", id) |
4497 | + self.mark_watch_status("idle", id) |
4498 | + self.mark_watch_status("idle", id) |
4499 | + watch.stop() |
4500 | + if not self.builder.get_object("display_all_watches").active: |
4501 | + self.remove_notifier_entry(id) |
4502 | + else: |
4503 | + model.set_value(iter, 0, 1) |
4504 | + watch.start() |
4505 | + |
4506 | + def connected_message(self, connected): |
4507 | + return |
4508 | + if not connected: |
4509 | + self.builder.get_object("statusbar1").push(0, _("The network connection seems to be down, networked watches will not check until then.")) |
4510 | + self.builder.get_object("statusbar1").show() |
4511 | + else: |
4512 | + self.builder.get_object("statusbar1").hide() |
4513 | + |
4514 | + def show_watch_info(self, *args): |
4515 | + """ Show the watch information in the notifier window. """ |
4516 | + model, iter = self.treeview.get_selection().get_selected() |
4517 | + |
4518 | + if iter != None and self.model.iter_is_valid(iter): |
4519 | + self.builder.get_object("edit").set_sensitive(True) |
4520 | + self.builder.get_object("remove").set_sensitive(True) |
4521 | + |
4522 | + if not self.info_table.flags() & gtk.VISIBLE: |
4523 | + #hide the tip of the day and show the buttons |
4524 | + self.quicktip.hide() |
4525 | + self.quicktip_image.hide() |
4526 | + self.builder.get_object("vbox_panel_buttons").show() |
4527 | + self.builder.get_object("notebook1").show() |
4528 | + self.info_table.show() |
4529 | + |
4530 | + id = int(model.get_value(iter, 3)) |
4531 | + |
4532 | + watch = self.specto.watch_db[id] |
4533 | + watch_values = watch.get_gui_info() |
4534 | + |
4535 | + #set the error log field |
4536 | + if not self.specto.DEBUG: |
4537 | + self.builder.get_object("notebook1").remove_page(2) |
4538 | + else: |
4539 | + if self.builder.get_object("notebook1").get_n_pages() == 2: |
4540 | + self.builder.get_object("notebook1").append_page(self.error_log_window, self.label_error_log) |
4541 | + log_text = self.specto.logger.watch_log(watch.name) |
4542 | + |
4543 | + start = self.log_buffer.get_start_iter() |
4544 | + end = self.log_buffer.get_end_iter() |
4545 | + self.log_buffer.delete(start, end) |
4546 | + |
4547 | + iter = self.log_buffer.get_iter_at_offset(0) |
4548 | + for line in log_text: |
4549 | + self.log_buffer.insert_with_tags_by_name(iter, line[1], line[0]) |
4550 | + |
4551 | + if watch.changed == False: |
4552 | + self.builder.get_object("clear").set_sensitive(False) |
4553 | + self.builder.get_object("btnClear").set_sensitive(False) |
4554 | + self.builder.get_object("lblExtraInfo").set_label(_("No extra information available.")) |
4555 | + else: |
4556 | + self.builder.get_object("clear").set_sensitive(True) |
4557 | + self.builder.get_object("btnClear").set_sensitive(True) |
4558 | + try: |
4559 | + self.extra_info = watch.get_extra_information() |
4560 | + if self.extra_info != "": |
4561 | + try: |
4562 | + self.builder.get_object("lblExtraInfo").set_label(self.extra_info) |
4563 | + except: |
4564 | + self.specto.logger.log(_("Extra information could not be set"), "error", self.specto.watch_db[id].name) |
4565 | + except: |
4566 | + self.specto.logger.log(_("Extra information could not be set"), "error", self.specto.watch_db[id].name) |
4567 | + |
4568 | + i = 0 |
4569 | + while i < 4: |
4570 | + if i >= len(watch_values): |
4571 | + self.info_labels[i][0].set_label("") |
4572 | + self.info_labels[i][1].set_label("") |
4573 | + else: |
4574 | + #create label |
4575 | + self.info_labels[i][0].set_label("<b>" + str(watch_values[i][0]) + ":</b>") |
4576 | + label = watch.escape(str(watch_values[i][1])) |
4577 | + self.info_labels[i][1].set_label(label) |
4578 | + |
4579 | + i += 1 |
4580 | + |
4581 | + image = self.builder.get_object("watch_icon") |
4582 | + image.set_from_pixbuf(self.get_icon(watch.icon, 0, True)) |
4583 | + |
4584 | + def open_watch(self, id): |
4585 | + """ |
4586 | + Open the selected watch. |
4587 | + Returns False if the watch failed to open |
4588 | + """ |
4589 | + return self.specto.watch_db[id].open_watch() |
4590 | + |
4591 | + def open_watch_callback(self, *args): |
4592 | + """ |
4593 | + Opens the selected watch and mark it as unchanged |
4594 | + """ |
4595 | + model, iter = self.treeview.get_selection().get_selected() |
4596 | + id = int(model.get_value(iter, 3)) |
4597 | + self.open_watch(id) |
4598 | + if self.specto.watch_db[id].changed == True: |
4599 | + self.mark_watch_as_read(None, id) |
4600 | + |
4601 | + def show_watch_popup(self, treeview, event, data=None): |
4602 | + if event.button == 3: |
4603 | + x = int(event.x) |
4604 | + y = int(event.y) |
4605 | + time = event.time |
4606 | + pthinfo = treeview.get_path_at_pos(x, y) |
4607 | + if pthinfo is not None: |
4608 | + path, col, cellx, celly = pthinfo |
4609 | + treeview.grab_focus() |
4610 | + treeview.set_cursor(path, col, 0) |
4611 | + menu = self.create_menu(self, self.notifier, None) |
4612 | + menu.popup(None, None, None, 3, time) |
4613 | + return 1 |
4614 | + |
4615 | + def _mark_watch_as_read(self, *widget): |
4616 | + try: |
4617 | + model, iter = self.treeview.get_selection().get_selected() |
4618 | + id = int(model.get_value(iter, 3)) |
4619 | + |
4620 | + self.mark_watch_as_read(id) |
4621 | + except: |
4622 | + pass |
4623 | + |
4624 | + def refresh_watch(self, widget): |
4625 | + model, iter = self.treeview.get_selection().get_selected() |
4626 | + id = int(model.get_value(iter, 3)) |
4627 | + watch = self.specto.watch_db[id] |
4628 | + watch.restart() |
4629 | + |
4630 | + def edit_watch(self, widget): |
4631 | + model, iter = self.treeview.get_selection().get_selected() |
4632 | + id = int(model.get_value(iter, 3)) |
4633 | + self.show_edit_watch(self, widget, id) |
4634 | + |
4635 | + def create_menu(self, window, event, data=None): |
4636 | + model, iter = self.treeview.get_selection().get_selected() |
4637 | + id = int(model.get_value(iter, 3)) |
4638 | + watch = self.specto.watch_db[id] |
4639 | + menu = gtk.Menu() |
4640 | + menuItem = None |
4641 | + |
4642 | + menuItem = create_menu_item(_("Refresh"), self.refresh_watch, |
4643 | + gtk.STOCK_REFRESH) |
4644 | + if not watch.active: |
4645 | + menuItem.set_sensitive(False) |
4646 | + menu.append(menuItem) |
4647 | + |
4648 | + menuItem = create_menu_item(_("Mark as read"), self._mark_watch_as_read, |
4649 | + gtk.STOCK_CLEAR) |
4650 | + if not watch.changed: |
4651 | + menuItem.set_sensitive(False) |
4652 | + menu.append(menuItem) |
4653 | + |
4654 | + menuItem = create_menu_item(_("Crawl"), self.crawl_watch, gtk.STOCK_EDIT) |
4655 | + menu.append(menuItem) |
4656 | + |
4657 | + separator = gtk.SeparatorMenuItem() |
4658 | + menu.append(separator) |
4659 | + |
4660 | + menuItem = create_menu_item(_("Edit"), self.edit_watch, gtk.STOCK_EDIT) |
4661 | + menu.append(menuItem) |
4662 | + |
4663 | + menuItem = create_menu_item(_("Remove"), self.remove_watch, |
4664 | + gtk.STOCK_REMOVE) |
4665 | + menu.append(menuItem) |
4666 | + |
4667 | + menu.show_all() |
4668 | + return menu |
4669 | + |
4670 | + def change_entry_name(self, *args): |
4671 | + """ Edit the name from the watch in the notifier window. """ |
4672 | + # Change the name in the treeview |
4673 | + model, iter = self.treeview.get_selection().get_selected() |
4674 | + id = int(model.get_value(iter, 3)) |
4675 | + self.change_name(args[2], id) |
4676 | + |
4677 | + def change_name(self, new_name, id): |
4678 | + if self.specto.watch_db[id].changed == True: |
4679 | + weight = pango.WEIGHT_BOLD |
4680 | + else: |
4681 | + weight = pango.WEIGHT_NORMAL |
4682 | + self.model.set(self.iter[id], 2, new_name, 5, weight) |
4683 | + |
4684 | + # Write the new name in watches.list |
4685 | + self.specto.watch_io.replace_name(self.specto.watch_db[id].name, new_name) |
4686 | + # Change the name in the database |
4687 | + self.specto.watch_db[id].name = new_name |
4688 | + self.show_watch_info() |
4689 | + |
4690 | +### GUI FUNCTIONS ### |
4691 | + def get_quick_tip(self): |
4692 | + """Return a random tip of the day to be shown on startup""" |
4693 | + tips = [_("You can add all kinds of websites as watches. Static pages, RSS or Atom feeds, etc. Specto will automatically handle them."), |
4694 | + _("Website watches can use an error margin that allows you to set a minimum difference percentage. This allows you to adapt to websites that change constantly or have lots of advertising."), |
4695 | + _("Single-click an existing watch to display information, and double-click it to open the content."), |
4696 | + _("Please set a reasonable refresh interval in order to save bandwidth and prevent you from being blocked from content providers.")] |
4697 | + chosen_tip = tips[randrange(len(tips))] |
4698 | + return chosen_tip |
4699 | + |
4700 | + def toggle_display_toolbar(self, *args): |
4701 | + """ Show or hide the toolbar. """ |
4702 | + if self.builder.get_object("display_toolbar").active: |
4703 | + self.builder.get_object("toolbar").show() |
4704 | + self.specto.specto_gconf.set_entry("hide_toolbar", False) |
4705 | + else: |
4706 | + self.builder.get_object("toolbar").hide() |
4707 | + self.specto.specto_gconf.set_entry("hide_toolbar", True) |
4708 | + |
4709 | + def toggle_show_deactivated_watches(self, *widget): |
4710 | + """ Display only active watches or all watches. """ |
4711 | + if self.startup != True: |
4712 | + self.startup = False # This is important to prevent *widget from messing with us. If you don't believe me, print startup ;) |
4713 | + if self.startup == True: |
4714 | + self.startup = False |
4715 | + else: |
4716 | + if self.builder.get_object("display_all_watches").active: |
4717 | + for watch in self.specto.watch_db: |
4718 | + if watch.active == False: # For each watch that is supposed to be inactive, show it in the notifier but don't activate it |
4719 | + if self.startup == False: # Recreate the item because it was deleted |
4720 | + self.add_notifier_entry(watch.id) |
4721 | + self.specto.specto_gconf.set_entry("show_deactivated_watches", True) |
4722 | + else: # Hide the deactivated watches |
4723 | + for i in self.iter: |
4724 | + if self.model.iter_is_valid(self.iter[i]): |
4725 | + path = self.model.get_path(self.iter[i]) |
4726 | + iter = self.model.get_iter(path) |
4727 | + model = self.model |
4728 | + id = int(model.get_value(iter, 3)) |
4729 | + |
4730 | + if self.specto.watch_db[id].active == False: |
4731 | + model.remove(iter) |
4732 | + self.specto.specto_gconf.set_entry("show_deactivated_watches", False) |
4733 | + |
4734 | + def remove_watch(self, *widget): |
4735 | + try: |
4736 | + model, iter = self.treeview.get_selection().get_selected() |
4737 | + id = int(model.get_value(iter, 3)) |
4738 | + except: |
4739 | + pass |
4740 | + else: |
4741 | + dialog = RemoveDialog(_("Remove a watch"), |
4742 | + (_('<big>Remove the watch "%s"?</big>\nThis operation cannot be undone.') % self.specto.watch_db[id].name)) |
4743 | + answer = dialog.show() |
4744 | + if answer == True: |
4745 | + self.remove_notifier_entry(id) |
4746 | + self.specto.watch_db.remove(id) #remove the watch |
4747 | + self.specto.watch_io.remove_watch(self.specto.watch_db[id].name) |
4748 | + if self.tray: |
4749 | + self.tray.show_tooltip() |
4750 | + |
4751 | + def delete_event(self, *args): |
4752 | + """ |
4753 | + quit specto |
4754 | + """ |
4755 | + self.save_size_and_position() |
4756 | + self.specto.quit() |
4757 | + return True |
4758 | + |
4759 | + |
4760 | + def close_event(self, *args): |
4761 | + """ |
4762 | + if the trayicon and the indicator or not available then quit specto else hide the notifier window |
4763 | + """ |
4764 | + if self.specto.specto_gconf.get_entry("always_show_icon") == True or self.indicator: |
4765 | + self.notifier.hide() |
4766 | + self.specto.specto_gconf.set_entry("show_notifier", False)#save the window state for the next time specto starts |
4767 | + return True |
4768 | + else: |
4769 | + self.specto.quit() |
4770 | + return True |
4771 | + |
4772 | + def restore_size_and_position(self): |
4773 | + """ |
4774 | + Restore the size and the postition from the notifier window. |
4775 | + """ |
4776 | + saved_window_width = self.specto.specto_gconf.get_entry("window_notifier_width") |
4777 | + saved_window_height = self.specto.specto_gconf.get_entry("window_notifier_height") |
4778 | + saved_window_x = self.specto.specto_gconf.get_entry("window_notifier_x") |
4779 | + saved_window_y = self.specto.specto_gconf.get_entry("window_notifier_y") |
4780 | + if self.specto.specto_gconf.get_entry("hide_from_windowlist")==True: |
4781 | + self.notifier.set_skip_taskbar_hint(True) # Hide from the window list applet |
4782 | + |
4783 | + if saved_window_width != None and saved_window_height != None: # Check if the size is not 0 |
4784 | + self.builder.get_object("notifier").resize(saved_window_width, saved_window_height) |
4785 | + |
4786 | + if saved_window_x != None and saved_window_y != None: # Check if the position is not 0 |
4787 | + self.builder.get_object("notifier").move(saved_window_x, saved_window_y) |
4788 | + |
4789 | + def save_size_and_position(self): |
4790 | + """ |
4791 | + Save the size and position from the notifier in gconf when the window is closed. |
4792 | + """ |
4793 | + # Save the size in gconf |
4794 | + current_window_size = self.builder.get_object("notifier").get_size() |
4795 | + current_window_width = current_window_size[0] |
4796 | + current_window_height = current_window_size[1] |
4797 | + self.specto.specto_gconf.set_entry("window_notifier_width", current_window_width) |
4798 | + self.specto.specto_gconf.set_entry("window_notifier_height", current_window_height) |
4799 | + |
4800 | + # Save the window position in gconf when the window is closed |
4801 | + current_window_xy = self.builder.get_object("notifier").get_position() |
4802 | + current_window_x = current_window_xy[0] |
4803 | + current_window_y = current_window_xy[1] |
4804 | + self.specto.specto_gconf.set_entry("window_notifier_x", current_window_x) |
4805 | + self.specto.specto_gconf.set_entry("window_notifier_y", current_window_y) |
4806 | + |
4807 | + def get_state(self): |
4808 | + """ Return True if the notifier window is visible. """ |
4809 | + return bool(self.notifier.flags() & gtk.VISIBLE) |
4810 | + |
4811 | + def create_notifier_gui(self): |
4812 | + """ Create the gui from the notifier. """ |
4813 | + self.treeview = self.builder.get_object("treeview") |
4814 | + self.treeview.set_model(self.model) |
4815 | + self.treeview.set_flags(gtk.TREE_MODEL_ITERS_PERSIST) |
4816 | + self.treeview.connect("button_press_event", self.show_watch_popup, None) |
4817 | + self.builder.get_object("button_clear_all").set_sensitive(False) |
4818 | + self.builder.get_object("clear_all1").set_sensitive(False) |
4819 | + |
4820 | + if self.specto.specto_gconf.get_entry("always_show_icon") == False and not self.indicator: |
4821 | + self.builder.get_object("close").set_sensitive(False) |
4822 | + |
4823 | + if self.specto.specto_gconf.get_entry("show_in_windowlist") == False: |
4824 | + self.notifier.set_skip_taskbar_hint(True) |
4825 | + |
4826 | + |
4827 | + ### Initiate the window |
4828 | + self.restore_size_and_position() |
4829 | + self.show_toolbar = self.specto.specto_gconf.get_entry("show_toolbar") |
4830 | + if self.show_toolbar == False: |
4831 | + self.builder.get_object("display_toolbar").set_active(False) |
4832 | + self.toggle_display_toolbar() |
4833 | + else: |
4834 | + self.builder.get_object("display_toolbar").set_active(True) |
4835 | + self.toggle_display_toolbar() |
4836 | + |
4837 | + self.startup = True |
4838 | + if self.specto.specto_gconf.get_entry("show_deactivated_watches") == True: |
4839 | + self.builder.get_object("display_all_watches").set_active(True) |
4840 | + else: |
4841 | + self.builder.get_object("display_all_watches").set_active(False) |
4842 | + self.startup = False |
4843 | + |
4844 | + if not self.specto.notifier_hide: |
4845 | + self.notifier.show() |
4846 | + |
4847 | + ### Checkbox |
4848 | + self.columnCheck_renderer = gtk.CellRendererToggle() |
4849 | + self.columnCheck_renderer.set_property("activatable", True) |
4850 | + self.columnCheck_renderer.connect("toggled", self.check_clicked, self.model) |
4851 | + self.columnCheck = gtk.TreeViewColumn(_("Active"), self.columnCheck_renderer, active=0) |
4852 | + self.columnCheck.connect("clicked", self.sort_active_from_treeview_headers) |
4853 | + self.columnCheck.set_sort_column_id(0) |
4854 | + self.treeview.append_column(self.columnCheck) |
4855 | + |
4856 | + ### Icon |
4857 | + self.columnIcon_renderer = gtk.CellRendererPixbuf() |
4858 | + self.columnIcon = gtk.TreeViewColumn(_("Type"), self.columnIcon_renderer, pixbuf=1) |
4859 | + self.columnIcon.set_clickable(True) |
4860 | + self.columnIcon.connect("clicked", self.sort_type_from_treeview_headers) |
4861 | + self.treeview.append_column(self.columnIcon) |
4862 | + |
4863 | + ### Titre |
4864 | + self.columnTitle_renderer = gtk.CellRendererText() |
4865 | + #self.columnTitle_renderer.set_property("editable", True) |
4866 | + #self.columnTitle_renderer.connect('edited', self.change_entry_name) |
4867 | + self.columnTitle = gtk.TreeViewColumn(_("Name"), self.columnTitle_renderer, text=2, weight=5) |
4868 | + self.columnTitle.connect("clicked", self.sort_name_from_treeview_headers) |
4869 | + self.columnTitle.set_expand(True) |
4870 | + self.columnTitle.set_resizable(True) |
4871 | + self.columnTitle.set_sort_column_id(2) |
4872 | + self.treeview.append_column(self.columnTitle) |
4873 | + |
4874 | + ### ID |
4875 | + self.columnID_renderer = gtk.CellRendererText() |
4876 | + self.columnID = gtk.TreeViewColumn(_("ID"), self.columnID_renderer, markup=3) |
4877 | + self.columnID.set_visible(False) |
4878 | + self.columnID.set_sort_column_id(3) |
4879 | + self.treeview.append_column(self.columnID) |
4880 | + |
4881 | + ### type |
4882 | + self.renderer = gtk.CellRendererText() |
4883 | + self.columnType = gtk.TreeViewColumn(_("TYPE"), self.renderer, markup=4) |
4884 | + self.columnType.set_visible(False) |
4885 | + self.columnType.set_sort_column_id(4) |
4886 | + self.treeview.append_column(self.columnType) |
4887 | + |
4888 | + self.get_startup_sort_order() |
4889 | + |
4890 | + |
4891 | + ###Create info-panel |
4892 | + vbox_info = self.builder.get_object("vbox_info") |
4893 | + |
4894 | + #show tip of the day |
4895 | + self.quicktip = self.get_quick_tip() |
4896 | + self.quicktip_image = gtk.Image() |
4897 | + self.quicktip_image.set_from_pixbuf(self.get_icon("dialog-information", 0, True)) |
4898 | + self.quicktip_image.show() |
4899 | + vbox_info.pack_start(self.quicktip_image, False, False, 0) |
4900 | + self.quicktip = gtk.Label(("<big>" + _("Tip of the Day:") + "</big> "+ self.quicktip)) |
4901 | + self.quicktip.set_line_wrap(True) |
4902 | + self.quicktip.set_use_markup(True) |
4903 | + self.quicktip.set_alignment(xalign=0.0, yalign=0.5) |
4904 | + self.quicktip.show() |
4905 | + vbox_info.pack_start(self.quicktip, False, False, 0) |
4906 | + |
4907 | + #create the info table |
4908 | + self.info_table = gtk.Table(rows=4, columns=2, homogeneous=True) |
4909 | + self.info_table.set_row_spacings(6) |
4910 | + self.info_table.set_col_spacings(6) |
4911 | + vbox_watch_info = self.builder.get_object("vbox_watch_info") |
4912 | + vbox_watch_info.pack_start(self.info_table, False, False, 0) #show the image |
4913 | + |
4914 | + i = 0 |
4915 | + self.info_labels = [] |
4916 | + while i < 4: |
4917 | + gtk_label = gtk.Label() |
4918 | + gtk_label.set_alignment(xalign=0.0, yalign=0.5) |
4919 | + gtk_label.set_use_markup(True) |
4920 | + gtk_label.set_ellipsize(pango.ELLIPSIZE_END) |
4921 | + gtk_label.show() |
4922 | + |
4923 | + #create value |
4924 | + gtk_label1 = gtk.Label() |
4925 | + gtk_label1.set_alignment(xalign=0.0, yalign=0.5) |
4926 | + gtk_label1.set_use_markup(True) |
4927 | + gtk_label1.set_ellipsize(pango.ELLIPSIZE_END) |
4928 | + gtk_label1.show() |
4929 | + |
4930 | + self.info_labels.extend([(gtk_label, gtk_label1)]) |
4931 | + self.info_table.attach(self.info_labels[i][1], 1, 2, i, i + 1) |
4932 | + self.info_table.attach(self.info_labels[i][0], 0, 1, i, i + 1) |
4933 | + |
4934 | + i += 1 |
4935 | + |
4936 | + #create the error log textview and notebook label |
4937 | + self.error_log = gtk.TextView() |
4938 | + self.log_buffer = self.error_log.get_buffer() |
4939 | + self.log_buffer.create_tag("ERROR", foreground="#a40000") |
4940 | + self.log_buffer.create_tag("INFO", foreground="#4e9a06") |
4941 | + self.log_buffer.create_tag("WARNING", foreground="#c4a000") |
4942 | + self.error_log_window = gtk.ScrolledWindow() |
4943 | + self.error_log_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) |
4944 | + self.error_log_window.add_with_viewport(self.error_log) |
4945 | + self.error_log_window.show() |
4946 | + self.label_error_log = gtk.Label(_("Error log")) |
4947 | + self.error_log.show() |
4948 | + self.label_error_log.show() |
4949 | + |
4950 | + #hide the buttons |
4951 | + self.builder.get_object("vbox_panel_buttons").hide() |
4952 | + |
4953 | + self.builder.get_object("edit").set_sensitive(False) |
4954 | + self.builder.get_object("clear").set_sensitive(False) |
4955 | + self.builder.get_object("remove").set_sensitive(False) |
4956 | + |
4957 | + self.builder.get_object("statusbar1").show() |
4958 | + |
4959 | + self.builder.get_object("notebook1").hide() |
4960 | + |
4961 | + self.generate_add_menu() |
4962 | + |
4963 | +### Sort functions ### |
4964 | + def get_startup_sort_order(self): |
4965 | + order = self.get_gconf_sort_order() |
4966 | + sort_function = self.specto.specto_gconf.get_entry("sort_function") |
4967 | + if sort_function == "name": |
4968 | + self.builder.get_object("by_name").set_active(True) |
4969 | + self.model.set_sort_column_id(2, order) |
4970 | + elif sort_function == "type": |
4971 | + self.builder.get_object("by_watch_type").set_active(True) |
4972 | + self.model.set_sort_column_id(4, order) |
4973 | + elif sort_function == "active": |
4974 | + self.builder.get_object("by_watch_active").set_active(True) |
4975 | + self.model.set_sort_column_id(0, order) |
4976 | + |
4977 | + def get_gconf_sort_order(self): |
4978 | + """ Get the order (asc, desc) from a gconf key. """ |
4979 | + order = self.specto.specto_gconf.get_entry("sort_order") |
4980 | + if order == "asc": |
4981 | + sort_order = gtk.SORT_ASCENDING |
4982 | + else: |
4983 | + sort_order = gtk.SORT_DESCENDING |
4984 | + return sort_order |
4985 | + |
4986 | + def set_gconf_sort_order(self, order): |
4987 | + """ Set the order (asc, desc) for a gconf keys. """ |
4988 | + if order == gtk.SORT_ASCENDING: |
4989 | + sort_order = "asc" |
4990 | + else: |
4991 | + sort_order = "desc" |
4992 | + return sort_order |
4993 | + |
4994 | + def sort_name(self, *args): |
4995 | + """ Sort by watch name. """ |
4996 | + self.model.set_sort_column_id(2, not self.columnTitle.get_sort_order()) |
4997 | + self.specto.specto_gconf.set_entry("sort_function", "name") |
4998 | + |
4999 | + def sort_type(self, *args): |
5000 | + """ Sort by watch type. """ |
Bonjour,
I couldn't run the code yet, it adds a bunch of dependencies, some of which [like "MySQLdb"] are not available in linux distributions and I'm not sure what to expect from such a huge merge.
However, from a look at the surface of things, there are various problems that I've detected. Just run a directory comparison with meld (http:// meld.sf. net) between your branch and the "main" branch and it should become quite apparent. statically link all that code into specto (which I can't afford to maintain anyway)...
- You committed a bunch of unrelated files from a build/ directory.
- The merge is unclean (there are merge conflicts). If possible, rebase your branch onto the latest code (maybe you could use for this if you're used to it).
- You added code that is commented out, and print statements. Please do not add unused code.
- You added a huge amount of "public domain" code as a pdfminer directory. Instead, you should depend on a pdfminer library being packaged by Linux distributions, not copy-paste/
In short, the code needs fixing, various things shouldn't be part of the commits at all (like the build stuff or the pdfminer library) and you should ideally rebase everything onto the latest lp:specto to make the merge easier.
Thanks in advance!