Update PyDev project to run in ESBox and allow `import gtk' to work in
[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 from org.maemo.hermes.gui.contactview import ContactView
7 import urllib2
8 import hildon
9 from org.bleb.wimpworks import WimpWorks
10 from org.maemo.hermes.gui.mapcontact import MapContact
11 from org.bleb.wimpworks import HildonMainScreenLayout
12 #from hermes import Hermes ### FIXME This needs to be new
13
14 class HermesGUI(WimpWorks):
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         gettext.install('hermes','/opt/hermes/share/locale/')
25         WimpWorks.__init__(self, 'Hermes', version = '0.2.0', dbus_name = 'org.maemo.hermes')
26         self.set_background('background.png')
27         
28         layout = HildonMainScreenLayout(offset = 0.8, container = self)
29         layout.add_button('Retrieve', _("Get contacts' missing info"))
30         layout.add_button('Refresh', _("Update contacts' info"))
31         
32         self.add_menu_action("Accounts")
33         self.menu.show_all()
34
35   
36     # -----------------------------------------------------------------------
37     def do_retrieve(self, widget):
38         self.sync(widget, False)
39     
40     
41     # -----------------------------------------------------------------------
42     def do_refresh(self, widget):
43         self.sync(widget, True)
44
45
46     # -----------------------------------------------------------------------
47     def do_accounts(self, widget = None):
48         dialog = gtk.Dialog(_('Accounts'), self.main_window)
49         dialog.add_button(_('Save'), gtk.RESPONSE_OK)
50         
51         #pa = hildon.PannableArea()
52         #dialog.vbox.add(pa)
53         content = dialog.vbox 
54         #content = gtk.VBox()
55         #pa.add(content)
56         #pa.set_size_request(600, 380)
57         
58         use_facebook = self.new_checkbox(_('Use Facebook'), content)
59         use_facebook.set_active(self.get_use_facebook())
60         
61         indent = self.new_indent(content)
62         self.link_control(use_facebook, gtk.Label(_('Note: authentication via web page')), indent)
63         
64         fb_empty = self.link_control(use_facebook, self.new_checkbox(_('Create birthday-only contacts')), indent)
65         fb_empty.set_active(self.get_create_empty())
66         
67         use_twitter = self.new_checkbox(_('Use Twitter'), content)
68         use_twitter.set_active(self.get_use_twitter())
69         
70         indent = self.new_indent(content)
71         tw_user = self.link_control(use_twitter, self.new_input(_('Twitter username')), indent)
72         tw_user.set_text(self.get_twitter_credentials()[0])
73         
74         tw_pass = self.link_control(use_twitter, self.new_input(_('Twitter password'), password = True), indent)
75         tw_pass.set_text(self.get_twitter_credentials()[1])
76         
77         dialog.show_all()
78         result = dialog.run()
79         dialog.hide()
80         if result == gtk.RESPONSE_OK:
81             self.set_use_facebook(use_facebook.get_active())
82             self.set_create_empty(fb_empty.get_active())
83             self.set_use_twitter(use_twitter.get_active(), tw_user.get_text(), tw_pass.get_text())
84         
85         return result
86    
87
88     # -----------------------------------------------------------------------
89     def sync(self, widget, force, main = True):
90         if main and not self.get_use_facebook() and not self.get_use_twitter():
91             saved = self.do_accounts()
92             if saved == gtk.RESPONSE_DELETE_EVENT:
93                 return
94         
95         if main:
96             self.main_window.set_property('sensitive', False)
97             thread.start_new_thread(self.sync, (widget, force, False))
98         else:
99             try:
100                 fb2c = Hermes(self,
101                               twitter = (self.get_use_twitter() and self.get_twitter_credentials()) or None,
102                               facebook = self.get_use_facebook(),
103                               empty = self.get_create_empty())
104                 fb2c.load_friends()
105                 fb2c.sync_contacts(resync = force)
106                 gobject.idle_add(self.open_summary, fb2c)
107         
108             except urllib2.HTTPError, e:
109                 traceback.print_exc()
110                 if e.code == 401:
111                     gobject.idle_add(self.report_error, _('Authentication problem. Check credentials.'), True)
112                 else:
113                     gobject.idle_add(self.report_error, _('Network connection error. Check connectivity.'))
114         
115             except urllib2.URLError, e:
116                 traceback.print_exc()
117                 gobject.idle_add(self.report_error, _('Network connection error. Check connectivity.'))
118           
119             except Exception, e:
120                 traceback.print_exc()
121                 gobject.idle_add(self.report_error, _('Something went wrong: ') + e.message)
122     
123     
124     # -----------------------------------------------------------------------
125     def open_summary(self, fb2c):
126         gobject.idle_add(self.main_window.set_property, 'sensitive', True)
127     
128         dialog = gtk.Dialog(_('Summary'), self.main_window)
129         dialog.add_button(_('Done'), gtk.RESPONSE_OK)
130       
131         button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
132                                title = _('Updated %d contacts') % (len(fb2c.updated)))
133         button.connect('clicked', self.show_contacts, fb2c, fb2c.updated)
134         button.set_property('sensitive', len(fb2c.updated) > 0)
135         dialog.vbox.add(button)
136         
137         button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
138                                title = _('Matched %d contacts') % (len(fb2c.matched)))
139         button.connect('clicked', self.show_contacts, fb2c, fb2c.matched)
140         button.set_property('sensitive', len(fb2c.matched) > 0)
141         dialog.vbox.add(button)
142       
143         button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
144                                title = _('%d contacts unmatched') % (len(fb2c.unmatched)))
145         button.connect('clicked', self.show_contacts, fb2c, fb2c.unmatched)
146         button.set_property('sensitive', len(fb2c.unmatched) > 0)
147         dialog.vbox.add(button)
148       
149         dialog.show_all()
150         dialog.run()
151         dialog.hide()
152     
153     
154     # -----------------------------------------------------------------------
155     def show_contacts(self, widget, fb2c, contacts):
156         view = ContactView(contacts)
157     
158         dialog = gtk.Dialog(_('Contacts'), self.main_window)
159         view.connect('contact-activated', self.map_contact, fb2c)
160         dialog.vbox.add(view)
161         dialog.show_all()
162       
163         dialog.run()
164         dialog.hide()
165       
166       
167     # -----------------------------------------------------------------------
168     def map_contact(self, widget, contact, fb2c):
169         view = MapContact(fb2c.friends, contact)
170     
171         dialog = gtk.Dialog(contact.get_name(), self.main_window)
172         dialog.add_button(_('Update'), gtk.RESPONSE_OK)
173         dialog.vbox.add(view)
174         dialog.show_all()
175       
176         result = dialog.run()
177         dialog.hide()
178         if result == gtk.RESPONSE_OK:
179             friend = view.get_selected_friend()
180             if friend:
181                 if 'contact' in friend and friend['contact'] == contact:
182                     hildon.hildon_banner_show_information(self.main_window, '', _("Removing existing mappings is not yet supported"))
183                 elif view.contact_mapped:
184                     if fb2c.update_contact(contact, friend, True):
185                         fb2c.addresses.commit_contact(contact)
186                 else:
187                     if fb2c.update_contact(contact, friend, False):
188                         fb2c.addresses.commit_contact(contact)
189     
190       
191     # -----------------------------------------------------------------------
192     def need_auth(self, main = False):
193         if main:
194             hildon.hildon_banner_show_information(self.main_window, '', _("Need to authenticate with Facebook"))
195         else:
196             gobject.idle_add(self.need_auth, True)
197       
198     
199     # -----------------------------------------------------------------------
200     def block_for_auth(self, main = False, lock = None):
201         if main:
202             note = gtk.Dialog(_('Facebook authorisation'), self.main_window)
203             note.add_button(_("Validate"), gtk.RESPONSE_OK)
204             note.vbox.add(gtk.Label(_("\nPress 'Validate' once Facebook has\nbeen authenticated in web browser.\n")))
205     
206             note.show_all()
207             result = note.run()
208             note.hide()
209             lock.release()
210         
211         else:
212             time.sleep(2)
213             lock = thread.allocate_lock()
214             lock.acquire()
215             gobject.idle_add(self.block_for_auth, True, lock)
216             lock.acquire()
217             lock.release()
218     
219     
220     # -----------------------------------------------------------------------
221     def progress(self, i, j, main = False):
222         if main:
223             if i == 0:
224                 self.progressbar = gtk.ProgressBar()
225                 self.progressnote = gtk.Dialog(_("Fetching friends' info"), self.main_window)
226                 self.progressnote.vbox.add(self.progressbar)
227                 hildon.hildon_gtk_window_set_progress_indicator(self.progressnote, 1)
228                
229                 self.progressnote.show_all()
230               
231             elif i < j:
232                 if i == 1:
233                     self.progressnote.set_title(_("Updating contacts"))
234                     hildon.hildon_gtk_window_set_progress_indicator(self.progressnote, 0)
235                 
236                 self.progressbar.set_fraction(float(i) / float(j))
237               
238             else:
239                 self.progressnote.destroy()
240               
241             print i,j
242         else:
243             gobject.idle_add(self.progress, i, j, True)
244     
245     
246     # -----------------------------------------------------------------------
247     def report_error(self, e, prefs = False):
248         if self.progressnote:
249             self.main_window.set_property('sensitive', True)
250             self.progressnote.destroy()
251     
252         hildon.hildon_banner_show_information(self.main_window, '', e)
253         if prefs:
254             self.do_accounts()
255     
256         
257     def get_use_facebook(self):
258         return self.gconf.get_bool("/apps/maemo/hermes/use_facebook")
259     
260     
261     def set_use_facebook(self, value):
262         self.gconf.set_bool("/apps/maemo/hermes/use_facebook", value)
263     
264     def get_create_empty(self):
265         return self.gconf.get_bool("/apps/maemo/hermes/create_empty")
266     
267     
268     def set_create_empty(self, value):
269         self.gconf.set_bool("/apps/maemo/hermes/create_empty", value)
270     
271     
272     def get_use_twitter(self):
273         return self.gconf.get_bool("/apps/maemo/hermes/use_twitter")
274     
275     
276     def set_use_twitter(self, value, user, password):
277         self.gconf.set_bool("/apps/maemo/hermes/use_twitter", value)
278         self.gconf.set_string("/apps/maemo/hermes/twitter_user", user)
279         self.gconf.set_string("/apps/maemo/hermes/twitter_pwd", password)
280       
281     
282     def get_twitter_credentials(self):
283         return (self.gconf.get_string("/apps/maemo/hermes/twitter_user") or '',
284                 self.gconf.get_string("/apps/maemo/hermes/twitter_pwd") or '')