Merging in the tweaks branch
[gc-dialer] / src / dialcentral / gc_dialer.py
index b3ce552..effb344 100755 (executable)
@@ -31,7 +31,6 @@ import warnings
 
 import gobject
 import gtk
 
 import gobject
 import gtk
-gtk.gdk.threads_init()
 import gtk.glade
 
 try:
 import gtk.glade
 
 try:
@@ -39,12 +38,12 @@ try:
 except ImportError:
        hildon = None
 
 except ImportError:
        hildon = None
 
-
-"""
-This changes the default, system wide, socket timeout so that a hung server will not completly
-hork the application
-"""
 import socket
 import socket
+
+
+gtk.gdk.threads_init()
+#This changes the default, system wide, socket timeout so that a hung server will not completly
+#hork the application
 socket.setdefaulttimeout(5)
 
 
 socket.setdefaulttimeout(5)
 
 
@@ -147,7 +146,7 @@ class DummyAddressBook(object):
                return self
 
        @staticmethod
                return self
 
        @staticmethod
-       def factory_short_name():
+       def contact_source_short_name(contactId):
                return ""
 
        @staticmethod
                return ""
 
        @staticmethod
@@ -169,6 +168,66 @@ class DummyAddressBook(object):
                return []
 
 
                return []
 
 
+class MergedAddressBook(object):
+       """
+       Merger of all addressbooks
+       """
+
+       def __init__(self, addressbooks, sorter = None):
+               self.__addressbooks = addressbooks
+               self.__sort_contacts = sorter if sorter is not None else self.null_sorter
+
+       def get_addressbooks(self):
+               """
+               @returns Iterable of (Address Book Factory, Book Id, Book Name)
+               """
+               yield self, "", ""
+       
+       def open_addressbook(self, bookId):
+               return self
+
+       def contact_source_short_name(self, contactId):
+               bookIndex, originalId = contactId.split("-", 1)
+               return self.__addressbooks[int(bookIndex)].contact_source_short_name(originalId)
+
+       @staticmethod
+       def factory_name():
+               return "All Contacts"
+
+       def get_contacts(self):
+               """
+               @returns Iterable of (contact id, contact name)
+               """
+               contacts = (
+                       ("-".join([str(bookIndex), contactId]), contactName)
+                               for (bookIndex, addressbook) in enumerate(self.__addressbooks)
+                                       for (contactId, contactName) in addressbook.get_contacts()
+               )
+               sortedContacts = self.__sort_contacts(contacts)
+               return sortedContacts
+
+       @staticmethod
+       def get_contact_details(contactId):
+               """
+               @returns Iterable of (Phone Type, Phone Number)
+               """
+               bookIndex, originalId = contactId.split("-", 1)
+               return self.__addressbooks[int(bookIndex)].get_contact_details(originalId)
+
+       @staticmethod
+       def null_sorter(contacts):
+               return contacts
+
+       @staticmethod
+       def basic_lastname_sorter(contacts):
+               contactsWithKey = [
+                       (contactName.rsplit(" ", 1)[-1], (contactId, contactName))
+                               for (contactId, contactName) in contacts
+               ]
+               contactsWithKey.sort()
+               return (contactData for (lastName, contactData) in contactsWithKey)
+
+
 class PhoneTypeSelector(object):
 
        def __init__(self, widgetTree, gcBackend):
 class PhoneTypeSelector(object):
 
        def __init__(self, widgetTree, gcBackend):
@@ -347,10 +406,12 @@ class Dialpad(object):
                If something can be done after the UI loads, push it here so it's not blocking the UI
                """
                
                If something can be done after the UI loads, push it here so it's not blocking the UI
                """
                
-               from gc_backend import GCDialer
-               from evo_backend import EvolutionAddressBook
+               import gc_backend
+               import evo_backend
+               import gmail_backend
+               import maemo_backend
 
 
-               self._gcBackend = GCDialer()
+               self._gcBackend = gc_backend.GCDialer()
 
                try:
                        import osso
 
                try:
                        import osso
