Merging in the tweaks branch
authorepage <eopage@byu.net>
Fri, 3 Oct 2008 00:05:36 +0000 (00:05 +0000)
committerepage <eopage@byu.net>
Fri, 3 Oct 2008 00:05:36 +0000 (00:05 +0000)
git-svn-id: file:///svnroot/gc-dialer/trunk@160 c39d3808-3fe2-4d86-a59f-b7f623ee9f21

src/dialcentral/evo_backend.py
src/dialcentral/gc_backend.py
src/dialcentral/gc_dialer.py
src/dialcentral/gmail_backend.py [new file with mode: 0644]
src/dialcentral/maemo_backend.py [new file with mode: 0644]

index c094c2e..c1c0487 100644 (file)
@@ -39,7 +39,17 @@ class EvolutionAddressBook(object):
                        return
 
                self._phoneTypes = None
-               self._bookId = bookId if bookId is not None else self.get_addressbooks().next()[1]
+               if bookId is not None:
+                       self._bookId = bookId
+               else:
+                       try:
+                               self._bookId = [
+                                       bookData[1]
+                                               for bookData in self.get_addressbooks()
+                               ][0]
+                       except IndexError:
+                               global evolution
+                               evolution = None
                self._book = evolution.ebook.open_addressbook(self._bookId)
        
        @classmethod
@@ -66,7 +76,7 @@ class EvolutionAddressBook(object):
                return self
 
        @staticmethod
-       def factory_short_name():
+       def contact_source_short_name(contactId):
                return "Evo"
 
        @staticmethod
@@ -81,13 +91,13 @@ class EvolutionAddressBook(object):
                        return
 
                for contact in self._book.get_all_contacts():
-                       yield contact.get_uid(), contact.props.full_name
+                       yield str(contact.get_uid()), contact.props.full_name
        
        def get_contact_details(self, contactId):
                """
                @returns Iterable of (Phone Type, Phone Number)
                """
-               contact = self._book.get_contact(contactId)
+               contact = self._book.get_contact(int(contactId))
 
                if self._phoneTypes is None and contact is not None:
                        self._phoneTypes = [pt for pt in dir(contact.props) if "phone" in pt.lower()]
@@ -97,7 +107,8 @@ class EvolutionAddressBook(object):
                        if isinstance(phoneNumber, str):
                                yield phoneType, phoneNumber
 
-def print_addressbooks():
+
+def print_evobooks():
        """
        Included here for debugging.
 
index d1641de..cda6eb6 100644 (file)
@@ -31,6 +31,11 @@ import warnings
 
 from browser_emu import MozillaEmulator
 
+import socket
+
+
+socket.setdefaulttimeout(5)
+
 
 class GCDialer(object):
        """
@@ -268,7 +273,7 @@ class GCDialer(object):
                return self
 
        @staticmethod
-       def factory_short_name():
+       def contact_source_short_name(contactId):
                return "GC"
 
        @staticmethod
index a47a467..effb344 100755 (executable)
@@ -146,7 +146,7 @@ class DummyAddressBook(object):
                return self
 
        @staticmethod
-       def factory_short_name():
+       def contact_source_short_name(contactId):
                return ""
 
        @staticmethod
@@ -168,6 +168,66 @@ class DummyAddressBook(object):
                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):
