Add preferences UI for Facebook. Tidy up lose ends related to this;
[hermes] / package / src / org / maemo / hermes / gui / gtkui.py
1 import gettext
2 import gtk, gobject
3 import traceback
4 import time
5 import thread
6 import urllib2
7 import hildon
8 from org.bleb.wimpworks import WimpWorks
9 from org.maemo.hermes.gui.contactview import ContactView
10 from org.maemo.hermes.gui.mapcontact import MapContact
11 from org.maemo.hermes.gui.accountsdialogue import AccountsDialogue
12 from org.bleb.wimpworks import HildonMainScreenLayout
13 #from hermes import Hermes ### FIXME This needs to be new
14
15 class HermesGUI(WimpWorks):
16     """Provides the GUI for Hermes, allowing the syncing of Facebook and
17        Twitter friends' information with the Evolution contacts' database.
18        
19        Copyright (c) Andrew Flegg <andrew@bleb.org> 2009.
20        Released under the Artistic Licence."""
21
22
23     # -----------------------------------------------------------------------
24     def __init__(self, providers = None):
25         gettext.install('hermes','/opt/hermes/share/locale/')
26         WimpWorks.__init__(self, 'Hermes', version = '0.9.0', dbus_name = 'org.maemo.hermes')
27         self.set_background('background.png')
28         
29         layout = HildonMainScreenLayout(offset = 0.8, container = self)
30         layout.add_button('Retrieve', _("Get contacts' missing info"))
31         layout.add_button('Refresh', _("Update contacts' info"))
32         
33         self.add_menu_action("Accounts")
34         self.menu.show_all()
35         
36         self.providers = providers
37         self.progressnote = None
38
39   
40     # -----------------------------------------------------------------------
41     def do_retrieve(self, widget):
42         self.sync(widget, False)
43     
44     
45     # -----------------------------------------------------------------------
46     def do_refresh(self, widget):
47         self.sync(widget, True)
48
49
50     # -----------------------------------------------------------------------
51     def do_accounts(self, widget = None):
52         dialog = AccountsDialogue(self.main_window, self.providers)
53         dialog.show()
54    
55
56     # -----------------------------------------------------------------------
57     def sync(self, widget, force, main = True):
58         enabled = []
59         for provider in self.providers:
60             if self.gconf.get_bool('/apps/maemo/hermes/use_%s' % (provider.get_id())):
61                 enabled.append(provider)
62                 
63         if main and len(enabled) == 0:
64             saved = self.do_accounts()
65             if saved == gtk.RESPONSE_DELETE_EVENT:
66                 return
67         
68         if main:
69             self.main_window.set_property('sensitive', False)
70             thread.start_new_thread(self.sync, (widget, force, False))
71         else:
72             try:
73                 services = []
74                 for provider in enabled:
75                     services.append(provider.service(self))
76                     
77                 print services
78                 raise Exception("TODO - implement syncing")
79         
80             except urllib2.HTTPError, e:
81                 traceback.print_exc()
82                 if e.code == 401:
83                     gobject.idle_add(self.report_error, _('Authentication problem. Check credentials.'), True)
84                 else:
85                     gobject.idle_add(self.report_error, _('Network connection error. Check connectivity.'))
86         
87             except urllib2.URLError, e:
88                 traceback.print_exc()
89                 gobject.idle_add(self.report_error, _('Network connection error. Check connectivity.'))
90           
91             except Exception, e:
92                 traceback.print_exc()
93                 gobject.idle_add(self.report_error, _('Something went wrong: ') + e.message)
94     
95     
96     # -----------------------------------------------------------------------
97     def open_summary(self, fb2c):
98         gobject.idle_add(self.main_window.set_property, 'sensitive', True)
99     
100         dialog = gtk.Dialog(_('Summary'), self.main_window)
101         dialog.add_button(_('Done'), gtk.RESPONSE_OK)
102       
103         button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
104                                title = _('Updated %d contacts') % (len(fb2c.updated)))
105         button.connect('clicked', self.show_contacts, fb2c, fb2c.updated)
106         button.set_property('sensitive', len(fb2c.updated) > 0)
107         dialog.vbox.add(button)
108         
109         button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
110                                title = _('Matched %d contacts') % (len(fb2c.matched)))
111         button.connect('clicked', self.show_contacts, fb2c, fb2c.matched)
112         button.set_property('sensitive', len(fb2c.matched) > 0)
113         dialog.vbox.add(button)
114       
115         button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
116                                title = _('%d contacts unmatched') % (len(fb2c.unmatched)))
117         button.connect('clicked', self.show_contacts, fb2c, fb2c.unmatched)
118         button.set_property('sensitive', len(fb2c.unmatched) > 0)
119         dialog.vbox.add(button)
120       
121         dialog.show_all()
122         dialog.run()
123         dialog.hide()
124     
125     
126     # -----------------------------------------------------------------------
127     def show_contacts(self, widget, fb2c, contacts):
128         view = ContactView(contacts)
129     
130         dialog = gtk.Dialog(_('Contacts'), self.main_window)
131         view.connect('contact-activated', self.map_contact, fb2c)
132         dialog.vbox.add(view)
133         dialog.show_all()
134       
135         dialog.run()
136         dialog.hide()
137       
138       
139     # -----------------------------------------------------------------------
140     def map_contact(self, widget, contact, fb2c):
141         view = MapContact(fb2c.friends, contact)
142     
143         dialog = gtk.Dialog(contact.get_name(), self.main_window)
144         dialog.add_button(_('Update'), gtk.RESPONSE_OK)
145         dialog.vbox.add(view)
146         dialog.show_all()
147       
148         result = dialog.run()
149         dialog.hide()
150         if result == gtk.RESPONSE_OK:
151             friend = view.get_selected_friend()
152             if friend:
153                 if 'contact' in friend and friend['contact'] == contact:
154                     hildon.hildon_banner_show_information(self.main_window, '', _("Removing existing mappings is not yet supported"))
155                 elif view.contact_mapped:
156                     if fb2c.update_contact(contact, friend, True):
157                         fb2c.addresses.commit_contact(contact)
158                 else:
159                     if fb2c.update_contact(contact, friend, False):
160                         fb2c.addresses.commit_contact(contact)
161     
162                         
163     # -----------------------------------------------------------------------
164     def need_auth(self, main = False):
165         """Part of the GUI callback API."""
166         
167         if main:
168             hildon.hildon_banner_show_information(self.main_window, '', _("Need to authenticate with Facebook"))
169         else:
170             gobject.idle_add(self.need_auth, True)
171       
172     
173     # -----------------------------------------------------------------------
174     def block_for_auth(self, main = False, lock = None):
175         """Part of the GUI callback API."""
176
177         if main:
178             note = gtk.Dialog(_('Facebook authorisation'), self.main_window)
179             note.add_button(_("Validate"), gtk.RESPONSE_OK)
180             note.vbox.add(gtk.Label(_("\nPress 'Validate' once Facebook has\nbeen authenticated in web browser.\n")))
181     
182             note.show_all()
183             result = note.run()
184             note.hide()
185             lock.release()
186         
187         else:
188             time.sleep(2)
189             lock = thread.allocate_lock()
190             lock.acquire()
191             gobject.idle_add(self.block_for_auth, True, lock)
192             lock.acquire()
193             lock.release()
194                       
195                         
196     # -----------------------------------------------------------------------
197     def progress(self, i, j, main = False):
198         """Part of the GUI callback API."""
199
200         if main:
201             if i == 0:
202                 self.progressbar = gtk.ProgressBar()
203                 self.progressnote = gtk.Dialog(_("Fetching friends' info"), self.main_window)
204                 self.progressnote.vbox.add(self.progressbar)
205                 hildon.hildon_gtk_window_set_progress_indicator(self.progressnote, 1)
206                
207                 self.progressnote.show_all()
208               
209             elif i < j:
210                 if i == 1:
211                     self.progressnote.set_title(_("Updating contacts"))
212                     hildon.hildon_gtk_window_set_progress_indicator(self.progressnote, 0)
213                 
214                 self.progressbar.set_fraction(float(i) / float(j))
215               
216             else:
217                 self.progressnote.destroy()
218               
219             print i,j
220         else:
221             gobject.idle_add(self.progress, i, j, True)
222
223        
224     # -----------------------------------------------------------------------
225     def report_error(self, e, prefs = False):
226         if self.progressnote:
227             self.main_window.set_property('sensitive', True)
228             self.progressnote.destroy()
229     
230         hildon.hildon_banner_show_information(self.main_window, '', e)
231         if prefs:
232             self.do_accounts()