10 from org.bleb.wimpworks import WimpWorks
11 from org.maemo.hermes.gui.contactview import ContactView
12 from org.maemo.hermes.gui.mapcontact import MapContact
13 from org.maemo.hermes.gui.accountsdialogue import AccountsDialogue
14 from org.bleb.wimpworks import HildonMainScreenLayout
15 from org.maemo.hermes.engine.syncjob import SyncJob
16 from org.maemo.hermes.engine.hermes import Hermes
18 class HermesGUI(WimpWorks):
19 """Provides the GUI for Hermes, allowing the syncing of Facebook and
20 Twitter friends' information with the Evolution contacts' database.
22 Copyright (c) Andrew Flegg <andrew@bleb.org> 2009.
23 Released under the Artistic Licence."""
26 # -----------------------------------------------------------------------
27 def __init__(self, providers = None):
28 gettext.install('hermes','/opt/hermes/share/locale/')
29 WimpWorks.__init__(self, 'Hermes', version = '0.8.2', dbus_name = 'org.maemo.hermes')
30 self.set_background('background.png')
32 layout = HildonMainScreenLayout(offset = 0.8, container = self)
33 layout.add_button('Retrieve', _("Get contacts' missing info"))
34 layout.add_button('Refresh', _("Update contacts' info"))
36 self.add_menu_action("Accounts")
37 self.add_menu_action("About")
40 self.providers = providers
41 self.progressnote = None
42 connection = conic.Connection()
43 gobject.timeout_add(100, connection.request_connection, conic.CONNECT_FLAG_NONE)
46 # -----------------------------------------------------------------------
47 def do_retrieve(self, widget):
48 self.sync(widget, False)
51 # -----------------------------------------------------------------------
52 def do_refresh(self, widget):
53 self.sync(widget, True)
56 # -----------------------------------------------------------------------
57 def do_accounts(self, widget = None):
58 dialog = AccountsDialogue(self.main_window, self.providers)
62 # -----------------------------------------------------------------------
63 def do_about(self, widget):
64 """Inspired by HeAboutDialog Python port:
65 http://wiki.maemo.org/Hildon-Extras#HeAboutDialog"""
67 dlg = gtk.Dialog(_("About"), self.main_window)
70 icon.set_from_icon_name(self.name.lower(), gtk.ICON_SIZE_DIALOG)
71 icon.set_padding(5, 5)
73 name = gtk.Label(self.name)
74 name.set_alignment(0, 1)
75 hildon.hildon_helper_set_logical_font(name, 'X-LargeSystemFont')
77 version = gtk.Label('v%s' % (self.version))
78 version.set_alignment(0, 1)
79 version.set_padding(10, 0)
80 hildon.hildon_helper_set_logical_font(version, 'LargeSystemFont')
82 desc = gtk.Label(_("Enrich contacts' from social networks."))
83 desc.set_alignment(0, 0)
85 copy = gtk.Label("Copyright (c) 2010 Andrew Flegg, Fredrik Wendt, Tim Samoff")
86 copy.set_alignment(0, 1)
87 copy.set_padding(0, 5)
88 hildon.hildon_helper_set_logical_font(copy, 'SmallSystemFont')
89 hildon.hildon_helper_set_logical_color(copy, gtk.RC_FG, gtk.STATE_NORMAL, "SecondaryTextColor")
91 layout = gtk.Table(3, 3, False)
92 layout.attach(icon, 0, 1, 0, 2, 0, gtk.EXPAND, 0, 0)
93 layout.attach(name, 1, 2, 0, 1, 0, gtk.EXPAND | gtk.FILL, 0, 0)
94 layout.attach(version, 2, 3, 0, 1, gtk.EXPAND | gtk.FILL, gtk.EXPAND | gtk.FILL, 0, 0)
95 layout.attach(desc, 1, 3, 1, 2, gtk.EXPAND | gtk.FILL, gtk.EXPAND | gtk.FILL, 0, 0)
96 layout.attach(copy, 0, 3, 2, 3, gtk.EXPAND | gtk.FILL, gtk.EXPAND | gtk.FILL, 0, 0)
99 dlg.add_button(_('Visit website'), gtk.RESPONSE_APPLY)
100 dlg.add_button(_('Report bug'), gtk.RESPONSE_NO)
103 if response == gtk.RESPONSE_APPLY:
104 webbrowser.open('http://hermes.garage.maemo.org/')
105 elif response == gtk.RESPONSE_NO:
106 webbrowser.open('https://bugs.maemo.org/enter_bug.cgi?product=Hermes')
110 # -----------------------------------------------------------------------
111 def sync(self, widget, force, main = True):
113 for provider in self.providers:
114 if self.gconf.get_bool('/apps/maemo/hermes/use_%s' % (provider.get_id())):
115 enabled.append(provider)
117 if main and len(enabled) == 0:
118 saved = self.do_accounts()
119 if saved == gtk.RESPONSE_DELETE_EVENT:
122 print "doing sync", main
125 self.main_window.set_property('sensitive', False)
126 thread.start_new_thread(self.sync, (widget, force, False))
129 self.progress('', 0, 0)
131 for provider in enabled:
132 services.append(provider.service(self))
134 hermes = Hermes(services, self.progress)
136 gobject.idle_add(self.open_summary, hermes)
138 except urllib2.HTTPError, e:
139 traceback.print_exc()
141 gobject.idle_add(self.report_error, _('Authentication problem. Check credentials.'), True)
143 gobject.idle_add(self.report_error, _('Network connection error. Check connectivity.'))
145 except urllib2.URLError, e:
146 traceback.print_exc()
147 gobject.idle_add(self.report_error, _('Network connection error. Check connectivity.'))
150 traceback.print_exc()
151 gobject.idle_add(self.report_error, _('Something went wrong: ') + e.message)
154 # -----------------------------------------------------------------------
155 def open_summary(self, fb2c):
156 gobject.idle_add(self.main_window.set_property, 'sensitive', True)
158 dialog = gtk.Dialog(_('Summary'), self.main_window)
159 dialog.add_button(_('Done'), gtk.RESPONSE_OK)
161 button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
162 title = _('Updated %d contacts') % (len(fb2c.updated)))
163 button.connect('clicked', self.show_contacts, fb2c, fb2c.updated)
164 button.set_property('sensitive', len(fb2c.updated) > 0)
165 dialog.vbox.add(button)
167 button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
168 title = _('Matched %d contacts') % (len(fb2c.matched)))
169 button.connect('clicked', self.show_contacts, fb2c, fb2c.matched)
170 button.set_property('sensitive', len(fb2c.matched) > 0)
171 dialog.vbox.add(button)
173 button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL,
174 title = _('%d contacts unmatched') % (len(fb2c.unmatched)))
175 button.connect('clicked', self.show_contacts, fb2c, fb2c.unmatched)
176 button.set_property('sensitive', len(fb2c.unmatched) > 0)
177 dialog.vbox.add(button)
184 # -----------------------------------------------------------------------
185 def show_contacts(self, widget, fb2c, contacts):
186 view = ContactView(contacts)
188 dialog = gtk.Dialog(_('Contacts'), self.main_window)
189 view.connect('contact-activated', self.map_contact, fb2c)
190 dialog.vbox.add(view)
197 # -----------------------------------------------------------------------
198 def map_contact(self, widget, contact, fb2c):
199 view = MapContact(fb2c.friends, contact)
201 dialog = gtk.Dialog(contact.get_name(), self.main_window)
202 dialog.add_button(_('Update'), gtk.RESPONSE_OK)
203 dialog.vbox.add(view)
206 result = dialog.run()
208 if result == gtk.RESPONSE_OK:
209 friend = view.get_selected_friend()
211 if friend.get_contact() == contact:
212 hildon.hildon_banner_show_information(self.main_window, '', _("Removing existing mappings is not yet supported"))
213 elif view.contact_mapped:
214 fb2c.update_contact(contact, friend, True, True)
215 widget.add_mapping(friend.get_source())
217 fb2c.update_contact(contact, friend, False, True)
218 widget.add_mapping(friend.get_source())
221 # -----------------------------------------------------------------------
222 def need_auth(self, main = False):
223 """Part of the GUI callback API."""
226 hildon.hildon_banner_show_information(self.main_window, '', _("Need to authenticate via browser"))
228 gobject.idle_add(self.need_auth, True)
231 # -----------------------------------------------------------------------
232 def block_for_auth(self, prompt = False, main = False, lock = None):
233 """Part of the GUI callback API."""
236 note = gtk.Dialog(_('Service authorisation'), self.main_window)
237 note.add_button(_("Validate"), gtk.RESPONSE_OK)
239 input = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
240 input.set_property('is-focus', False)
241 note.set_title(_("Verification code from web browser"))
244 note.vbox.add(gtk.Label(_("\nPress 'Validate' once account has\nbeen authorised in web browser.\n")))
250 if prompt and result == gtk.RESPONSE_OK:
251 print input.get_text()
252 return input.get_text()
258 lock = thread.allocate_lock()
260 gobject.idle_add(self.block_for_auth, prompt, True, lock)
265 # -----------------------------------------------------------------------
266 def progress(self, msg, i, j, main = False):
267 """Part of the GUI callback API."""
271 self.progressbar = gtk.ProgressBar()
272 self.progressnote = gtk.Dialog(_("Initialising connections"), self.main_window)
273 self.progressnote.vbox.add(self.progressbar)
274 hildon.hildon_gtk_window_set_progress_indicator(self.progressnote, 1)
276 self.progressnote.show_all()
279 self.progressnote.set_title(_(msg))
280 hildon.hildon_gtk_window_set_progress_indicator(self.progressnote, 0)
282 self.progressbar.set_fraction(float(i) / float(j))
285 self.progressnote.destroy()
289 gobject.idle_add(self.progress, msg, i, j, True)
292 # -----------------------------------------------------------------------
293 def report_error(self, e, prefs = False):
294 if self.progressnote:
295 self.main_window.set_property('sensitive', True)
296 self.progressnote.destroy()
298 hildon.hildon_banner_show_information(self.main_window, '', e)