@@ -346,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
                """
                
-               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
@@ -379,11 +441,14 @@ class Dialpad(object):
                        warnings.warn("No Internet Connectivity API ", UserWarning, 2)
 
 
-               self._addressBookFactories = [
+               addressBooks = [
                        self._gcBackend,
+                       evo_backend.EvolutionAddressBook(),
                        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])
        
@@ -455,6 +520,13 @@ class Dialpad(object):
                # 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)
@@ -520,8 +592,8 @@ class Dialpad(object):
                contactsview.freeze_child_notify()
                contactsview.set_model(None)
 
-               contactType = (self._addressBook.factory_short_name(),)
                for contactId, contactName in self._addressBook.get_contacts():
+                       contactType = (self._addressBook.contact_source_short_name(contactId),)
                        self._contactsmodel.append(contactType + (contactName, "", contactId) + ("",))
                        yield
 
@@ -567,6 +639,8 @@ class Dialpad(object):
                                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)
 
diff --git a/src/dialcentral/gmail_backend.py b/src/dialcentral/gmail_backend.py
new file mode 100644 (file)
index 0000000..f29c7ca
--- /dev/null
@@ -0,0 +1,104 @@
+#!/usr/bin/python
+
+# GC Dialer - Front end for Google's Grand Central service.
+# Copyright (C) 2008  Eric Warnke ericew AT gmail DOT com
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+"""
+GMail Contacts Support
+"""
+
+
+import warnings
+
+
+try:
+       import libgmail
+except ImportError:
+       libgmail = None
+
+
+class GMailAddressBook(object):
+       """
+       @note Combined the factory and the addressbook for "simplicity" and "cutting down" the number of allocations/deallocations
+       """
+
+       def __init__(self, username, password):
+               if not self.is_supported():
+                       return
+
+               self._account = libgmail.GmailAccount(username, password)
+               self._gmailContacts = self._account.getContacts()
+       
+       @classmethod
+       def is_supported(cls):
+               return libgmail is not None
+
+       def get_addressbooks(self):
+               """
+               @returns Iterable of (Address Book Factory, Book Id, Book Name)
+               """
+               if not self.is_supported():
+                       return
+
+               yield self, "", ""
+       
+       def open_addressbook(self, bookId):
+               return self
+
+       @staticmethod
+       def contact_source_short_name(contactId):
+               return "G"
+
+       @staticmethod
+       def factory_name():
+               return "GMail"
+
+       def get_contacts(self):
+               """
+               @returns Iterable of (contact id, contact name)
+               """
+               if not self.is_supported():
+                       return
+               pass
+       
+       def get_contact_details(self, contactId):
+               """
+               @returns Iterable of (Phone Type, Phone Number)
+               """
+               pass
+
+
+def print_gbooks(username, password):
+       """
+       Included here for debugging.
+
+       Either insert it into the code or launch python with the "-i" flag
+       """
+       if not GMailAddressBook.is_supported():
+               print "No GMail Support"
+               return
+
+       gab = GMailAddressBook(username, password)
+       for book in gab.get_addressbooks():
+               gab = gab.open_addressbook(book[1])
+               print book
+               for contact in gab.get_contacts():
+                       print "\t", contact
+                       for details in gab.get_contact_details(contact[0]):
+                               print "\t\t", details
+       print gab._gmailContacts
diff --git a/src/dialcentral/maemo_backend.py b/src/dialcentral/maemo_backend.py
new file mode 100644 (file)
index 0000000..24a27d9
--- /dev/null
@@ -0,0 +1,109 @@
+#!/usr/bin/python
+
+# GC Dialer - Front end for Google's Grand Central service.
+# Copyright (C) 2008  Eric Warnke ericew AT gmail DOT com
+# 
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+# 
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+# 
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+"""
+Maemo Contacts Support
+"""
+
+
+import warnings
+
+try:
+       import abook
+except ImportError:
+       abook = None
+
+try:
+       import evolution.ebook as ebook
+except ImportError:
+       ebook = None
+
+
+class MaemoAddressBook(object):
+       """
+       @note Combined the factory and the addressbook for "simplicity" and "cutting down" the number of allocations/deallocations
+       """
+
+       def __init__(self, contextName, context):
+               if not self.is_supported():
+                       return
+               
+               abook.init_with_name(contextName, context)
+               self._book = abook.all_group_get()
+       
+       @classmethod
+       def is_supported(cls):
+               return abook is not None and ebook is not None
+
+       def get_addressbooks(self):
+               """
+               @returns Iterable of (Address Book Factory, Book Id, Book Name)
+               """
+               if not self.is_supported():
+                       return
+
+               yield self, "", ""
+       
+       def open_addressbook(self, bookId):
+               return self
+
+       @staticmethod
+       def contact_source_short_name(contactId):
+               return "M"
+
+       @staticmethod
+       def factory_name():
+               return "Maemo"
+
+       def get_contacts(self):
+               """
+               @returns Iterable of (contact id, contact name)
+               """
+               if not self.is_supported():
+                       return
+               pass
+       
+       def get_contact_details(self, contactId):
+               """
+               @returns Iterable of (Phone Type, Phone Number)
+               """
+               pass
+
+
+def print_maemobooks():
+       """
+       Included here for debugging.
+
+       Either insert it into the code or launch python with the "-i" flag
+       """
+       if not MaemoAddressBook.is_supported():
+               print "No GMail Support"
+               return
+
+       mab = MaemoAddressBook()
+       for book in mab.get_addressbooks():
+               mab = mab.open_addressbook(book[1])
+               print book
+               for contact in mab.get_contacts():
+                       print "\t", contact
+                       for details in mab.get_contact_details(contact[0]):
+                               print "\t\t", details
+       print mab._gmailContacts
+