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