Add v0.0.6 of Hermes from source tarball
[hermes] / package / src / gui.py
1 #!/usr/bin/env python
2
3 import gtk, gobject
4 import gnome.gconf
5 import hildon, osso
6 import traceback
7 import time
8 import thread
9 import contactview
10 from hermes import Hermes
11
12 gobject.threads_init()
13
14 class HermesGUI:
15   """Provides the GUI for Hermes, allowing the syncing of Facebook and
16      Twitter friends' information with the Evolution contacts' database.
17        
18      Copyright (c) Andrew Flegg <andrew@bleb.org> 2009.
19      Released under the Artistic Licence."""
20
21
22   # -----------------------------------------------------------------------
23   def __init__(self):
24     """Constructor. Initialises the gconf connection."""
25     self.gc = gnome.gconf.client_get_default()
26
27
28   # -----------------------------------------------------------------------
29   def doSync(self, widget, force, main = True):
30     if main and not self.get_use_facebook() and not self.get_use_twitter():
31       saved = self.open_prefs()
32       if saved == gtk.RESPONSE_DELETE_EVENT:
33         return
34
35     if main:
36       self.window.set_property('sensitive', False)
37       thread.start_new_thread(self.doSync, (widget, force, False))
38     else:
39       try:
40         fb2c = Hermes(self,
41                       twitter = (self.get_use_twitter() and self.get_twitter_credentials()) or None,
42                       facebook = self.get_use_facebook())
43         fb2c.load_friends()
44         fb2c.sync_contacts(resync = force)
45         gobject.idle_add(self.open_summary, fb2c)
46       except Exception, e:
47         traceback.print_exc()
48         gobject.idle_add(self.report_error, 'Something went wrong: ' + e.message)
49
50
51   # -----------------------------------------------------------------------
52   def open_summary(self, fb2c):
53     gobject.idle_add(self.window.set_property, 'sensitive', True)
54
55     dialog = gtk.Dialog('Summary', self.window)
56     dialog.add_button('Done', gtk.RESPONSE_OK)
57     
58     button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
59                            title = 'Updated %d contacts' % (len(fb2c.updated)))
60     button.connect('clicked', self.show_contacts, fb2c.updated)
61     button.set_property('sensitive', len(fb2c.updated) > 0)
62     dialog.vbox.add(button)
63     
64     button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
65                            title = 'Matched %d contacts' % (len(fb2c.matched)))
66     button.connect('clicked', self.show_contacts, fb2c.matched)
67     button.set_property('sensitive', len(fb2c.matched) > 0)
68     dialog.vbox.add(button)
69     
70     button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
71                            title = '%d contacts unmatched' % (len(fb2c.unmatched)))
72     button.connect('clicked', self.show_contacts, fb2c.unmatched)
73     button.set_property('sensitive', len(fb2c.unmatched) > 0)
74     dialog.vbox.add(button)
75     
76     dialog.show_all()
77     dialog.run()
78     dialog.hide()
79   
80
81   # -----------------------------------------------------------------------
82   def show_contacts(self, widget, contacts):
83     view = contactview.ContactView(contacts)
84
85     dialog = gtk.Dialog('Contacts', self.window)
86     #view.connect('contact-activated', self.map_contact)
87     dialog.vbox.add(view)
88     dialog.show_all()
89     
90     dialog.run()
91     dialog.hide()
92     
93     
94   # -----------------------------------------------------------------------
95   def map_contact(self, widget, contact):
96     print widget, contact
97
98
99   # -----------------------------------------------------------------------
100   def open_prefs(self, widget = None):
101     dialog = gtk.Dialog('Accounts', self.window)
102     dialog.add_button('Save', gtk.RESPONSE_OK)
103
104     use_facebook = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
105     use_facebook.set_label('Use Facebook')
106     use_facebook.set_active(self.get_use_facebook())
107     dialog.vbox.add(use_facebook)
108
109     use_twitter = hildon.CheckButton(gtk.HILDON_SIZE_FINGER_HEIGHT)
110     use_twitter.set_label('Use Twitter')
111     use_twitter.set_active(self.get_use_twitter())
112     dialog.vbox.add(use_twitter)
113
114     tw_indent = gtk.HBox()
115     tw_user = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
116     tw_user.set_property('hildon-input-mode', gtk.HILDON_GTK_INPUT_MODE_FULL)
117     tw_user.set_placeholder("Username")
118     tw_user.set_property('is-focus', False)
119     tw_user.set_text(self.get_twitter_credentials()[0])
120     self.sync_edit(use_twitter, tw_user)
121     use_twitter.connect('toggled', self.sync_edit, tw_user)
122     tw_indent.pack_start(tw_user, padding=48)
123     dialog.vbox.add(tw_indent)
124
125     tw_indent = gtk.HBox()
126     tw_pass = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
127     tw_pass.set_placeholder("Password")
128     tw_pass.set_property('hildon-input-mode', gtk.HILDON_GTK_INPUT_MODE_FULL |
129                                               gtk.HILDON_GTK_INPUT_MODE_INVISIBLE)
130     tw_pass.set_text(self.get_twitter_credentials()[1])
131     self.sync_edit(use_twitter, tw_pass)
132     use_twitter.connect('toggled', self.sync_edit, tw_pass)
133     tw_indent.pack_start(tw_pass, padding=48)
134     dialog.vbox.add(tw_indent)
135
136     dialog.show_all()
137     result = dialog.run()
138     dialog.hide()
139     if result == gtk.RESPONSE_OK:
140       self.set_use_facebook(use_facebook.get_active())
141       self.set_use_twitter(use_twitter.get_active(), tw_user.get_text(), tw_pass.get_text())
142
143     return result
144     
145     
146   # -----------------------------------------------------------------------
147   def sync_edit(self, use_twitter, edit):
148     edit.set_property('sensitive', use_twitter.get_active())
149
150
151   # -----------------------------------------------------------------------
152   def need_auth(self, main = False):
153     if main:
154       hildon.hildon_banner_show_information(self.window, '', "Need to authenticate with Facebook")
155     else:
156       gobject.idle_add(self.need_auth, True)
157     
158
159   # -----------------------------------------------------------------------
160   def block_for_auth(self, main = False, lock = None):
161     if main:
162       note = gtk.Dialog('Facebook authorisation', self.window)
163       note.add_button("Validate", gtk.RESPONSE_OK)
164       note.vbox.add(gtk.Label("\nPress 'Validate' once Facebook has\nbeen authenticated in web browser.\n"))
165
166       note.show_all()
167       result = note.run()
168       note.hide()
169       lock.release()
170       
171     else:
172       time.sleep(2)
173       lock = thread.allocate_lock()
174       lock.acquire()
175       gobject.idle_add(self.block_for_auth, True, lock)
176       lock.acquire()
177       lock.release()
178
179
180   # -----------------------------------------------------------------------
181   def progress(self, i, j, main = False):
182     if main:
183       if i == 0:
184         self.progressbar = gtk.ProgressBar()
185         self.progressnote = gtk.Dialog("Fetching friends' info", self.window)
186         self.progressnote.vbox.add(self.progressbar)
187         hildon.hildon_gtk_window_set_progress_indicator(self.progressnote, 1)
188         
189         self.progressnote.show_all()
190         
191       elif i < j:
192         if i == 1:
193           self.progressnote.set_title("Updating contacts")
194           hildon.hildon_gtk_window_set_progress_indicator(self.progressnote, 0)
195           
196         self.progressbar.set_fraction(float(i) / float(j))
197         
198       else:
199         self.progressnote.destroy()
200         
201       print i,j
202     else:
203       gobject.idle_add(self.progress, i, j, True)
204
205
206   # -----------------------------------------------------------------------
207   def report_error(self, e):
208     hildon.hildon_banner_show_information(self.window, '', e)
209
210
211   # -----------------------------------------------------------------------
212   def main(self):
213     # -- Window and app...
214     #
215     self.app = hildon.Program()
216     self.window = hildon.Window()
217     gtk.set_application_name('Hermes')
218     self.osso_context = osso.Context('org.maemo.hermes', '0.0.5', False)
219     self.app.add_window(self.window)
220
221     self.window.connect("delete-event", gtk.main_quit)
222
223     # -- Main window buttons...
224     #
225     box = gtk.HButtonBox()
226     self.window.add(box)
227     
228     box.set_property('layout-style', gtk.BUTTONBOX_SPREAD)
229     button = hildon.Button(gtk.HILDON_SIZE_THUMB_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
230                            title = 'Retrieve', value = "Get contacts' missing info")
231     button.set_property('width-request', 250)
232     button.connect('clicked', self.doSync, False)
233     box.add(button)
234
235     button = hildon.Button(gtk.HILDON_SIZE_THUMB_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
236                            title = 'Update', value = "Update contacts' info")
237     button.set_property('width-request', 250)
238     button.connect('clicked', self.doSync, True)
239     box.add(button)
240     
241     # -- Application menu...
242     #
243     menu = hildon.AppMenu()
244     button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
245     button.set_label("Accounts")
246     button.connect("clicked", self.open_prefs)
247     menu.append(button)
248     menu.show_all()
249     self.window.set_app_menu(menu)
250   
251     self.window.show_all()
252     gtk.main()
253
254
255   def get_use_facebook(self):
256     return self.gc.get_bool("/apps/maemo/hermes/use_facebook")
257
258
259   def set_use_facebook(self, value):
260     self.gc.set_bool("/apps/maemo/hermes/use_facebook", value)
261
262
263   def get_use_twitter(self):
264     return self.gc.get_bool("/apps/maemo/hermes/use_twitter")
265
266
267   def set_use_twitter(self, value, user, password):
268     self.gc.set_bool("/apps/maemo/hermes/use_twitter", value)
269     self.gc.set_string("/apps/maemo/hermes/twitter_user", user)
270     self.gc.set_string("/apps/maemo/hermes/twitter_pwd", password)
271     
272   
273   def get_twitter_credentials(self):
274     return (self.gc.get_string("/apps/maemo/hermes/twitter_user") or '',
275             self.gc.get_string("/apps/maemo/hermes/twitter_pwd") or '')
276
277
278 # -------------------------------------------------------------------------
279 if __name__ == '__main__':
280   HermesGUI().main()
281