@@ -380,11 +441,14 @@ class Dialpad(object):
                        warnings.warn("No Internet Connectivity API ", UserWarning, 2)
 
 
                        warnings.warn("No Internet Connectivity API ", UserWarning, 2)
 
 
-               self._addressBookFactories = [
+               addressBooks = [
                        self._gcBackend,
                        self._gcBackend,
+                       evo_backend.EvolutionAddressBook(),
                        DummyAddressBook(),
                        DummyAddressBook(),
-                       EvolutionAddressBook(),
                ]
                ]
+               mergedBook = MergedAddressBook(addressBooks, MergedAddressBook.basic_lastname_sorter)
+               self._addressBookFactories = list(addressBooks)
+               self._addressBookFactories.insert(0, mergedBook)
                self._addressBook = None
                self.open_addressbook(*self.get_addressbooks().next()[0][0:2])
        
                self._addressBook = None
                self.open_addressbook(*self.get_addressbooks().next()[0][0:2])
        
@@ -410,8 +474,8 @@ class Dialpad(object):
                combobox = self._widgetTree.get_widget("addressbook_combo")
                combobox.set_model(self._booksList)
                cell = gtk.CellRendererText()
                combobox = self._widgetTree.get_widget("addressbook_combo")
                combobox.set_model(self._booksList)
                cell = gtk.CellRendererText()
-               combobox.pack_start(cell, True)
-               combobox.add_attribute(cell, 'text', 2)
+               combobox.pack_start(cell, True)
+               combobox.add_attribute(cell, 'text', 2)
                combobox.set_active(0)
                gtk.gdk.threads_leave()
 
                combobox.set_active(0)
                gtk.gdk.threads_leave()
 
@@ -422,9 +486,7 @@ class Dialpad(object):
                self._init_contacts_view()
                gtk.gdk.threads_leave()
 
                self._init_contacts_view()
                gtk.gdk.threads_leave()
 
-               """
-               This is where the blocking can start
-               """
+               #This is where the blocking can start
                if self._gcBackend.is_authed():
                        gtk.gdk.threads_enter()
                        self.set_account_number(self._gcBackend.get_account_number())
                if self._gcBackend.is_authed():
                        gtk.gdk.threads_enter()
                        self.set_account_number(self._gcBackend.get_account_number())
@@ -458,6 +520,13 @@ class Dialpad(object):
                # Add the column to the treeview
                column = gtk.TreeViewColumn("Contact")
 
                # Add the column to the treeview
                column = gtk.TreeViewColumn("Contact")
 
+               #displayContactSource = False
+               displayContactSource = True
+               if displayContactSource:
+                       textrenderer = gtk.CellRendererText()
+                       column.pack_start(textrenderer, expand=False)
+                       column.add_attribute(textrenderer, 'text', 0)
+
                textrenderer = gtk.CellRendererText()
                column.pack_start(textrenderer, expand=True)
                column.add_attribute(textrenderer, 'text', 1)
                textrenderer = gtk.CellRendererText()
                column.pack_start(textrenderer, expand=True)
                column.add_attribute(textrenderer, 'text', 1)
@@ -523,8 +592,8 @@ class Dialpad(object):
                contactsview.freeze_child_notify()
                contactsview.set_model(None)
 
                contactsview.freeze_child_notify()
                contactsview.set_model(None)
 
-               contactType = (self._addressBook.factory_short_name(),)
                for contactId, contactName in self._addressBook.get_contacts():
                for contactId, contactName in self._addressBook.get_contacts():
+                       contactType = (self._addressBook.contact_source_short_name(contactId),)
                        self._contactsmodel.append(contactType + (contactName, "", contactId) + ("",))
                        yield
 
                        self._contactsmodel.append(contactType + (contactName, "", contactId) + ("",))
                        yield
 
