X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=gc_dialer%2Fgc_dialer.py;h=48691ba89f3e5d9032610165b93fb3aaa3e279ca;hb=62d24ce45a80b900fea34b82ceef9831c10be0cc;hp=0475080f8d9b58537ca16ecb986bc3b33766ac85;hpb=cd41d02c1d5b7129d36b3a195ede619613ffa6ce;p=gc-dialer diff --git a/gc_dialer/gc_dialer.py b/gc_dialer/gc_dialer.py index 0475080..48691ba 100755 --- a/gc_dialer/gc_dialer.py +++ b/gc_dialer/gc_dialer.py @@ -10,51 +10,69 @@ bergman@merctech.com import sys +import gc import os -import re -import time import threading -import contextlib +import time +import re +import warnings + import gobject import gtk -import gc -#import hildon +import gtk.glade + +try: + import hildon +except ImportError: + hildon = None + +try: + import osso + try: + import abook + import evolution.ebook as evobook + except ImportError: + abook = None + evobook = None +except ImportError: + osso = None + +try: + import conic +except ImportError: + conic = None try: import doctest import optparse -except: - pass +except ImportError: + doctest = None + optparse = None from gcbackend import GCDialer import socket -socket.setdefaulttimeout(5) -@contextlib.contextmanager -def gtk_critical_section(): - #The API changed and I hope these are the right calls - gtk.gdk.threads_enter() - yield - gtk.gdk.threads_leave() + +socket.setdefaulttimeout(5) -def makeugly(prettynumber): +def make_ugly(prettynumber): """ function to take a phone number and strip out all non-numeric characters - >>> makeugly("+012-(345)-678-90") + >>> make_ugly("+012-(345)-678-90") '01234567890' """ uglynumber = re.sub('\D', '', prettynumber) return uglynumber -def makepretty(phonenumber): +def make_pretty(phonenumber): """ Function to take a phone number and return the pretty version - pretty numbers: + pretty numbers: if phonenumber begins with 0: ...-(...)-...-.... if phonenumber begins with 1: ( for gizmo callback numbers ) @@ -63,15 +81,15 @@ def makepretty(phonenumber): (...)-...-.... if phonenumber is 10 digits: ...-.... - >>> makepretty("12") + >>> make_pretty("12") '12' - >>> makepretty("1234567") + >>> make_pretty("1234567") '123-4567' - >>> makepretty("2345678901") + >>> make_pretty("2345678901") '(234)-567-8901' - >>> makepretty("12345678901") + >>> make_pretty("12345678901") '1 (234)-567-8901' - >>> makepretty("01234567890") + >>> make_pretty("01234567890") '+012-(345)-678-90' """ if phonenumber is None: @@ -93,107 +111,214 @@ def makepretty(phonenumber): elif len(phonenumber) <= 7: prettynumber = "%s-%s" % (phonenumber[0:3], phonenumber[3:]) elif len(phonenumber) > 8 and phonenumber[0] == "1": - prettynumber = "1 (%s)-%s-%s" %(phonenumber[1:4], phonenumber[4:7], phonenumber[7:]) + prettynumber = "1 (%s)-%s-%s" % (phonenumber[1:4], phonenumber[4:7], phonenumber[7:]) elif len(phonenumber) > 7: prettynumber = "(%s)-%s-%s" % (phonenumber[0:3], phonenumber[3:6], phonenumber[6:]) return prettynumber +class PhoneTypeSelector(object): + + def __init__(self, widgetTree, gcBackend): + self._gcBackend = gcBackend + self._widgetTree = widgetTree + self._dialog = self._widgetTree.get_widget("phonetype_dialog") + + self._selectButton = self._widgetTree.get_widget("select_button") + self._selectButton.connect("clicked", self._on_phonetype_select) + + self._cancelButton = self._widgetTree.get_widget("cancel_button") + self._cancelButton.connect("clicked", self._on_phonetype_cancel) + + self._typemodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) + self._typeviewselection = None + + typeview = self._widgetTree.get_widget("phonetypes") + typeview.connect("row-activated", self._on_phonetype_select) + typeview.set_model(self._typemodel) + textrenderer = gtk.CellRendererText() + + # Add the column to the treeview + column = gtk.TreeViewColumn("Phone Numbers", textrenderer, text=1) + column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + + typeview.append_column(column) + + self._typeviewselection = typeview.get_selection() + self._typeviewselection.set_mode(gtk.SELECTION_SINGLE) + + def run(self, contactDetails): + self._typemodel.clear() + + for phoneType, phoneNumber in contactDetails: + self._typemodel.append((phoneNumber, "%s - %s" % (make_pretty(phoneNumber), phoneType))) + + userResponse = self._dialog.run() + + if userResponse == gtk.RESPONSE_OK: + model, itr = self._typeviewselection.get_selected() + if itr: + phoneNumber = self._typemodel.get_value(itr, 0) + else: + phoneNumber = "" + + self._typeviewselection.unselect_all() + self._dialog.hide() + return phoneNumber + + def _on_phonetype_select(self, *args): + self._dialog.response(gtk.RESPONSE_OK) + + def _on_phonetype_cancel(self, *args): + self._dialog.response(gtk.RESPONSE_CANCEL) + + class Dialpad(object): + __app_name__ = "gc_dialer" + __version__ = "0.7.0" + __app_magic__ = 0xdeadbeef + + _glade_files = [ + './gc_dialer.glade', + '../lib/gc_dialer.glade', + '/usr/local/lib/gc_dialer.glade', + ] + def __init__(self): - self.phonenumber = "" - self.prettynumber = "" - self.areacode = "518" - self.clipboard = gtk.clipboard_get() - self.wTree = gtk.Builder() - self.recentmodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) - self.recentviewselection = None - self.callbackNeedsSetup = True - self.recenttime = 0.0 - - for path in [ './gc_dialer.xml', - '../lib/gc_dialer.xml', - '/usr/local/lib/gc_dialer.xml' ]: + self._phonenumber = "" + self._prettynumber = "" + self._areacode = "518" + + self._clipboard = gtk.clipboard_get() + + self._deviceIsOnline = True + self._callbackNeedsSetup = True + + self._recenttime = 0.0 + self._recentmodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) + self._recentviewselection = None + + self._contactstime = 0.0 + self._contactsmodel = gtk.ListStore(gtk.gdk.Pixbuf, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) + self._contactsviewselection = None + + for path in Dialpad._glade_files: if os.path.isfile(path): - self.wTree.add_from_file(path) + self._widgetTree = gtk.glade.XML(path) break else: - self.ErrPopUp("Cannot find gc_dialer.xml") + self.display_error_message("Cannot find gc_dialer.glade") gtk.main_quit() return + aboutHeader = self._widgetTree.get_widget("about_title") + aboutHeader.set_label("%s\nVersion %s" % (aboutHeader.get_label(), Dialpad.__version__)) #Get the buffer associated with the number display - self.numberdisplay = self.wTree.get_object("numberdisplay") - self.setNumber("") - self.notebook = self.wTree.get_object("notebook") - - self.isHildon = False + self._numberdisplay = self._widgetTree.get_widget("numberdisplay") + self.set_number("") + self._notebook = self._widgetTree.get_widget("notebook") + + self._window = self._widgetTree.get_widget("Dialpad") + + global hildon + self._app = None + self._isFullScreen = False + if hildon is not None and isinstance(self._window, gtk.Window): + warnings.warn("Hildon installed but glade file not updated to work with hildon", UserWarning, 2) + hildon = None + elif hildon is not None: + self._app = hildon.Program() + self._window.set_title("Keypad") + self._app.add_window(self._window) + self._widgetTree.get_widget("callbackcombo").get_child().set_property('hildon-input-mode', (1 << 4)) + self._widgetTree.get_widget("usernameentry").set_property('hildon-input-mode', 7) + self._widgetTree.get_widget("passwordentry").set_property('hildon-input-mode', 7|(1 << 29)) + + gtkMenu = self._widgetTree.get_widget("menubar1") + menu = gtk.Menu() + for child in gtkMenu.get_children(): + child.reparent(menu) + self._window.set_menu(menu) + gtkMenu.destroy() + + self._window.connect("key-press-event", self._on_key_press) + self._window.connect("window-state-event", self._on_window_state_change) + else: + warnings.warn("No Hildon", UserWarning, 2) + + self._osso = None + self._ebook = None + if osso is not None: + self._osso = osso.Context(Dialpad.__app_name__, Dialpad.__version__, False) + device = osso.DeviceState(self._osso) + device.set_device_state_callback(self._on_device_state_change, 0) + if abook is not None and evobook is not None: + abook.init_with_name(Dialpad.__app_name__, self._osso) + self._ebook = evobook.open_addressbook("default") + else: + warnings.warn("No abook and No evolution address book support", UserWarning, 2) + else: + warnings.warn("No OSSO", UserWarning, 2) - self.window = self.wTree.get_object("Dialpad") - #if True: - try: - #self.osso = osso.Context("gc_dialer", "0.6.0", False) - #device = osso.DeviceState(self.osso) - #device.set_device_state_callback(self.on_device_state_change, None) - #abook.init_with_name("gc_dialer", self.osso) - #self.ebook = evo.open_addressbook("default") - self.app = hildon.Program() - self.wTree.get_object("callbackentry").set_property('hildon-input-mode', (1 << 4)) - self.wTree.get_object("usernameentry").set_property('hildon-input-mode', 7) - self.wTree.get_object("passwordentry").set_property('hildon-input-mode', 7) - self.isHildon = True - except: - print "No hildon" - - if self.window: - self.window.connect("destroy", gtk.main_quit) - self.window.show_all() + self._connection = None + if conic is not None: + self._connection = conic.Connection() + self._connection.connect("connection-event", self._on_connection_change, Dialpad.__app_magic__) + self._connection.request_connection(conic.CONNECT_FLAG_NONE) + else: + warnings.warn("No Internet Connectivity API ", UserWarning, 2) callbackMapping = { # Process signals from buttons - "on_digit_clicked" : self.on_digit_clicked, - "on_dial_clicked" : self.on_dial_clicked, - "on_loginbutton_clicked" : self.on_loginbutton_clicked, - "on_clearcookies_clicked" : self.on_clearcookies_clicked, - "on_callbackentry_changed" : self.on_callbackentry_changed, - "on_notebook_switch_page" : self.on_notebook_switch_page, - "on_recentview_row_activated" : self.on_recentview_row_activated, - "on_back_clicked" : self.Backspace + "on_loginbutton_clicked": self._on_loginbutton_clicked, + "on_loginclose_clicked": self._on_loginclose_clicked, + + "on_dialpad_quit": (lambda data: gtk.main_quit()), + "on_paste": self._on_paste, + "on_clear_number": self._on_clear_number, + + "on_clearcookies_clicked": self._on_clearcookies_clicked, + "on_notebook_switch_page": self._on_notebook_switch_page, + "on_recentview_row_activated": self._on_recentview_row_activated, + "on_contactsview_row_activated" : self._on_contactsview_row_activated, + + "on_digit_clicked": self._on_digit_clicked, + "on_back_clicked": self._on_backspace, + "on_dial_clicked": self._on_dial_clicked, } - self.wTree.connect_signals(callbackMapping) + self._widgetTree.signal_autoconnect(callbackMapping) + self._widgetTree.get_widget("callbackcombo").get_child().connect("changed", self._on_callbackentry_changed) - # Defer initalization of recent view - self.gcd = GCDialer() + if self._window: + self._window.connect("destroy", gtk.main_quit) + self._window.show_all() - self.attemptLogin(2) - gobject.idle_add(self.init_grandcentral) - #self.init_grandcentral() - gobject.idle_add(self.init_recentview) + self._gcBackend = GCDialer() - #self.reduce_memory() + self._phoneTypeSelector = PhoneTypeSelector(self._widgetTree, self._gcBackend) + + self.attempt_login(2) + gobject.idle_add(self._init_grandcentral) + gobject.idle_add(self._init_recent_view) + gobject.idle_add(self._init_contacts_view) + + def _init_grandcentral(self): + """ Deferred initalization of the grandcentral info """ + + if self._gcBackend.is_authed(): + if self._gcBackend.get_callback_number() is None: + self._gcBackend.set_sane_callback() + self.set_account_number() - def init_grandcentral(self): - """ deferred initalization of the grandcentral info """ - - try: - #self.attemptLogin(2) - if self.gcd.isAuthed(): - if self.gcd.getCallbackNumber() is None: - self.gcd.setSaneCallback() - except: - pass - - self.setAccountNumber() - print "exit init_gc" return False - def init_recentview(self): - """ deferred initalization of the recent view treeview """ + def _init_recent_view(self): + """ Deferred initalization of the recent view treeview """ - recentview = self.wTree.get_object("recentview") - recentview.set_model(self.recentmodel) + recentview = self._widgetTree.get_widget("recentview") + recentview.set_model(self._recentmodel) textrenderer = gtk.CellRendererText() # Add the column to the treeview @@ -202,152 +327,293 @@ class Dialpad(object): recentview.append_column(column) - self.recentviewselection = recentview.get_selection() - self.recentviewselection.set_mode(gtk.SELECTION_SINGLE) + self._recentviewselection = recentview.get_selection() + self._recentviewselection.set_mode(gtk.SELECTION_SINGLE) return False - def on_recentview_row_activated(self, treeview, path, view_column): - model, itr = self.recentviewselection.get_selected() - if not itr: - return + def _init_contacts_view(self): + """ deferred initalization of the contacts view treeview """ - self.setNumber(self.recentmodel.get_value(itr, 0)) - self.notebook.set_current_page(0) - self.recentviewselection.unselect_all() + contactsview = self._widgetTree.get_widget("contactsview") + contactsview.set_model(self._contactsmodel) - def on_notebook_switch_page(self, notebook, page, page_num): - if page_num == 1 and (time.time() - self.recenttime) > 300: - gobject.idle_add(self.populate_recentview) - elif page_num ==2 and self.callbackNeedsSetup: - gobject.idle_add(self.setupCallbackCombo) + # Add the column to the treeview + column = gtk.TreeViewColumn("Contact") - def populate_recentview(self): - print "Populating" - self.recentmodel.clear() - for item in self.gcd.get_recent(): - self.recentmodel.append(item) - self.recenttime = time.time() + iconrenderer = gtk.CellRendererPixbuf() + column.pack_start(iconrenderer, expand=False) + column.add_attribute(iconrenderer, 'pixbuf', 0) - return False + textrenderer = gtk.CellRendererText() + column.pack_start(textrenderer, expand=True) + column.add_attribute(textrenderer, 'text', 1) - def on_clearcookies_clicked(self, data=None): - self.gcd.reset() - self.callbackNeedsSetup = True - self.recenttime = 0.0 - - # re-run the inital grandcentral setup - self.attemptLogin(2) - gobject.idle_add(self.init_grandcentral) + textrenderer = gtk.CellRendererText() + column.pack_start(textrenderer, expand=True) + column.add_attribute(textrenderer, 'text', 4) + + column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + column.set_sort_column_id(1) + column.set_visible(True) + contactsview.append_column(column) + + #textrenderer = gtk.CellRendererText() + #column = gtk.TreeViewColumn("Location", textrenderer, text=2) + #column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + #column.set_sort_column_id(2) + #column.set_visible(True) + #contactsview.append_column(column) + + #textrenderer = gtk.CellRendererText() + #column = gtk.TreeViewColumn("Phone", textrenderer, text=3) + #column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + #column.set_sort_column_id(3) + #column.set_visible(True) + #contactsview.append_column(column) + + self._contactsviewselection = contactsview.get_selection() + self._contactsviewselection.set_mode(gtk.SELECTION_SINGLE) - def setupCallbackCombo(self): - combobox = self.wTree.get_object("callbackcombo") + return False + + def _setup_callback_combo(self): + combobox = self._widgetTree.get_widget("callbackcombo") self.callbacklist = gtk.ListStore(gobject.TYPE_STRING) combobox.set_model(self.callbacklist) combobox.set_text_column(0) - for number, description in self.gcd.getCallbackNumbers().iteritems(): - self.callbacklist.append([makepretty(number)] ) - - self.wTree.get_object("callbackentry").set_text(makepretty(self.gcd.getCallbackNumber())) - self.callbackNeedsSetup = False - - def on_callbackentry_changed(self, data=None): - text = makeugly(self.wTree.get_object("callbackentry").get_text()) - if self.gcd.validate(text) and text != self.gcd.getCallbackNumber(): - self.gcd.setCallbackNumber(text) - self.wTree.get_object("callbackentry").set_text(self.wTree.get_object("callbackentry").get_text()) - #self.reduce_memory() - - def attemptLogin(self, times = 1): - #if self.isHildon: - # dialog = hildon.LoginDialog(self.window) - # dialog.set_message("Grandcentral Login") - #else: - dialog = self.wTree.get_object("login_dialog") - - while (0 < times) and not self.gcd.isAuthed(): - if dialog.run() != gtk.RESPONSE_OK: - times = 0 - continue - - #if self.isHildon: - # username = dialog.get_username() - # password = dialog.get_password() - #else: - username = self.wTree.get_object("usernameentry").get_text() - password = self.wTree.get_object("passwordentry").get_text() - self.wTree.get_object("passwordentry").set_text("") - print "Attempting login" - self.gcd.login(username, password) - print "hiding dialog" - dialog.hide() - times = times - 1 + for number, description in self._gcBackend.get_callback_numbers().iteritems(): + self.callbacklist.append([make_pretty(number)]) + + combobox.get_child().set_text(make_pretty(self._gcBackend.get_callback_number())) + self._callbackNeedsSetup = False + + def populate_recentview(self): + self._recentmodel.clear() + + for personsName, phoneNumber, date, action in self._gcBackend.get_recent(): + item = (phoneNumber, "%s on %s from/to %s - %s" % (action.capitalize(), date, personsName, phoneNumber)) + self._recentmodel.append(item) + + self._recenttime = time.time() + return False + + def populate_contactsview(self): + self._contactsmodel.clear() + + # completely disable updating the treeview while we populate the data + contactsview = self._widgetTree.get_widget("contactsview") + contactsview.freeze_child_notify() + contactsview.set_model(None) + + # get gc icon + gc_icon = gtk.gdk.pixbuf_new_from_file_at_size('gc_contact.png', 16, 16) + for contactId, contactName in self._gcBackend.get_contacts(): + self._contactsmodel.append((gc_icon,) + (contactName, "", contactId) + ("",)) + + # restart the treeview data rendering + contactsview.set_model(self._contactsmodel) + contactsview.thaw_child_notify() + + self._contactstime = time.time() + return False + + def attempt_login(self, numOfAttempts = 1): + assert 0 < numOfAttempts, "That was pointless having 0 or less login attempts" + dialog = self._widgetTree.get_widget("login_dialog") + + if self._gcBackend.is_authed(): + return True + + for i in range(numOfAttempts): + dialog.run() - #if self.isHildon: - # print "destroy dialog" - # dialog.destroy() + username = self._widgetTree.get_widget("usernameentry").get_text() + password = self._widgetTree.get_widget("passwordentry").get_text() + self._widgetTree.get_widget("passwordentry").set_text("") + + loggedIn = self._gcBackend.login(username, password) + dialog.hide() + if loggedIn: + return True return False - def ErrPopUp(self, msg): + def display_error_message(self, msg): error_dialog = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg) def close(dialog, response, editor): editor.about_dialog = None dialog.destroy() error_dialog.connect("response", close, self) - self.error_dialog = error_dialog error_dialog.run() - def on_paste(self, data=None): - contents = self.clipboard.wait_for_text() - phoneNumber = re.sub('\D', '', contents) - self.setNumber(phoneNumber) - - def on_loginbutton_clicked(self, data=None): - self.wTree.get_object("login_dialog").response(gtk.RESPONSE_OK) + def set_number(self, number): + self._phonenumber = make_ugly(number) + self._prettynumber = make_pretty(self._phonenumber) + self._numberdisplay.set_label("%s" % ( self._prettynumber ) ) + + def set_account_number(self): + accountnumber = self._gcBackend.get_account_number() + self._widgetTree.get_widget("gcnumberlabel").set_label("%s" % (accountnumber)) + + def _on_device_state_change(self, shutdown, save_unsaved_data, memory_low, system_inactivity, message, userData): + """ + For shutdown or save_unsaved_data, our only state is cookies and I think the cookie manager handles that for us. + For system_inactivity, we have no background tasks to pause + + @note Hildon specific + """ + if memory_low: + self._gcBackend.clear_caches() + re.purge() + gc.collect() + + def _on_connection_change(self, connection, event, magicIdentifier): + """ + @note Hildon specific + """ + status = event.get_status() + error = event.get_error() + iap_id = event.get_iap_id() + bearer = event.get_bearer_type() + + if status == conic.STATUS_CONNECTED: + self._window.set_sensitive(True) + self._deviceIsOnline = True + elif status == conic.STATUS_DISCONNECTED: + self._window.set_sensitive(False) + self._deviceIsOnline = False + + def _on_window_state_change(self, widget, event, *args): + """ + @note Hildon specific + """ + if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN: + self._isFullScreen = True + else: + self._isFullScreen = False + + def _on_key_press(self, widget, event, *args): + """ + @note Hildon specific + """ + if event.keyval == gtk.keysyms.F6: + if self._isFullScreen: + self._window.unfullscreen() + else: + self._window.fullscreen() + + def _on_loginbutton_clicked(self, *args): + self._widgetTree.get_widget("login_dialog").response(gtk.RESPONSE_OK) + + def _on_loginclose_clicked(self, *args): + gtk.main_quit() + sys.exit(0) - def on_dial_clicked(self, widget): - self.attemptLogin(3) + def _on_clearcookies_clicked(self, *args): + self._gcBackend.reset() + self._callbackNeedsSetup = True + self._recenttime = 0.0 + self._contactstime = 0.0 + self._recentmodel.clear() + self._widgetTree.get_widget("callbackcombo").get_child().set_text("") - if not self.gcd.isAuthed() or self.gcd.getCallbackNumber() == "": - self.ErrPopUp("Backend link with grandcentral is not working, please try again") + # re-run the inital grandcentral setup + self.attempt_login(2) + gobject.idle_add(self._init_grandcentral) + + def _on_callbackentry_changed(self, *args): + """ + @todo Potential blocking on web access, maybe we should defer this or put up a dialog? + """ + text = make_ugly(self._widgetTree.get_widget("callbackcombo").get_child().get_text()) + if not self._gcBackend.is_valid_syntax(text): + warnings.warn("%s is not a valid callback number" % text, UserWarning, 2) + elif text != self._gcBackend.get_callback_number(): + self._gcBackend.set_callback_number(text) + else: + warnings.warn("Callback number already is %s" % self._gcBackend.get_callback_number(), UserWarning, 2) + + def _on_recentview_row_activated(self, treeview, path, view_column): + model, itr = self._recentviewselection.get_selected() + if not itr: return - #if len(self.phonenumber) == 7: - # #add default area code - # self.phonenumber = self.areacode + self.phonenumber + self.set_number(self._recentmodel.get_value(itr, 0)) + self._notebook.set_current_page(0) + self._recentviewselection.unselect_all() - if self.gcd.dial(self.phonenumber) is False: - self.ErrPopUp(self.gcd._msg) + def _on_contactsview_row_activated(self, treeview, path, view_column): + model, itr = self._contactsviewselection.get_selected() + if not itr: + return + + contactId = self._contactsmodel.get_value(itr, 3) + contactDetails = self._gcBackend.get_contact_details(contactId) + contactDetails = [phoneNumber for phoneNumber in contactDetails] + + if len(contactDetails) == 0: + phoneNumber = "" + elif len(contactDetails) == 1: + phoneNumber = contactDetails[0][1] else: - self.setNumber("") + phoneNumber = self._phoneTypeSelector.run(contactDetails) - self.recentmodel.clear() - self.recenttime = 0.0 - #self.reduce_memory() - - #def on_device_state_change(self, shutdown, save_unsaved_data, memory_low, system_inactivity, message, userData): - # """ - # @todo Might be useful to do something when going in offline mode or low memory - # @note Hildon specific - # """ - # pass + if 0 < len(phoneNumber): + self.set_number(phoneNumber) + self._notebook.set_current_page(0) - def setNumber(self, number): - self.phonenumber = makeugly(number) - self.prettynumber = makepretty(self.phonenumber) - self.numberdisplay.set_label("%s" % ( self.prettynumber ) ) + self._contactsviewselection.unselect_all() - def setAccountNumber(self): - accountnumber = self.gcd.getAccountNumber() - self.wTree.get_object("gcnumberlabel").set_label("%s" % (accountnumber)) + def _on_notebook_switch_page(self, notebook, page, page_num): + if page_num == 1 and 300 < (time.time() - self._contactstime): + gobject.idle_add(self.populate_contactsview) + elif page_num == 2 and 300 < (time.time() - self._recenttime): + gobject.idle_add(self.populate_recentview) + elif page_num == 3 and self._callbackNeedsSetup: + gobject.idle_add(self._setup_callback_combo) + + if hildon: + self._window.set_title(self._notebook.get_tab_label(self._notebook.get_nth_page(page_num)).get_text()) + + def _on_dial_clicked(self, widget): + """ + @todo Potential blocking on web access, maybe we should defer parts of this or put up a dialog? + """ + loggedIn = self.attempt_login(2) + if not loggedIn or not self._gcBackend.is_authed() or self._gcBackend.get_callback_number() == "": + self.display_error_message("Backend link with grandcentral is not working, please try again") + warnings.warn("Backend Status: Logged in? %s, Authenticated? %s, Callback=%s" % (loggedIn, self._gcBackend.is_authed(), self._gcBackend.get_callback_number()), UserWarning, 2) + return + + try: + callSuccess = self._gcBackend.dial(self._phonenumber) + except ValueError, e: + self._gcBackend._msg = e.message + callSuccess = False + + if not callSuccess: + self.display_error_message(self._gcBackend._msg) + else: + self.set_number("") + + self._recentmodel.clear() + self._recenttime = 0.0 - def Backspace(self, widget): - self.setNumber(self.phonenumber[:-1]) + def _on_paste(self, *args): + contents = self._clipboard.wait_for_text() + phoneNumber = re.sub('\D', '', contents) + self.set_number(phoneNumber) + + def _on_clear_number(self, *args): + self.set_number("") - def on_digit_clicked(self, widget): - self.setNumber(self.phonenumber + widget.get_name()[5]) + def _on_digit_clicked(self, widget): + self.set_number(self._phonenumber + widget.get_name()[5]) + + def _on_backspace(self, widget): + self.set_number(self._phonenumber[:-1]) def run_doctest(): @@ -360,29 +626,31 @@ def run_doctest(): def run_dialpad(): - gc.set_threshold(50, 3, 3) gtk.gdk.threads_init() title = 'Dialpad' handle = Dialpad() gtk.main() - sys.exit(1) class DummyOptions(object): + def __init__(self): self.test = False if __name__ == "__main__": - try: + if hildon is not None: + gtk.set_application_name("Dialer") + + if optparse is not None: parser = optparse.OptionParser() parser.add_option("-t", "--test", action="store_true", dest="test", help="Run tests") - (options, args) = parser.parse_args() - except: - args = [] - options = DummyOptions() + (commandOptions, commandArgs) = parser.parse_args() + else: + commandOptions = DummyOptions() + commandArgs = [] - if options.test: + if commandOptions.test: run_doctest() else: run_dialpad()