From 45787448ebd8b8f2cf8e2a26f750f4a432911306 Mon Sep 17 00:00:00 2001 From: epage Date: Fri, 3 Oct 2008 00:05:36 +0000 Subject: [PATCH] Merging in the tweaks branch git-svn-id: file:///svnroot/gc-dialer/trunk@160 c39d3808-3fe2-4d86-a59f-b7f623ee9f21 --- src/dialcentral/evo_backend.py | 21 ++++++-- src/dialcentral/gc_backend.py | 7 ++- src/dialcentral/gc_dialer.py | 88 +++++++++++++++++++++++++++--- src/dialcentral/gmail_backend.py | 104 ++++++++++++++++++++++++++++++++++++ src/dialcentral/maemo_backend.py | 109 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 316 insertions(+), 13 deletions(-) create mode 100644 src/dialcentral/gmail_backend.py create mode 100644 src/dialcentral/maemo_backend.py diff --git a/src/dialcentral/evo_backend.py b/src/dialcentral/evo_backend.py index c094c2e..c1c0487 100644 --- a/src/dialcentral/evo_backend.py +++ b/src/dialcentral/evo_backend.py @@ -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. diff --git a/src/dialcentral/gc_backend.py b/src/dialcentral/gc_backend.py index d1641de..cda6eb6 100644 --- a/src/dialcentral/gc_backend.py +++ b/src/dialcentral/gc_backend.py @@ -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 diff --git a/src/dialcentral/gc_dialer.py b/src/dialcentral/gc_dialer.py index a47a467..effb344 100755 --- a/src/dialcentral/gc_dialer.py +++ b/src/dialcentral/gc_dialer.py @@ -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 index 0000000..f29c7ca --- /dev/null +++ b/src/dialcentral/gmail_backend.py @@ -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 index 0000000..24a27d9 --- /dev/null +++ b/src/dialcentral/maemo_backend.py @@ -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 + -- 1.7.9.5