@@ -550,7 +619,7 @@ class Dialpad(object):
                for x in xrange(numOfAttempts):
                        gtk.gdk.threads_enter()
 
                for x in xrange(numOfAttempts):
                        gtk.gdk.threads_enter()
 
-                       dialog = self._widgetTree.get_widget("login_dialog")
+                       dialog = self._widgetTree.get_widget("login_dialog")
                        dialog.set_transient_for(self._window)
                        dialog.set_default_response(0)
                        dialog.run()
                        dialog.set_transient_for(self._window)
                        dialog.set_default_response(0)
                        dialog.run()
@@ -567,8 +636,10 @@ class Dialpad(object):
                                        self._gcBackend.set_sane_callback()
                                self.populate_callback_combo()
                                self.set_account_number(self._gcBackend.get_account_number())
                                        self._gcBackend.set_sane_callback()
                                self.populate_callback_combo()
                                self.set_account_number(self._gcBackend.get_account_number())
-                               gtk.gdk.threads_leave()
-                               return True
+                               gtk.gdk.threads_leave()
+                               return True
+
+               return False
 
        def display_error_message(self, msg):
                error_dialog = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg)
 
        def display_error_message(self, msg):
                error_dialog = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg)
@@ -635,7 +706,7 @@ class Dialpad(object):
                if status == conic.STATUS_CONNECTED:
                        self._window.set_sensitive(True)
                        self._deviceIsOnline = True
                if status == conic.STATUS_CONNECTED:
                        self._window.set_sensitive(True)
                        self._deviceIsOnline = True
-                       threading.Thread(target=self.attempt_login,args=[2]).start()
+                       threading.Thread(target=self.attempt_login, args=[2]).start()
                elif status == conic.STATUS_DISCONNECTED:
                        self._window.set_sensitive(False)
                        self._deviceIsOnline = False
                elif status == conic.STATUS_DISCONNECTED:
                        self._window.set_sensitive(False)
                        self._deviceIsOnline = False
@@ -675,7 +746,7 @@ class Dialpad(object):
                self.set_account_number("")
 
                # re-run the inital grandcentral setup
                self.set_account_number("")
 
                # re-run the inital grandcentral setup
-               threading.Thread(target=self.attempt_login,args=[2]).start()
+               threading.Thread(target=self.attempt_login, args=[2]).start()
                #gobject.idle_add(self._idly_populate_callback_combo)
 
        def _on_callbackentry_changed(self, *args):
                #gobject.idle_add(self._idly_populate_callback_combo)
 
        def _on_callbackentry_changed(self, *args):
@@ -773,6 +844,7 @@ class Dialpad(object):
 
        def _on_paste(self, *args):
                contents = self._clipboard.wait_for_text()
 
        def _on_paste(self, *args):
                contents = self._clipboard.wait_for_text()
+               phoneNumber = make_ugly(contents)
                self.set_number(phoneNumber)
 
        def _on_clear_number(self, *args):
                self.set_number(phoneNumber)
 
        def _on_clear_number(self, *args):
@@ -803,7 +875,7 @@ class Dialpad(object):
                dlg.set_copyright("Copyright 2008 - LGPL")
                dlg.set_comments("Dialer is designed to interface with your Google Grandcentral account.  This application is not affiliated with Google or Grandcentral in any way")
                dlg.set_website("http://gc-dialer.garage.maemo.org/")
                dlg.set_copyright("Copyright 2008 - LGPL")
                dlg.set_comments("Dialer is designed to interface with your Google Grandcentral account.  This application is not affiliated with Google or Grandcentral in any way")
                dlg.set_website("http://gc-dialer.garage.maemo.org/")
-               dlg.set_authors(["<z2n@merctech.com>","Eric Warnke <ericew@gmail.com>","Ed Page <edpage@byu.net>"])
+               dlg.set_authors(["<z2n@merctech.com>", "Eric Warnke <ericew@gmail.com>", "Ed Page <edpage@byu.net>"])
                dlg.run()
                dlg.destroy()
        
                dlg.run()
                dlg.destroy()