Merge lp:~jconti/gm-notify/messaging-menu into lp:gm-notify
- messaging-menu
- Merge into trunk
Proposed by
Dimitri John Ledkov
Status: | Merged |
---|---|
Approved by: | Mateusz Balbus |
Approved revision: | 96 |
Merged at revision: | 80 |
Proposed branch: | lp:~jconti/gm-notify/messaging-menu |
Merge into: | lp:gm-notify |
Diff against target: |
1304 lines (+762/-216) 10 files modified
MANIFEST (+2/-0) data/gm-notify.convert (+6/-0) data/gm-notify.desktop (+2/-2) data/net.launchpad.gm-notify.gschema.xml (+25/-0) gm-config.ui (+439/-0) gm-notify (+150/-106) gm-notify-config (+84/-75) gm_notify_keyring.py (+40/-24) gtalk.py (+11/-5) setup.py (+3/-4) |
To merge this branch: | bzr merge lp:~jconti/gm-notify/messaging-menu |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Mateusz Balbus | Approve | ||
Review via email: mp+155163@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Dimitri John Ledkov (xnox) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'MANIFEST' |
2 | --- MANIFEST 2010-09-18 13:06:25 +0000 |
3 | +++ MANIFEST 2013-03-25 04:23:21 +0000 |
4 | @@ -4,12 +4,14 @@ |
5 | keyring.py |
6 | setup.py |
7 | gm-config.glade |
8 | +gm-config.ui |
9 | gtalk.py |
10 | data/checking.gif |
11 | data/gm-notify |
12 | data/gm-notify-config.desktop |
13 | data/gm-notify.desktop |
14 | data/gm-notify.schemas |
15 | +data/net.launchpad.gm-notify.gschema.xml |
16 | po/gm-notify.pot |
17 | po/bg/gm-notify.mo |
18 | po/bg/gm-notify.po |
19 | |
20 | === added file 'data/gm-notify.convert' |
21 | --- data/gm-notify.convert 1970-01-01 00:00:00 +0000 |
22 | +++ data/gm-notify.convert 2013-03-25 04:23:21 +0000 |
23 | @@ -0,0 +1,6 @@ |
24 | +[net.launchpad.gm-notify] |
25 | +play-sound = /apps/gm-notify/play_sound |
26 | +ignore-inbox = /apps/gm-notify/ignore_inbox |
27 | +soundfile = /apps/gm-notify/soundfile |
28 | +mailboxes = /apps/gm-notify/mailboxes |
29 | +openclient = /apps/gm-notify/openclient |
30 | |
31 | === modified file 'data/gm-notify.desktop' |
32 | --- data/gm-notify.desktop 2010-06-22 19:46:39 +0000 |
33 | +++ data/gm-notify.desktop 2013-03-25 04:23:21 +0000 |
34 | @@ -1,8 +1,8 @@ |
35 | [Desktop Entry] |
36 | Encoding=UTF-8 |
37 | -Name=Google Mail |
38 | +Name=GMail Notifier |
39 | Comment=An E-Mail Notifier for Google Mail |
40 | -Icon=applications-email-panel |
41 | +Icon=evolution |
42 | Type=Application |
43 | Exec=gm-notify |
44 | StartupNotify=False |
45 | |
46 | === added file 'data/net.launchpad.gm-notify.gschema.xml' |
47 | --- data/net.launchpad.gm-notify.gschema.xml 1970-01-01 00:00:00 +0000 |
48 | +++ data/net.launchpad.gm-notify.gschema.xml 2013-03-25 04:23:21 +0000 |
49 | @@ -0,0 +1,25 @@ |
50 | +<?xml version="1.0" encoding="UTF-8"?> |
51 | +<schemalist> |
52 | + <schema path="/net/launchpad/gm-notify/" id="net.launchpad.gm-notify" gettext-domain="gm-notify"> |
53 | + <key type="b" name="play-sound"> |
54 | + <default>false</default> |
55 | + <summary>Shall we play a sound on new mail?</summary> |
56 | + </key> |
57 | + <key type="b" name="ignore-inbox"> |
58 | + <default>false</default> |
59 | + <summary>If true, there won't be notifications regarding just your inbox.</summary> |
60 | + </key> |
61 | + <key type="s" name="soundfile"> |
62 | + <default>''</default> |
63 | + <summary>Path to the soundfile which should be played when a new mail arrives</summary> |
64 | + </key> |
65 | + <key type="as" name="mailboxes"> |
66 | + <default>[]</default> |
67 | + <summary>List containing mailboxes to check</summary> |
68 | + </key> |
69 | + <key type="b" name="openclient"> |
70 | + <default>false</default> |
71 | + <summary>Shall we open the default mail client or webinterface?</summary> |
72 | + </key> |
73 | + </schema> |
74 | +</schemalist> |
75 | |
76 | === added file 'gm-config.ui' |
77 | --- gm-config.ui 1970-01-01 00:00:00 +0000 |
78 | +++ gm-config.ui 2013-03-25 04:23:21 +0000 |
79 | @@ -0,0 +1,439 @@ |
80 | +<?xml version="1.0" encoding="UTF-8"?> |
81 | +<interface> |
82 | + <!-- interface-requires gtk+ 3.0 --> |
83 | + <object class="GtkWindow" id="gmnotify_config_main"> |
84 | + <property name="can_focus">False</property> |
85 | + <property name="border_width">10</property> |
86 | + <property name="title" translatable="yes">GMail Notifier</property> |
87 | + <property name="window_position">center</property> |
88 | + <property name="icon_name">evolution</property> |
89 | + <child> |
90 | + <object class="GtkBox" id="vbox_main"> |
91 | + <property name="visible">True</property> |
92 | + <property name="can_focus">False</property> |
93 | + <property name="orientation">vertical</property> |
94 | + <property name="spacing">10</property> |
95 | + <child> |
96 | + <object class="GtkNotebook" id="notebook_main"> |
97 | + <property name="visible">True</property> |
98 | + <property name="can_focus">True</property> |
99 | + <child> |
100 | + <object class="GtkBox" id="vbox1"> |
101 | + <property name="can_focus">False</property> |
102 | + <property name="orientation">vertical</property> |
103 | + <child> |
104 | + <object class="GtkGrid" id="grid1"> |
105 | + <property name="visible">True</property> |
106 | + <property name="can_focus">False</property> |
107 | + <property name="row_homogeneous">True</property> |
108 | + <property name="column_homogeneous">True</property> |
109 | + <child> |
110 | + <object class="GtkLabel" id="label_user"> |
111 | + <property name="visible">True</property> |
112 | + <property name="can_focus">False</property> |
113 | + <property name="label" translatable="yes">E-Mail:</property> |
114 | + </object> |
115 | + <packing> |
116 | + <property name="left_attach">0</property> |
117 | + <property name="top_attach">0</property> |
118 | + <property name="width">1</property> |
119 | + <property name="height">1</property> |
120 | + </packing> |
121 | + </child> |
122 | + <child> |
123 | + <object class="GtkLabel" id="label_password"> |
124 | + <property name="visible">True</property> |
125 | + <property name="can_focus">False</property> |
126 | + <property name="label" translatable="yes">Password:</property> |
127 | + </object> |
128 | + <packing> |
129 | + <property name="left_attach">0</property> |
130 | + <property name="top_attach">1</property> |
131 | + <property name="width">1</property> |
132 | + <property name="height">1</property> |
133 | + </packing> |
134 | + </child> |
135 | + <child> |
136 | + <object class="GtkEntry" id="input_user"> |
137 | + <property name="visible">True</property> |
138 | + <property name="can_focus">True</property> |
139 | + <property name="invisible_char">●</property> |
140 | + <property name="invisible_char_set">True</property> |
141 | + </object> |
142 | + <packing> |
143 | + <property name="left_attach">1</property> |
144 | + <property name="top_attach">0</property> |
145 | + <property name="width">1</property> |
146 | + <property name="height">1</property> |
147 | + </packing> |
148 | + </child> |
149 | + <child> |
150 | + <object class="GtkEntry" id="input_password"> |
151 | + <property name="visible">True</property> |
152 | + <property name="can_focus">True</property> |
153 | + <property name="visibility">False</property> |
154 | + <property name="invisible_char">●</property> |
155 | + <property name="invisible_char_set">True</property> |
156 | + <signal name="focus-out-event" handler="on_input_password_focus_out_event" swapped="no"/> |
157 | + </object> |
158 | + <packing> |
159 | + <property name="left_attach">1</property> |
160 | + <property name="top_attach">1</property> |
161 | + <property name="width">1</property> |
162 | + <property name="height">1</property> |
163 | + </packing> |
164 | + </child> |
165 | + <child> |
166 | + <object class="GtkImage" id="image_credentials"> |
167 | + <property name="visible">True</property> |
168 | + <property name="can_focus">False</property> |
169 | + <property name="stock">gtk-stop</property> |
170 | + </object> |
171 | + <packing> |
172 | + <property name="left_attach">0</property> |
173 | + <property name="top_attach">2</property> |
174 | + <property name="width">1</property> |
175 | + <property name="height">1</property> |
176 | + </packing> |
177 | + </child> |
178 | + <child> |
179 | + <object class="GtkLabel" id="label_credentials"> |
180 | + <property name="visible">True</property> |
181 | + <property name="can_focus">False</property> |
182 | + <property name="label" translatable="yes">Please enter credentials</property> |
183 | + </object> |
184 | + <packing> |
185 | + <property name="left_attach">1</property> |
186 | + <property name="top_attach">2</property> |
187 | + <property name="width">1</property> |
188 | + <property name="height">1</property> |
189 | + </packing> |
190 | + </child> |
191 | + </object> |
192 | + <packing> |
193 | + <property name="expand">True</property> |
194 | + <property name="fill">True</property> |
195 | + <property name="position">0</property> |
196 | + </packing> |
197 | + </child> |
198 | + <child> |
199 | + <object class="GtkHSeparator" id="seperator_account"> |
200 | + <property name="visible">True</property> |
201 | + <property name="can_focus">False</property> |
202 | + </object> |
203 | + <packing> |
204 | + <property name="expand">False</property> |
205 | + <property name="fill">True</property> |
206 | + <property name="position">2</property> |
207 | + </packing> |
208 | + </child> |
209 | + <child> |
210 | + <object class="GtkBox" id="vbox2"> |
211 | + <property name="visible">True</property> |
212 | + <property name="can_focus">False</property> |
213 | + <property name="border_width">10</property> |
214 | + <property name="orientation">vertical</property> |
215 | + <property name="spacing">5</property> |
216 | + <child> |
217 | + <object class="GtkLabel" id="label_click"> |
218 | + <property name="visible">True</property> |
219 | + <property name="can_focus">False</property> |
220 | + <property name="xalign">0</property> |
221 | + <property name="label" translatable="yes">Click on applet opens:</property> |
222 | + </object> |
223 | + <packing> |
224 | + <property name="expand">False</property> |
225 | + <property name="fill">True</property> |
226 | + <property name="position">0</property> |
227 | + </packing> |
228 | + </child> |
229 | + <child> |
230 | + <object class="GtkAlignment" id="alignment1"> |
231 | + <property name="visible">True</property> |
232 | + <property name="can_focus">False</property> |
233 | + <property name="left_padding">20</property> |
234 | + <child> |
235 | + <object class="GtkRadioButton" id="radiobutton_openweb"> |
236 | + <property name="label" translatable="yes">GMail webinterface</property> |
237 | + <property name="visible">True</property> |
238 | + <property name="can_focus">True</property> |
239 | + <property name="receives_default">False</property> |
240 | + <property name="relief">none</property> |
241 | + <property name="xalign">0.5</property> |
242 | + <property name="active">True</property> |
243 | + <property name="draw_indicator">True</property> |
244 | + </object> |
245 | + </child> |
246 | + </object> |
247 | + <packing> |
248 | + <property name="expand">False</property> |
249 | + <property name="fill">True</property> |
250 | + <property name="position">1</property> |
251 | + </packing> |
252 | + </child> |
253 | + <child> |
254 | + <object class="GtkAlignment" id="alignment2"> |
255 | + <property name="visible">True</property> |
256 | + <property name="can_focus">False</property> |
257 | + <property name="left_padding">20</property> |
258 | + <child> |
259 | + <object class="GtkRadioButton" id="radiobutton_openclient"> |
260 | + <property name="label" translatable="yes">Current default mail client</property> |
261 | + <property name="visible">True</property> |
262 | + <property name="can_focus">True</property> |
263 | + <property name="receives_default">False</property> |
264 | + <property name="xalign">0.5</property> |
265 | + <property name="yalign">0.50999999046325684</property> |
266 | + <property name="active">True</property> |
267 | + <property name="draw_indicator">True</property> |
268 | + <property name="group">radiobutton_openweb</property> |
269 | + </object> |
270 | + </child> |
271 | + </object> |
272 | + <packing> |
273 | + <property name="expand">False</property> |
274 | + <property name="fill">True</property> |
275 | + <property name="position">2</property> |
276 | + </packing> |
277 | + </child> |
278 | + </object> |
279 | + <packing> |
280 | + <property name="expand">False</property> |
281 | + <property name="fill">True</property> |
282 | + <property name="position">3</property> |
283 | + </packing> |
284 | + </child> |
285 | + </object> |
286 | + </child> |
287 | + <child type="tab"> |
288 | + <object class="GtkLabel" id="label_account"> |
289 | + <property name="visible">True</property> |
290 | + <property name="can_focus">False</property> |
291 | + <property name="label" translatable="yes">Account</property> |
292 | + </object> |
293 | + <packing> |
294 | + <property name="tab_fill">False</property> |
295 | + </packing> |
296 | + </child> |
297 | + <child> |
298 | + <object class="GtkBox" id="vbox_enhanced"> |
299 | + <property name="visible">True</property> |
300 | + <property name="can_focus">False</property> |
301 | + <property name="border_width">10</property> |
302 | + <property name="orientation">vertical</property> |
303 | + <property name="spacing">5</property> |
304 | + <child> |
305 | + <object class="GtkCheckButton" id="checkbutton_sound"> |
306 | + <property name="label" translatable="yes">Play sound when new message arrives</property> |
307 | + <property name="visible">True</property> |
308 | + <property name="can_focus">True</property> |
309 | + <property name="receives_default">False</property> |
310 | + <property name="relief">half</property> |
311 | + <property name="xalign">0.5</property> |
312 | + <property name="draw_indicator">True</property> |
313 | + <signal name="toggled" handler="on_checkbutton_sound_toggled" swapped="no"/> |
314 | + </object> |
315 | + <packing> |
316 | + <property name="expand">False</property> |
317 | + <property name="fill">True</property> |
318 | + <property name="position">0</property> |
319 | + </packing> |
320 | + </child> |
321 | + <child> |
322 | + <object class="GtkFileChooserButton" id="fcbutton_sound"> |
323 | + <property name="visible">True</property> |
324 | + <property name="can_focus">False</property> |
325 | + <property name="create_folders">False</property> |
326 | + </object> |
327 | + <packing> |
328 | + <property name="expand">False</property> |
329 | + <property name="fill">True</property> |
330 | + <property name="position">1</property> |
331 | + </packing> |
332 | + </child> |
333 | + <child> |
334 | + <object class="GtkFrame" id="frame_labels"> |
335 | + <property name="visible">True</property> |
336 | + <property name="can_focus">False</property> |
337 | + <property name="label_xalign">0</property> |
338 | + <property name="shadow_type">none</property> |
339 | + <child> |
340 | + <object class="GtkAlignment" id="alignment3"> |
341 | + <property name="visible">True</property> |
342 | + <property name="can_focus">False</property> |
343 | + <property name="left_padding">12</property> |
344 | + <child> |
345 | + <object class="GtkBox" id="vbox3"> |
346 | + <property name="visible">True</property> |
347 | + <property name="can_focus">False</property> |
348 | + <property name="orientation">vertical</property> |
349 | + <child> |
350 | + <object class="GtkLabel" id="label_labeldesc"> |
351 | + <property name="visible">True</property> |
352 | + <property name="can_focus">False</property> |
353 | + <property name="xalign">0</property> |
354 | + <property name="label" translatable="yes">Please enter the Labels you want to have |
355 | +checked seperated by commas</property> |
356 | + </object> |
357 | + <packing> |
358 | + <property name="expand">False</property> |
359 | + <property name="fill">True</property> |
360 | + <property name="padding">5</property> |
361 | + <property name="position">0</property> |
362 | + </packing> |
363 | + </child> |
364 | + <child> |
365 | + <object class="GtkEntry" id="entry_labels"> |
366 | + <property name="visible">True</property> |
367 | + <property name="can_focus">True</property> |
368 | + <property name="invisible_char">●</property> |
369 | + </object> |
370 | + <packing> |
371 | + <property name="expand">False</property> |
372 | + <property name="fill">True</property> |
373 | + <property name="position">1</property> |
374 | + </packing> |
375 | + </child> |
376 | + <child> |
377 | + <object class="GtkCheckButton" id="checkbutton_inbox"> |
378 | + <property name="label" translatable="yes">Ignore inbox</property> |
379 | + <property name="visible">True</property> |
380 | + <property name="can_focus">True</property> |
381 | + <property name="receives_default">False</property> |
382 | + <property name="xalign">0.5</property> |
383 | + <property name="yalign">0.46000000834465027</property> |
384 | + <property name="draw_indicator">True</property> |
385 | + </object> |
386 | + <packing> |
387 | + <property name="expand">True</property> |
388 | + <property name="fill">True</property> |
389 | + <property name="position">2</property> |
390 | + </packing> |
391 | + </child> |
392 | + </object> |
393 | + </child> |
394 | + </object> |
395 | + </child> |
396 | + <child type="label"> |
397 | + <object class="GtkLabel" id="label_labels"> |
398 | + <property name="visible">True</property> |
399 | + <property name="can_focus">False</property> |
400 | + <property name="label" translatable="yes"><b>Labels:</b></property> |
401 | + <property name="use_markup">True</property> |
402 | + </object> |
403 | + </child> |
404 | + </object> |
405 | + <packing> |
406 | + <property name="expand">False</property> |
407 | + <property name="fill">True</property> |
408 | + <property name="position">2</property> |
409 | + </packing> |
410 | + </child> |
411 | + <child> |
412 | + <object class="GtkFrame" id="frame_autostart"> |
413 | + <property name="visible">True</property> |
414 | + <property name="can_focus">False</property> |
415 | + <property name="label_xalign">0</property> |
416 | + <property name="shadow_type">none</property> |
417 | + <child> |
418 | + <object class="GtkAlignment" id="alignment4"> |
419 | + <property name="visible">True</property> |
420 | + <property name="can_focus">False</property> |
421 | + <property name="left_padding">12</property> |
422 | + <child> |
423 | + <object class="GtkCheckButton" id="checkbutton_autostart"> |
424 | + <property name="label" translatable="yes">Start automatically on logon</property> |
425 | + <property name="visible">True</property> |
426 | + <property name="can_focus">True</property> |
427 | + <property name="receives_default">False</property> |
428 | + <property name="xalign">0.5</property> |
429 | + <property name="draw_indicator">True</property> |
430 | + </object> |
431 | + </child> |
432 | + </object> |
433 | + </child> |
434 | + <child type="label"> |
435 | + <object class="GtkLabel" id="label1"> |
436 | + <property name="visible">True</property> |
437 | + <property name="can_focus">False</property> |
438 | + <property name="label" translatable="yes"><b>Autostart:</b></property> |
439 | + <property name="use_markup">True</property> |
440 | + </object> |
441 | + </child> |
442 | + </object> |
443 | + <packing> |
444 | + <property name="expand">False</property> |
445 | + <property name="fill">True</property> |
446 | + <property name="position">3</property> |
447 | + </packing> |
448 | + </child> |
449 | + </object> |
450 | + <packing> |
451 | + <property name="position">1</property> |
452 | + <property name="tab_fill">False</property> |
453 | + </packing> |
454 | + </child> |
455 | + <child type="tab"> |
456 | + <object class="GtkLabel" id="label_enhanced"> |
457 | + <property name="visible">True</property> |
458 | + <property name="can_focus">False</property> |
459 | + <property name="label" translatable="yes">Enhanced</property> |
460 | + </object> |
461 | + <packing> |
462 | + <property name="position">1</property> |
463 | + <property name="tab_fill">False</property> |
464 | + </packing> |
465 | + </child> |
466 | + </object> |
467 | + <packing> |
468 | + <property name="expand">True</property> |
469 | + <property name="fill">True</property> |
470 | + <property name="position">0</property> |
471 | + </packing> |
472 | + </child> |
473 | + <child> |
474 | + <object class="GtkBox" id="hbox_mainbuttons"> |
475 | + <property name="visible">True</property> |
476 | + <property name="can_focus">False</property> |
477 | + <property name="spacing">10</property> |
478 | + <child> |
479 | + <object class="GtkButton" id="button_apply"> |
480 | + <property name="label">gtk-apply</property> |
481 | + <property name="visible">True</property> |
482 | + <property name="can_focus">True</property> |
483 | + <property name="receives_default">True</property> |
484 | + <property name="use_stock">True</property> |
485 | + <signal name="clicked" handler="on_button_apply_clicked" swapped="no"/> |
486 | + </object> |
487 | + <packing> |
488 | + <property name="expand">True</property> |
489 | + <property name="fill">True</property> |
490 | + <property name="position">0</property> |
491 | + </packing> |
492 | + </child> |
493 | + <child> |
494 | + <object class="GtkButton" id="button_close"> |
495 | + <property name="label">gtk-close</property> |
496 | + <property name="visible">True</property> |
497 | + <property name="can_focus">True</property> |
498 | + <property name="receives_default">True</property> |
499 | + <property name="use_stock">True</property> |
500 | + <signal name="clicked" handler="gtk_main_quit" swapped="no"/> |
501 | + </object> |
502 | + <packing> |
503 | + <property name="expand">True</property> |
504 | + <property name="fill">True</property> |
505 | + <property name="position">1</property> |
506 | + </packing> |
507 | + </child> |
508 | + </object> |
509 | + <packing> |
510 | + <property name="expand">False</property> |
511 | + <property name="fill">True</property> |
512 | + <property name="position">1</property> |
513 | + </packing> |
514 | + </child> |
515 | + </object> |
516 | + </child> |
517 | + </object> |
518 | +</interface> |
519 | |
520 | === modified file 'gm-notify' |
521 | --- gm-notify 2010-09-18 13:06:25 +0000 |
522 | +++ gm-notify 2013-03-25 04:23:21 +0000 |
523 | @@ -1,4 +1,4 @@ |
524 | -#!/usr/bin/env python |
525 | +#!/usr/bin/python |
526 | # -*- coding: utf-8 -*- |
527 | |
528 | # gm-notify v0.10.3 |
529 | @@ -19,21 +19,18 @@ |
530 | # You should have received a copy of the GNU General Public License |
531 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
532 | # |
533 | +from __future__ import print_function |
534 | + |
535 | import os |
536 | import sys |
537 | import subprocess |
538 | import gettext |
539 | import webbrowser |
540 | |
541 | -import pynotify |
542 | -import indicate |
543 | -import gobject |
544 | -import pygst |
545 | -pygst.require("0.10") |
546 | -import gst |
547 | -import gconf |
548 | -from twisted.internet import glib2reactor |
549 | -glib2reactor.install() |
550 | +from gi.repository import Gio, GLib, MessagingMenu, Notify |
551 | + |
552 | +from twisted.internet import gireactor |
553 | +gireactor.install() |
554 | from twisted.internet import reactor |
555 | from twisted.words.protocols.jabber import jid |
556 | |
557 | @@ -57,22 +54,69 @@ |
558 | if os.path.exists(path) and os.access(path, os.X_OK): return path |
559 | raise PathNotFound("%s not found" % name) |
560 | |
561 | -class CheckMail(): |
562 | +def play_sound(name): |
563 | + '''Spawns a canberra-gtk-play process to play the sound''' |
564 | + if name is None: |
565 | + return |
566 | + player_path = "/usr/bin/canberra-gtk-play" |
567 | + # Not installed? |
568 | + if not os.path.exists(player_path): |
569 | + return |
570 | + command = [player_path] |
571 | + # File exists, so use the file flag |
572 | + if os.path.exists(name): |
573 | + command.extend(["-f", name]) |
574 | + # Assume it is a sound id |
575 | + else: |
576 | + command.extend(["-i", name]) |
577 | + try: |
578 | + result = GLib.spawn_async(command) |
579 | + except: |
580 | + return |
581 | + # Does nothing but the documentation says to do it anyway |
582 | + if len(result) > 0: |
583 | + GLib.spawn_close_pid(result[0]) |
584 | + |
585 | +class CheckMail(Gio.Application): |
586 | def __init__(self): |
587 | '''initiates DBUS-Messaging interface, creates the MailChecker and registers with indicator-applet. |
588 | In the end it starts the periodic check timer and a gtk main-loop''' |
589 | - |
590 | - # Kill running gm-notify processes (UGLY!) |
591 | - subprocess.call("kill `pgrep -f gm-notify | grep -v %s`" % os.getpid(), stdout=open("/dev/null", "w"), shell=True) |
592 | - |
593 | - # Initiate pynotify and Gnome Keyring |
594 | - if not pynotify.init(_("GMail Notifier")): |
595 | + super(CheckMail, self).__init__(application_id="net.launchpad.gm-notify", |
596 | + flags=Gio.ApplicationFlags.FLAGS_NONE) |
597 | + |
598 | + self._has_activated = False |
599 | + self._counts = {} |
600 | + self.connect("activate", self.on_activate) |
601 | + |
602 | + def on_remote_quit(self, action, args): |
603 | + '''Stops the application when the "remote-quit" action is activated''' |
604 | + reactor.stop() |
605 | + |
606 | + def on_activate(self, app): |
607 | + '''When first receiving the activate signal, initialize the primary |
608 | + instance. On subsequent activate signals, we are being activated from a |
609 | + secondary instance, so treat it as if our name was clicked in the |
610 | + messaging menu.''' |
611 | + if self._has_activated: |
612 | + self.indicator_clicked() |
613 | + return |
614 | + |
615 | + self._has_activated = True |
616 | + |
617 | + # Add an action to quit |
618 | + quit_action = Gio.SimpleAction.new("remote-quit", None) |
619 | + quit_action.connect("activate", self.on_remote_quit) |
620 | + self.add_action(quit_action) |
621 | + |
622 | + # Initialize the desktop notifications |
623 | + if not Notify.init(_("GMail Notifier")): |
624 | sys.exit(-1) |
625 | - |
626 | + |
627 | keys = keyring.Keyring("GMail", "mail.google.com", "http") |
628 | if keys.has_credentials(): |
629 | self.creds = keys.get_credentials() |
630 | else: |
631 | + print("Failed to get credentials") |
632 | # Start gm-notify-config if no credentials are found |
633 | try: |
634 | subprocess.call(get_executable_path("gm-notify-config")) |
635 | @@ -88,67 +132,86 @@ |
636 | else: |
637 | self.domain = self.jid.host |
638 | |
639 | - # init gconf to read config values |
640 | - self.client = gconf.client_get_default() |
641 | - |
642 | - # init sound |
643 | - soundfile = self.client.get_string("/apps/gm-notify/soundfile") |
644 | - if self.client.get_bool("/apps/gm-notify/play_sound") and soundfile: |
645 | - self.player = gst.element_factory_make("playbin", "player") |
646 | - self.player.set_property("video-sink", gst.element_factory_make("fakesink", "fakesink")) |
647 | - self.player.set_property("uri", "file://" + soundfile) |
648 | - bus = self.player.get_bus() |
649 | - bus.add_signal_watch() |
650 | - bus.connect("message", self.gst_message) |
651 | - else: |
652 | - self.player = None |
653 | - |
654 | - # Register with Indicator-Applet |
655 | - self.server = indicate.indicate_server_ref_default() |
656 | - self.server.set_type("message.mail") |
657 | - self.server.set_desktop_file("/usr/share/gm-notify/gm-notify.desktop") |
658 | - self.server.connect("server-display", self.serverClick) |
659 | - self.indicators = {} |
660 | - |
661 | - # Read /apps/gm-notify/ignore_inbox value. If true you will only receive |
662 | - # notifications about configured labels |
663 | - self.ignore_inbox = self.client.get_bool("/apps/gm-notify/ignore_inbox") |
664 | + self.client = Gio.Settings("net.launchpad.gm-notify") |
665 | + |
666 | + # Set up the sound file |
667 | + self._soundfile = self.client.get_string("soundfile") |
668 | + if self._soundfile == '': |
669 | + self._soundfile = "message-new-instant" |
670 | + if not self.client.get_boolean("play-sound"): |
671 | + self._soundfile = None |
672 | + |
673 | + # Messaging Menu integration |
674 | + self._m_menu = MessagingMenu.App.new("gm-notify.desktop") |
675 | + self._m_menu.register() |
676 | + self._m_menu.connect("activate-source", self.source_clicked) |
677 | + |
678 | + # Read ignore-inbox value. If true you will only receive notifications |
679 | + # about configured labels |
680 | + self.ignore_inbox = self.client.get_boolean("ignore-inbox") |
681 | |
682 | # Retrieve the mailbox we're gonna check |
683 | - self.mailboxes = self.client.get_list("/apps/gm-notify/mailboxes", gconf.VALUE_STRING) |
684 | + self.mailboxes = self.client.get_strv("mailboxes") |
685 | self.mailboxes.insert(0, "inbox") |
686 | - self.addMailboxIndicators() |
687 | self.checker = MailChecker(self.jid, self.creds[1], self.mailboxes[1:], self.new_mail, self.update_count) |
688 | self.checker.connect() |
689 | - |
690 | - reactor.run() |
691 | - |
692 | - def gst_message(self, bus, message): |
693 | - if message.type == gst.MESSAGE_EOS: |
694 | - self.player.set_state(gst.STATE_NULL) |
695 | - elif message.type == gst.MESSAGE_ERROR: |
696 | - self.player.set_state(gst.STATE_NULL) |
697 | - print "Error: %s - %s" % message.parse_error() |
698 | - |
699 | - def serverClick(self, server, timestamp=None): |
700 | - '''called when the server is clicked in the indicator-applet and performs a Mail Check''' |
701 | - for indicator in self.indicators: |
702 | - self.indicators[indicator].set_property("draw-attention", "false") |
703 | - |
704 | - if self.player: self.player.set_state(gst.STATE_NULL) |
705 | + |
706 | + def indicator_clicked(self): |
707 | + '''called when "Google Mail" is clicked in indicator-messages and |
708 | + performs a Mail Check''' |
709 | + for label in self.mailboxes: |
710 | + self.remove_attention(label) |
711 | + |
712 | self.checker.queryInbox() |
713 | + |
714 | + def remove_attention(self, label): |
715 | + '''Removes attention from the label source if it exists''' |
716 | + if self._m_menu.has_source(label): |
717 | + self._m_menu.remove_attention(label) |
718 | + |
719 | + def has_source(self, label): |
720 | + '''Returns true if we have this label, or if we don't and it is in our |
721 | + mailboxes list, create it''' |
722 | + if label == "inbox" and self.ignore_inbox: |
723 | + return False |
724 | + elif label in self.mailboxes: |
725 | + if not self._m_menu.has_source(label): |
726 | + if label in MAILBOXES_NAMES: |
727 | + name = MAILBOXES_NAMES[label] |
728 | + else: |
729 | + name = label |
730 | + if label == "inbox": |
731 | + self._m_menu.insert_source_with_string(0, label, None, name, _("empty")) |
732 | + else: |
733 | + self._m_menu.append_source_with_string(label, None, name, _("empty")) |
734 | + if label in self._counts: |
735 | + self._m_menu.set_source_count(label, self._counts[label]) |
736 | + return True |
737 | + else: |
738 | + return False |
739 | |
740 | def update_count(self, count): |
741 | + '''Updates the count for all the mailboxes''' |
742 | for mailbox in count.iteritems(): |
743 | if mailbox[0] == "inbox" and self.ignore_inbox: |
744 | continue |
745 | |
746 | - i = self.indicators[mailbox[0]] |
747 | - if int(i.get_property("count")) > int(mailbox[1]): |
748 | - i.set_property("draw-attention", "false") |
749 | - i.set_property("count", unicode(mailbox[1])) |
750 | - if int(mailbox[1]) or mailbox[0] == "inbox": i.show() |
751 | - else: i.hide() |
752 | + if self.has_source(mailbox[0]): |
753 | + # Get the last count |
754 | + last_count = 0 |
755 | + if mailbox[0] in self._counts: |
756 | + last_count = self._counts[mailbox[0]] |
757 | + current_count = int(mailbox[1]) |
758 | + |
759 | + # Remove attention if the count has decreased |
760 | + if last_count > current_count: |
761 | + self._m_menu.remove_attention(mailbox[0]) |
762 | + if current_count > 0: |
763 | + self._m_menu.set_source_count(mailbox[0], current_count) |
764 | + # Remove the source if 0 messages, to save space |
765 | + else: |
766 | + self._m_menu.remove_source(mailbox[0]) |
767 | + self._counts[mailbox[0]] = current_count |
768 | |
769 | def new_mail(self, mails): |
770 | '''Takes mailbox name and titles of mails, to display notification and add indicators''' |
771 | @@ -158,11 +221,12 @@ |
772 | got_label = False |
773 | for label in mail['labels']: |
774 | if label == u"^i": label = "inbox" |
775 | - if label in self.indicators: |
776 | - if not label == "inbox" or not self.ignore_inbox: |
777 | - got_label = True |
778 | - self.indicators[label].set_property("draw-attention", "true") |
779 | - if not got_label and self.ignore_inbox: continue |
780 | + if label == "inbox" and self.ignore_inbox: |
781 | + continue |
782 | + if self.has_source(label): |
783 | + got_label = True |
784 | + self._m_menu.draw_attention(label) |
785 | + if not got_label: continue |
786 | |
787 | if "sender_name" in mail: text += mail['sender_name'] + ":\n" |
788 | elif "sender_address" in mail: text += mail['sender_address'] + ":\n" |
789 | @@ -179,9 +243,9 @@ |
790 | |
791 | if text: |
792 | self.showNotification(_("Incoming message"), text.strip("\n")) |
793 | - if self.player: self.player.set_state(gst.STATE_PLAYING) |
794 | + play_sound(self._soundfile) |
795 | |
796 | - def labelClick(self, indicator, timestamp=None): |
797 | + def source_clicked(self, app, source_id): |
798 | '''called when a label is clicked in the indicator-applet and opens the corresponding gmail page''' |
799 | if self.domain: |
800 | url = "https://mail.google.com/a/"+self.domain+"/" |
801 | @@ -189,49 +253,29 @@ |
802 | url = "https://mail.google.com/mail/" |
803 | |
804 | try: |
805 | - url += "#%s" % MAILBOXES_URLS[indicator.label] |
806 | + url += "#%s" % MAILBOXES_URLS[source_id] |
807 | except KeyError: |
808 | - url += "#label/%s" % indicator.label |
809 | - |
810 | - indicator.set_property("draw-attention", "false") |
811 | + url += "#label/%s" % source_id |
812 | |
813 | # Open mail client |
814 | - if self.client.get_bool("/apps/gm-notify/openclient"): |
815 | - command = self.client.get_string("/desktop/gnome/url-handlers/mailto/command").split(" ")[0] |
816 | - if command.find("mutt") != -1: command += " -f =%s" % indicator.label |
817 | - if self.client.get_bool("/desktop/gnome/url-handlers/mailto/needs_terminal"): |
818 | - termCmd = self.client.get_string("/desktop/gnome/applications/terminal/exec") |
819 | - if termCmd: |
820 | - termCmd += " " + self.client.get_string("/desktop/gnome/applications/terminal/exec_arg") + " " |
821 | - else: |
822 | - termCmd = "gnome-terminal -x " |
823 | - command = termCmd + command |
824 | - subprocess.Popen(command, shell=True) |
825 | + if self.client.get_boolean("openclient"): |
826 | + try: |
827 | + info = Gio.AppInfo.get_default_for_type("x-scheme-handler/mailto", False) |
828 | + info.launch(None, None) |
829 | + except: |
830 | + pass |
831 | else: |
832 | webbrowser.open(url) |
833 | - |
834 | + |
835 | def showNotification(self, title, message): |
836 | '''takes a title and a message to display the email notification. Returns the |
837 | created notification object''' |
838 | |
839 | - n = pynotify.Notification(title, message, "notification-message-email") |
840 | + n = Notify.Notification.new(title, message, "notification-message-email") |
841 | n.show() |
842 | |
843 | return n |
844 | |
845 | - def addMailboxIndicators(self): |
846 | - for mailbox in reversed(self.mailboxes): |
847 | - new_indicator = indicate.Indicator() |
848 | - |
849 | - try: |
850 | - new_indicator.set_property("name", MAILBOXES_NAMES[mailbox]) |
851 | - except KeyError: |
852 | - new_indicator.set_property("name", mailbox) |
853 | - new_indicator.set_property("count", "0") |
854 | - new_indicator.label = mailbox |
855 | - new_indicator.connect("user-display", self.labelClick) |
856 | - self.indicators[mailbox] = new_indicator |
857 | - self.indicators["inbox"].show() |
858 | - if self.ignore_inbox: self.indicators["inbox"].hide() |
859 | - |
860 | cm = CheckMail() |
861 | +reactor.registerGApplication(cm) |
862 | +reactor.run() |
863 | |
864 | === modified file 'gm-notify-config' |
865 | --- gm-notify-config 2010-09-18 13:06:25 +0000 |
866 | +++ gm-notify-config 2013-03-25 04:23:21 +0000 |
867 | @@ -19,19 +19,18 @@ |
868 | # You should have received a copy of the GNU General Public License |
869 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
870 | # |
871 | +from __future__ import print_function |
872 | + |
873 | import sys |
874 | import os |
875 | import gettext |
876 | import subprocess |
877 | import shutil |
878 | |
879 | -import pynotify |
880 | -import pygtk |
881 | -pygtk.require("2.0") |
882 | -import gtk, gtk.glade |
883 | -import gconf |
884 | -from twisted.internet import gtk2reactor |
885 | -gtk2reactor.install() |
886 | +from gi.repository import Gio, Gtk |
887 | + |
888 | +from twisted.internet import gtk3reactor |
889 | +gtk3reactor.install() |
890 | from twisted.internet import reactor |
891 | from twisted.words.protocols.jabber import jid |
892 | |
893 | @@ -39,8 +38,6 @@ |
894 | from gtalk import MailChecker |
895 | |
896 | _ = gettext.translation('gm-notify', fallback=True).ugettext |
897 | -if not pynotify.init(_("GMail Notifier")): |
898 | - sys.exit(-1) |
899 | |
900 | class PathNotFound(Exception): pass |
901 | |
902 | @@ -53,24 +50,39 @@ |
903 | if os.path.exists(path) and os.access(path, os.X_OK): return path |
904 | raise PathNotFound("%s not found" % name) |
905 | |
906 | -class Window: |
907 | +class Window(Gtk.Application): |
908 | def __init__(self): |
909 | + super(Window, self).__init__(application_id="net.launchpad.gm-notify-config", |
910 | + flags=Gio.ApplicationFlags.FLAGS_NONE) |
911 | + self.window = None |
912 | + self.connect("activate", self.on_activate) |
913 | + |
914 | + def on_activate(self, app): |
915 | + '''Setup the application''' |
916 | + if self.window is not None: |
917 | + return |
918 | + |
919 | ##### |
920 | # GUI initialization |
921 | ##### |
922 | self.keys = keyring.Keyring("GMail", "mail.google.com", "http") |
923 | - self.client = gconf.client_get_default() |
924 | + self.client = Gio.Settings("net.launchpad.gm-notify") |
925 | |
926 | - if os.path.exists("gm-config.glade"): |
927 | - glade_file = "gm-config.glade" |
928 | - elif os.path.exists("/usr/local/share/gm-notify/gm-config.glade"): |
929 | - glade_file = "/usr/local/share/gm-notify/gm-config.glade" |
930 | - elif os.path.exists("/usr/share/gm-notify/gm-config.glade"): |
931 | - glade_file = "/usr/share/gm-notify/gm-config.glade" |
932 | + if os.path.exists("gm-config.ui"): |
933 | + builder_file = "gm-config.ui" |
934 | + elif os.path.exists("/usr/local/share/gm-notify/gm-config.ui"): |
935 | + builder_file = "/usr/local/share/gm-notify/gm-config.ui" |
936 | + elif os.path.exists("/usr/share/gm-notify/gm-config.ui"): |
937 | + builder_file = "/usr/share/gm-notify/gm-config.ui" |
938 | |
939 | - self.wTree = gtk.glade.XML(glade_file, "gmnotify_config_main", "gm-notify") |
940 | - self.window = self.wTree.get_widget("gmnotify_config_main") |
941 | + self.wTree = Gtk.Builder.new() |
942 | + self.wTree.add_from_file(builder_file) |
943 | + self.wTree.set_translation_domain("gm-notify") |
944 | + self.window = self.wTree.get_object("gmnotify_config_main") |
945 | self.window.show_all() |
946 | + self.add_window(self.window) |
947 | + |
948 | + self.wTree.get_object("notebook_main").set_current_page(0) |
949 | |
950 | ##### |
951 | # Init with stored values |
952 | @@ -81,8 +93,8 @@ |
953 | self.creds = self.keys.get_credentials() |
954 | else: |
955 | self.creds = ("", "") |
956 | - self.wTree.get_widget("input_user").set_text(self.creds[0]) |
957 | - self.wTree.get_widget("input_password").set_text(self.creds[1]) |
958 | + self.wTree.get_object("input_user").set_text(self.creds[0]) |
959 | + self.wTree.get_object("input_password").set_text(self.creds[1]) |
960 | |
961 | self.api = MailChecker("", "") |
962 | self.api.cb_auth_successful = self.credentials_valid |
963 | @@ -91,68 +103,64 @@ |
964 | self.check_credentials(None, None) |
965 | |
966 | # Sound |
967 | - self.wTree.get_widget("checkbutton_sound").set_active(self.client.get_bool("/apps/gm-notify/play_sound")) |
968 | - if self.client.get_string("/apps/gm-notify/soundfile"): |
969 | - self.wTree.get_widget("fcbutton_sound").set_filename(self.client.get_string("/apps/gm-notify/soundfile")) |
970 | - self.on_checkbutton_sound_toggled(self.wTree.get_widget("checkbutton_sound")) |
971 | + self.wTree.get_object("checkbutton_sound").set_active(self.client.get_boolean("play-sound")) |
972 | + if self.client.get_string("soundfile"): |
973 | + self.wTree.get_object("fcbutton_sound").set_filename(self.client.get_string("soundfile")) |
974 | + self.on_checkbutton_sound_toggled(self.wTree.get_object("checkbutton_sound")) |
975 | |
976 | # ClickAction |
977 | - if self.client.get_bool("/apps/gm-notify/openclient"): |
978 | - self.wTree.get_widget("radiobutton_openclient").set_active(True) |
979 | + if self.client.get_boolean("openclient"): |
980 | + self.wTree.get_object("radiobutton_openclient").set_active(True) |
981 | else: |
982 | - self.wTree.get_widget("radiobutton_openweb").set_active(True) |
983 | + self.wTree.get_object("radiobutton_openweb").set_active(True) |
984 | |
985 | # Mailboxes |
986 | - mailboxes = self.client.get_list("/apps/gm-notify/mailboxes", gconf.VALUE_STRING) |
987 | - self.wTree.get_widget("checkbutton_inbox").set_active(self.client.get_bool("/apps/gm-notify/ignore_inbox")) |
988 | - self.wTree.get_widget("entry_labels").set_text(", ".join(mailboxes)) |
989 | + mailboxes = self.client.get_strv("mailboxes") |
990 | + self.wTree.get_object("checkbutton_inbox").set_active(self.client.get_boolean("ignore-inbox")) |
991 | + self.wTree.get_object("entry_labels").set_text(", ".join(mailboxes)) |
992 | |
993 | # Autorun |
994 | if os.path.exists("data/gm-notify.desktop"): |
995 | self.gm_notify_autostart_file = "data/gm-notify.desktop" |
996 | - elif os.path.exists("/usr/local/share/gm-notify/gm-notify.desktop"): |
997 | - self.gm_notify_autostart_file = "/usr/local/share/gm-notify/gm-notify.desktop" |
998 | - elif os.path.exists("/usr/share/gm-notify/gm-notify.desktop"): |
999 | - self.gm_notify_autostart_file = "/usr/share/gm-notify/gm-notify.desktop" |
1000 | + elif os.path.exists("/usr/local/share/applications/gm-notify.desktop"): |
1001 | + self.gm_notify_autostart_file = "/usr/local/share/applications/gm-notify.desktop" |
1002 | + elif os.path.exists("/usr/share/applications/gm-notify.desktop"): |
1003 | + self.gm_notify_autostart_file = "/usr/share/applications/gm-notify.desktop" |
1004 | self.autostart_file = os.path.expanduser("~/.config/autostart/gm-notify.desktop") |
1005 | - self.wTree.get_widget("checkbutton_autostart").set_active(os.path.exists(self.autostart_file)) |
1006 | + self.wTree.get_object("checkbutton_autostart").set_active(os.path.exists(self.autostart_file)) |
1007 | |
1008 | - signals = { "gtk_main_quit": self.terminate, |
1009 | - "on_button_apply_clicked": self.save, |
1010 | - "on_input_password_focus_out_event": self.check_credentials, |
1011 | - "on_checkbutton_sound_toggled": self.on_checkbutton_sound_toggled, |
1012 | - } |
1013 | - self.wTree.signal_autoconnect(signals) |
1014 | + # Connect signals |
1015 | + self.wTree.get_object("button_close").connect("clicked", self.terminate) |
1016 | + self.wTree.get_object("button_apply").connect("clicked", self.save) |
1017 | + self.wTree.get_object("input_password").connect("focus-out-event", self.check_credentials) |
1018 | + self.wTree.get_object("checkbutton_sound").connect("toggled", self.on_checkbutton_sound_toggled) |
1019 | |
1020 | def save(self, widget, data=None): |
1021 | '''saves the entered data and closes the app''' |
1022 | - |
1023 | - self.client.add_dir("/apps/gm-notify", gconf.CLIENT_PRELOAD_NONE) |
1024 | - |
1025 | # Credentials |
1026 | self.keys.delete_credentials() |
1027 | - self.keys.set_credentials(( self.wTree.get_widget("input_user").get_text(), |
1028 | - self.wTree.get_widget("input_password").get_text())) |
1029 | + self.keys.set_credentials(self.wTree.get_object("input_user").get_text(), |
1030 | + self.wTree.get_object("input_password").get_text()) |
1031 | |
1032 | # Mailboxes |
1033 | mailboxes = [] |
1034 | - for label in self.wTree.get_widget("entry_labels").get_text().split(","): |
1035 | + for label in self.wTree.get_object("entry_labels").get_text().split(","): |
1036 | mailboxes.append(label.strip()) |
1037 | - self.client.set_list("/apps/gm-notify/mailboxes", gconf.VALUE_STRING, mailboxes) |
1038 | - self.client.set_bool("/apps/gm-notify/ignore_inbox", self.wTree.get_widget("checkbutton_inbox").get_active()) |
1039 | + self.client.set_strv("mailboxes", mailboxes) |
1040 | + self.client.set_boolean("ignore-inbox", self.wTree.get_object("checkbutton_inbox").get_active()) |
1041 | |
1042 | # ClickAction |
1043 | - self.client.set_bool("/apps/gm-notify/openclient", self.wTree.get_widget("radiobutton_openclient").get_active()) |
1044 | + self.client.set_boolean("openclient", self.wTree.get_object("radiobutton_openclient").get_active()) |
1045 | |
1046 | # Soundfile |
1047 | - if self.wTree.get_widget("checkbutton_sound").get_active() and self.wTree.get_widget("fcbutton_sound").get_filename(): |
1048 | - self.client.set_bool("/apps/gm-notify/play_sound", True) |
1049 | - self.client.set_string("/apps/gm-notify/soundfile", str(self.wTree.get_widget("fcbutton_sound").get_filename())) |
1050 | + if self.wTree.get_object("checkbutton_sound").get_active() and self.wTree.get_object("fcbutton_sound").get_filename(): |
1051 | + self.client.set_boolean("play-sound", True) |
1052 | + self.client.set_string("soundfile", str(self.wTree.get_object("fcbutton_sound").get_filename())) |
1053 | else: |
1054 | - self.client.set_bool("/apps/gm-notify/play_sound", False) |
1055 | + self.client.set_boolean("play-sound", False) |
1056 | |
1057 | # Autorun |
1058 | - if self.wTree.get_widget("checkbutton_autostart").get_active(): |
1059 | + if self.wTree.get_object("checkbutton_autostart").get_active(): |
1060 | if not os.path.exists(self.autostart_file): |
1061 | try: |
1062 | os.makedirs(os.path.expanduser("~/.config/autostart")) |
1063 | @@ -163,13 +171,13 @@ |
1064 | shutil.copyfile(self.gm_notify_autostart_file, self.autostart_file) |
1065 | os.chmod(self.autostart_file, 0700) |
1066 | except IOError: |
1067 | - print "Warning: cannot write to path", self.autostart_file |
1068 | + print("Warning: cannot write to path", self.autostart_file) |
1069 | else: |
1070 | if os.path.exists(self.autostart_file): |
1071 | try: |
1072 | os.unlink(self.autostart_file) |
1073 | except: |
1074 | - print "Warning: cannot delete", self.autostart_file |
1075 | + print("Warning: cannot delete", self.autostart_file) |
1076 | |
1077 | # Start gm-notify itself |
1078 | subprocess.Popen(get_executable_path("gm-notify")) |
1079 | @@ -178,16 +186,16 @@ |
1080 | reactor.stop() |
1081 | |
1082 | def on_checkbutton_sound_toggled(self, widget): |
1083 | - self.wTree.get_widget("fcbutton_sound").set_sensitive(self.wTree.get_widget("checkbutton_sound").get_active()) |
1084 | + self.wTree.get_object("fcbutton_sound").set_sensitive(self.wTree.get_object("checkbutton_sound").get_active()) |
1085 | |
1086 | def check_credentials(self, widget, event, data=None): |
1087 | '''check if the given credentials are valid''' |
1088 | |
1089 | - input_user = self.wTree.get_widget("input_user") |
1090 | - input_password = self.wTree.get_widget("input_password") |
1091 | - image_credentials = self.wTree.get_widget("image_credentials") |
1092 | - label_credentials = self.wTree.get_widget("label_credentials") |
1093 | - button_apply = self.wTree.get_widget("button_apply") |
1094 | + input_user = self.wTree.get_object("input_user") |
1095 | + input_password = self.wTree.get_object("input_password") |
1096 | + image_credentials = self.wTree.get_object("image_credentials") |
1097 | + label_credentials = self.wTree.get_object("label_credentials") |
1098 | + button_apply = self.wTree.get_object("button_apply") |
1099 | button_apply.set_sensitive(False) |
1100 | |
1101 | # Change status text and disable input fields |
1102 | @@ -203,13 +211,13 @@ |
1103 | return False |
1104 | |
1105 | def credentials_valid(self): |
1106 | - input_user = self.wTree.get_widget("input_user") |
1107 | - input_password = self.wTree.get_widget("input_password") |
1108 | - image_credentials = self.wTree.get_widget("image_credentials") |
1109 | - label_credentials = self.wTree.get_widget("label_credentials") |
1110 | - button_apply = self.wTree.get_widget("button_apply") |
1111 | + input_user = self.wTree.get_object("input_user") |
1112 | + input_password = self.wTree.get_object("input_password") |
1113 | + image_credentials = self.wTree.get_object("image_credentials") |
1114 | + label_credentials = self.wTree.get_object("label_credentials") |
1115 | + button_apply = self.wTree.get_object("button_apply") |
1116 | |
1117 | - image_credentials.set_from_icon_name("gtk-yes", gtk.ICON_SIZE_MENU) |
1118 | + image_credentials.set_from_icon_name("gtk-yes", Gtk.IconSize.MENU) |
1119 | label_credentials.set_text(_("Valid credentials")) |
1120 | button_apply.set_sensitive(True) |
1121 | input_user.set_sensitive(True) |
1122 | @@ -218,12 +226,12 @@ |
1123 | self.api.die() |
1124 | |
1125 | def credentials_invalid(self): |
1126 | - input_user = self.wTree.get_widget("input_user") |
1127 | - input_password = self.wTree.get_widget("input_password") |
1128 | - image_credentials = self.wTree.get_widget("image_credentials") |
1129 | - label_credentials = self.wTree.get_widget("label_credentials") |
1130 | + input_user = self.wTree.get_object("input_user") |
1131 | + input_password = self.wTree.get_object("input_password") |
1132 | + image_credentials = self.wTree.get_object("image_credentials") |
1133 | + label_credentials = self.wTree.get_object("label_credentials") |
1134 | |
1135 | - image_credentials.set_from_icon_name("gtk-stop", gtk.ICON_SIZE_MENU) |
1136 | + image_credentials.set_from_icon_name("gtk-stop", Gtk.IconSize.MENU) |
1137 | label_credentials.set_text(_("Invalid credentials")) |
1138 | input_user.set_sensitive(True) |
1139 | input_password.set_sensitive(True) |
1140 | @@ -231,4 +239,5 @@ |
1141 | self.api.die() |
1142 | |
1143 | t = Window() |
1144 | +reactor.registerGApplication(t) |
1145 | reactor.run() |
1146 | |
1147 | === modified file 'gm_notify_keyring.py' |
1148 | --- gm_notify_keyring.py 2010-05-05 17:31:35 +0000 |
1149 | +++ gm_notify_keyring.py 2013-03-25 04:23:21 +0000 |
1150 | @@ -1,43 +1,59 @@ |
1151 | +from __future__ import print_function |
1152 | + |
1153 | __version__ = "$Revision: 14294 $" |
1154 | |
1155 | -import gtk # ensure that the application name is correctly set |
1156 | -import gnomekeyring as gkey |
1157 | - |
1158 | +from gi.repository import GnomeKeyring, Gtk |
1159 | + |
1160 | +def attributes(d): |
1161 | + '''Converts a dictionary to a GnomeKeyring.Attribute array''' |
1162 | + attrs = GnomeKeyring.Attribute.list_new() |
1163 | + for key in d: |
1164 | + GnomeKeyring.Attribute.list_append_string(attrs, key, str(d[key])) |
1165 | + return attrs |
1166 | + |
1167 | +def dict_from_attributes(attrs): |
1168 | + '''Converts item results back into a dictionary''' |
1169 | + result = {} |
1170 | + for attr in GnomeKeyring.Attribute.list_to_glist(attrs): |
1171 | + result[attr.name] = attr.get_string() |
1172 | + return result |
1173 | + |
1174 | +class KeyringException(Exception): |
1175 | + pass |
1176 | |
1177 | class Keyring(object): |
1178 | def __init__(self, name, server, protocol): |
1179 | self._name = name |
1180 | self._server = server |
1181 | self._protocol = protocol |
1182 | - self._keyring = gkey.get_default_keyring_sync() |
1183 | + result, self._keyring = GnomeKeyring.get_default_keyring_sync() |
1184 | |
1185 | def has_credentials(self): |
1186 | - try: |
1187 | - attrs = {"server": self._server, "protocol": self._protocol} |
1188 | - items = gkey.find_items_sync(gkey.ITEM_NETWORK_PASSWORD, attrs) |
1189 | - return len(items) > 0 |
1190 | - except (gkey.DeniedError, gkey.NoMatchError): |
1191 | + attrs = attributes({"server": self._server, "protocol": self._protocol}) |
1192 | + result, items = GnomeKeyring.find_items_sync(GnomeKeyring.ItemType.NETWORK_PASSWORD, attrs) |
1193 | + if result in (GnomeKeyring.Result.NO_MATCH, GnomeKeyring.Result.DENIED): |
1194 | return False |
1195 | + return len(items) > 0 |
1196 | |
1197 | def get_credentials(self): |
1198 | - attrs = {"server": self._server, "protocol": self._protocol} |
1199 | - items = gkey.find_items_sync(gkey.ITEM_NETWORK_PASSWORD, attrs) |
1200 | - return (items[0].attributes["user"], items[0].secret) |
1201 | + attrs = attributes({"server": self._server, "protocol": self._protocol}) |
1202 | + result, items = GnomeKeyring.find_items_sync(GnomeKeyring.ItemType.NETWORK_PASSWORD, attrs) |
1203 | + if len(items) == 0: |
1204 | + raise KeyringException("Credentials not found") |
1205 | + d = dict_from_attributes(items[0].attributes) |
1206 | + return (d["user"], items[0].secret) |
1207 | |
1208 | def delete_credentials(self): |
1209 | - attrs = {"server": self._server, "protocol": self._protocol} |
1210 | - try: |
1211 | - items = gkey.find_items_sync(gkey.ITEM_NETWORK_PASSWORD, attrs) |
1212 | - for item in items: |
1213 | - gkey.item_delete_sync(None, item.item_id) |
1214 | - except (gkey.DeniedError, gkey.NoMatchError): |
1215 | - pass |
1216 | + attrs = attributes({"server": self._server, "protocol": self._protocol}) |
1217 | + result, items = GnomeKeyring.find_items_sync(GnomeKeyring.ItemType.NETWORK_PASSWORD, attrs) |
1218 | + for item in items: |
1219 | + GnomeKeyring.item_delete_sync(self._keyring, item.item_id) |
1220 | |
1221 | - def set_credentials(self, (user, pw)): |
1222 | - attrs = { |
1223 | + def set_credentials(self, user, pw): |
1224 | + attrs = attributes({ |
1225 | "user": user, |
1226 | "server": self._server, |
1227 | "protocol": self._protocol, |
1228 | - } |
1229 | - gkey.item_create_sync(gkey.get_default_keyring_sync(), |
1230 | - gkey.ITEM_NETWORK_PASSWORD, self._name, attrs, pw, True) |
1231 | + }) |
1232 | + GnomeKeyring.item_create_sync(self._keyring, |
1233 | + GnomeKeyring.ItemType.NETWORK_PASSWORD, self._name, attrs, pw, True) |
1234 | |
1235 | === modified file 'gtalk.py' |
1236 | --- gtalk.py 2010-09-18 13:06:25 +0000 |
1237 | +++ gtalk.py 2013-03-25 04:23:21 +0000 |
1238 | @@ -19,17 +19,19 @@ |
1239 | # You should have received a copy of the GNU General Public License |
1240 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
1241 | # |
1242 | +from __future__ import print_function |
1243 | + |
1244 | from threading import Event |
1245 | |
1246 | from twisted.words.protocols.jabber import xmlstream, client, jid |
1247 | from twisted.words.xish import domish |
1248 | -from twisted.internet import reactor, task |
1249 | +from twisted.internet import reactor, task, error |
1250 | |
1251 | _DEBUG = False |
1252 | COLOR_GREEN = "\033[92m" |
1253 | COLOR_END = "\033[0m" |
1254 | def DEBUG(msg): |
1255 | - if _DEBUG: print COLOR_GREEN + str(msg) + COLOR_END |
1256 | + if _DEBUG: print(COLOR_GREEN + str(msg) + COLOR_END) |
1257 | |
1258 | class GTalkClientFactory(xmlstream.XmlStreamFactory): |
1259 | def __init__(self, jid, password): |
1260 | @@ -89,7 +91,11 @@ |
1261 | self.connector.disconnect() # Our reconnecting factory will try the reconnecting |
1262 | |
1263 | def send_callback_handler(self, data, callback=None, **kargs): |
1264 | - self.timeout_call_id.cancel() |
1265 | + try: |
1266 | + self.timeout_call_id.cancel() |
1267 | + except error.AlreadyCalled: |
1268 | + DEBUG("already called timeout_call_id.cancel()") |
1269 | + return |
1270 | if callback: |
1271 | callback(data, **kargs) |
1272 | else: |
1273 | @@ -242,10 +248,10 @@ |
1274 | if iq: self.queryInbox() |
1275 | |
1276 | def rawDataIn(self, buf): |
1277 | - print u"< %s" % unicode(buf, "utf-8") |
1278 | + print(u"< %s" % unicode(buf, "utf-8")) |
1279 | |
1280 | def rawDataOut(self, buf): |
1281 | - print u"> %s" % unicode(buf, "utf-8") |
1282 | + print(u"> %s" % unicode(buf, "utf-8")) |
1283 | |
1284 | def connectedCB(self, xmlstream): |
1285 | self.xmlstream = xmlstream |
1286 | |
1287 | === modified file 'setup.py' |
1288 | --- setup.py 2010-09-18 13:06:25 +0000 |
1289 | +++ setup.py 2013-03-25 04:23:21 +0000 |
1290 | @@ -10,11 +10,10 @@ |
1291 | py_modules=['gtalk', 'gm_notify_keyring'], |
1292 | scripts=['gm-notify', 'gm-notify-config'], |
1293 | data_files=[('/usr/share/applications', ['data/gm-notify-config.desktop']), |
1294 | - ('/usr/share/indicators/messages/applications', ['data/gm-notify']), |
1295 | - ('/usr/share/gm-notify', ['data/gm-notify.desktop']), |
1296 | + ('/usr/share/applications', ['data/gm-notify.desktop']), |
1297 | ('/usr/share/gm-notify', ['data/checking.gif']), |
1298 | - ('/usr/share/gm-notify', ['gm-config.glade']), |
1299 | - ('/etc/gconf/schemas', ['data/gm-notify.schemas']), |
1300 | + ('/usr/share/gm-notify', ['gm-config.ui']), |
1301 | + ('/usr/share/glib-2.0/schemas', ['data/net.launchpad.gm-notify.gschema.xml']), |
1302 | ('/usr/share/locale/da/LC_MESSAGES', ['po/da/gm-notify.mo']), |
1303 | ('/usr/share/locale/bg/LC_MESSAGES', ['po/bg/gm-notify.mo']), |
1304 | ('/usr/share/locale/de/LC_MESSAGES', ['po/de/gm-notify.mo']), |
This looks very good, I'm considering to upload this into Ubuntu Archive, as it has MessagingMenu support, among many other improvements.