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.5', 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)
192 dialog.vbox.add(view.get_search())
198 # -----------------------------------------------------------------------
199 def map_contact(self, widget, contact, fb2c):
200 view = MapContact(fb2c.friends, contact)
202 dialog = gtk.Dialog(contact.get_name(), self.main_window)
203 dialog.add_button(_('Update'), gtk.RESPONSE_OK)
204 dialog.vbox.add(view)
206 dialog.vbox.add(view.get_search())
208 result = dialog.run()
210 if result == gtk.RESPONSE_OK:
211 friend = view.get_selected_friend()
213 if friend.get_contact() == contact:
214 hildon.hildon_banner_show_information(self.main_window, '', _("Removing existing mappings is not yet supported"))
215 elif view.contact_mapped:
216 fb2c.update_contact(contact, friend, True, True)
217 widget.add_mapping(friend.get_source())
219 fb2c.update_contact(contact, friend, False, True)
220 widget.add_mapping(friend.get_source())
223 # -----------------------------------------------------------------------
224 def need_auth(self, main = False):
225 """Part of the GUI callback API."""
228 hildon.hildon_banner_show_information(self.main_window, '', _("Need to authenticate via browser"))
230 gobject.idle_add(self.need_auth, True)
233 # -----------------------------------------------------------------------
234 def block_for_auth(self, prompt = False, main = False, lock = None):
235 """Part of the GUI callback API."""
238 note = gtk.Dialog(_('Service authorisation'), self.main_window)
239 note.add_button(_("Validate"), gtk.RESPONSE_OK)
241 input = hildon.Entry(gtk.HILDON_SIZE_FINGER_HEIGHT)
242 input.set_property('is-focus', False)
243 note.set_title(_("Verification code from web browser"))
246 note.vbox.add(gtk.Label(_("\nPress 'Validate' once account has\nbeen authorised in web browser.\n")))
252 if prompt and result == gtk.RESPONSE_OK:
253 print input.get_text()
254 return input.get_text()
260 lock = thread.allocate_lock()
262 gobject.idle_add(self.block_for_auth, prompt, True, lock)
267 # -----------------------------------------------------------------------
268 def progress(self, msg, i, j, main = False):
269 """Part of the GUI callback API."""
273 self.progressbar = gtk.ProgressBar()
274 self.progressnote = gtk.Dialog(_("Initialising connections"), self.main_window)
275 self.progressnote.vbox.add(self.progressbar)
276 hildon.hildon_gtk_window_set_progress_indicator(self.progressnote, 1)
278 self.progressnote.show_all()
281 self.progressnote.set_title(_(msg))
282 hildon.hildon_gtk_window_set_progress_indicator(self.progressnote, 0)
284 self.progressbar.set_fraction(float(i) / float(j))
287 self.progressnote.destroy()
291 gobject.idle_add(self.progress, msg, i, j, True)
294 # -----------------------------------------------------------------------
295 def report_error(self, e, prefs = False):
296 if self.progressnote:
297 self.main_window.set_property('sensitive', True)
298 self.progressnote.destroy()
300 hildon.hildon_banner_show_information(self.main_window, '', e)