X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=src%2Fgc_dialer.py;h=bbbb1f69ac71e9810d10117120ed6b69f387a3d3;hb=c363385a1682ec034d0fb8b42de23d8590e35b97;hp=8c42f699430b7de6a0c3609ee1c45690d48338bc;hpb=f3d712b918bec32f7f28891513378c96f74ea3c6;p=gc-dialer diff --git a/src/gc_dialer.py b/src/gc_dialer.py index 8c42f69..bbbb1f6 100755 --- a/src/gc_dialer.py +++ b/src/gc_dialer.py @@ -1,11 +1,25 @@ -#!/usr/bin/python2.5 +#!/usr/bin/python + +# GC Dialer - Front end for Google's Grand Central service. +# Copyright (C) 2008 Mark Bergman bergman AT merctech 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 """ Grandcentral Dialer -Python front-end to a wget script to use grandcentral.com to place outbound VOIP calls. -(C) 2008 Mark Bergman -bergman@merctech.com """ @@ -28,12 +42,6 @@ except ImportError: try: import osso - try: - import abook - import evolution.ebook as evobook - except ImportError: - abook = None - evobook = None except ImportError: osso = None @@ -49,7 +57,8 @@ except ImportError: doctest = None optparse = None -from gcbackend import GCDialer +from gc_backend import GCDialer +from evo_backend import EvolutionAddressBook import socket @@ -123,20 +132,56 @@ def make_idler(func): """ a = [] - def callable(*args, **kwds): + def decorated_func(*args, **kwds): if not a: a.append(func(*args, **kwds)) try: a[0].next() return True except StopIteration: + del a[:] return False - callable.__name__ = func.__name__ - callable.__doc__ = func.__doc__ - callable.__dict__.update(func.__dict__) + decorated_func.__name__ = func.__name__ + decorated_func.__doc__ = func.__doc__ + decorated_func.__dict__.update(func.__dict__) - return callable + return decorated_func + + +class DummyAddressBook(object): + """ + Minimal example of both an addressbook factory and an addressbook + """ + + def get_addressbooks(self): + """ + @returns Iterable of (Address Book Factory, Book Id, Book Name) + """ + yield self, "", "None" + + def open_addressbook(self, bookId): + return self + + @staticmethod + def factory_short_name(): + return "" + + @staticmethod + def factory_name(): + return "" + + def get_contacts(self): + """ + @returns Iterable of (contact id, contact name) + """ + return [] + + def get_contact_details(self, contactId): + """ + @returns Iterable of (Phone Type, Phone Number) + """ + return [] class PhoneTypeSelector(object): @@ -197,8 +242,9 @@ class PhoneTypeSelector(object): class Dialpad(object): + __pretty_app_name__ = "Dialer" __app_name__ = "gc_dialer" - __version__ = "0.7.0" + __version__ = "0.8.0" __app_magic__ = 0xdeadbeef _glade_files = [ @@ -215,6 +261,7 @@ class Dialpad(object): self._clipboard = gtk.clipboard_get() self._deviceIsOnline = True + self.callbacklist = None self._callbackNeedsSetup = True self._recenttime = 0.0 @@ -222,13 +269,7 @@ class Dialpad(object): 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._contactsmodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) self._contactsviewselection = None for path in Dialpad._glade_files: @@ -253,18 +294,17 @@ class Dialpad(object): global hildon self._app = None self._isFullScreen = False - if hildon is not None and isinstance(self._window, gtk.Window): + if hildon is not None and self._window is 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") + gtkMenu = self._widgetTree.get_widget("dialpad_menubar") menu = gtk.Menu() for child in gtkMenu.get_children(): child.reparent(menu) @@ -276,17 +316,17 @@ class Dialpad(object): else: warnings.warn("No Hildon", UserWarning, 2) + if hildon is not None: + self._window.set_title("Keypad") + else: + self._window.set_title("%s - Keypad" % self.__pretty_app_name__) + 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) @@ -318,6 +358,7 @@ class Dialpad(object): } self._widgetTree.signal_autoconnect(callbackMapping) self._widgetTree.get_widget("callbackcombo").get_child().connect("changed", self._on_callbackentry_changed) + self._widgetTree.get_widget("addressbook_combo").get_child().connect("changed", self._on_addressbook_entry_changed) if self._window: self._window.connect("destroy", gtk.main_quit) @@ -325,6 +366,32 @@ class Dialpad(object): self._gcBackend = GCDialer() + self._addressBookFactories = [ + DummyAddressBook(), + EvolutionAddressBook(), + self._gcBackend, + ] + self._addressBook = None + self.open_addressbook(*self.get_addressbooks().next()[0][0:2]) + + self._booksList = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) + for (factoryId, bookId), (factoryName, bookName) in self.get_addressbooks(): + if factoryName and bookName: + entryName = "%s: %s" % (factoryName, bookName) + elif factoryName: + entryName = factoryName + elif bookName: + entryName = bookName + else: + entryName = "Bad name (%d)" % factoryId + row = (str(factoryId), bookId, entryName) + self._booksList.append(row) + + combobox = self._widgetTree.get_widget("addressbook_combo") + combobox.set_model(self._booksList) + combobox.set_text_column(2) + combobox.set_active(0) + self._phoneTypeSelector = PhoneTypeSelector(self._widgetTree, self._gcBackend) if not self._gcBackend.is_authed(): @@ -335,7 +402,9 @@ class Dialpad(object): gobject.idle_add(self._idly_init_contacts_view) def _idly_init_recent_view(self): - """ Deferred initalization of the recent view treeview """ + """ + Deferred initalization of the recent view treeview + """ recentview = self._widgetTree.get_widget("recentview") recentview.set_model(self._recentmodel) @@ -361,10 +430,6 @@ class Dialpad(object): # Add the column to the treeview column = gtk.TreeViewColumn("Contact") - iconrenderer = gtk.CellRendererPixbuf() - column.pack_start(iconrenderer, expand=False) - column.add_attribute(iconrenderer, 'pixbuf', 0) - textrenderer = gtk.CellRendererText() column.pack_start(textrenderer, expand=True) column.add_attribute(textrenderer, 'text', 1) @@ -398,12 +463,13 @@ class Dialpad(object): return False def _idly_setup_callback_combo(self): - combobox = self._widgetTree.get_widget("callbackcombo") self.callbacklist = gtk.ListStore(gobject.TYPE_STRING) + for number, description in self._gcBackend.get_callback_numbers().iteritems(): + self.callbacklist.append((make_pretty(number),)) + + combobox = self._widgetTree.get_widget("callbackcombo") combobox.set_model(self.callbacklist) combobox.set_text_column(0) - 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 @@ -428,10 +494,9 @@ class Dialpad(object): 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) + ("",)) + contactType = (self._addressBook.factory_short_name(),) + for contactId, contactName in self._addressBook.get_contacts(): + self._contactsmodel.append(contactType + (contactName, "", contactId) + ("",)) yield # restart the treeview data rendering @@ -473,20 +538,33 @@ class Dialpad(object): error_dialog.connect("response", close, self) error_dialog.run() + def get_addressbooks(self): + """ + @returns Iterable of ((Factory Id, Book Id), (Factory Name, Book Name)) + """ + for i, factory in enumerate(self._addressBookFactories): + for bookFactory, bookId, bookName in factory.get_addressbooks(): + yield (i, bookId), (factory.factory_name(), bookName) + + def open_addressbook(self, bookFactoryId, bookId): + self._addressBook = self._addressBookFactories[bookFactoryId].open_addressbook(bookId) + self._contactstime = 0 + gobject.idle_add(self._idly_populate_contactsview) + def set_number(self, number): """ Set the callback phonenumber """ self._phonenumber = make_ugly(number) self._prettynumber = make_pretty(self._phonenumber) - self._numberdisplay.set_label("%s" % ( self._prettynumber ) ) + self._numberdisplay.set_label("%s" % (self._prettynumber)) def set_account_number(self): """ Displays current account number """ accountnumber = self._gcBackend.get_account_number() - self._widgetTree.get_widget("gcnumberlabel").set_label("%s" % (accountnumber)) + self._widgetTree.get_widget("gcnumber_display").set_label("%s" % (accountnumber)) def _on_close(self, *args): gtk.main_quit() @@ -527,7 +605,7 @@ class Dialpad(object): self._isFullScreen = True else: self._isFullScreen = False - + def _on_key_press(self, widget, event, *args): """ @note Hildon specific @@ -578,13 +656,21 @@ class Dialpad(object): self._notebook.set_current_page(0) self._recentviewselection.unselect_all() + def _on_addressbook_entry_changed(self, *args, **kwds): + combobox = self._widgetTree.get_widget("addressbook_combo") + itr = combobox.get_active_iter() + + factoryId = int(self._booksList.get_value(itr, 0)) + bookId = self._booksList.get_value(itr, 1) + self.open_addressbook(factoryId, bookId) + 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 = self._addressBook.get_contact_details(contactId) contactDetails = [phoneNumber for phoneNumber in contactDetails] if len(contactDetails) == 0: @@ -608,9 +694,11 @@ class Dialpad(object): elif page_num == 3 and self._callbackNeedsSetup: gobject.idle_add(self._idly_setup_callback_combo) - if hildon: - hildonTitle = self._notebook.get_tab_label(self._notebook.get_nth_page(page_num)).get_text() - self._window.set_title(hildonTitle) + tabTitle = self._notebook.get_tab_label(self._notebook.get_nth_page(page_num)).get_text() + if hildon is not None: + self._window.set_title(tabTitle) + else: + self._window.set_title("%s - %s" % (self.__pretty_app_name__, tabTitle)) def _on_dial_clicked(self, widget): """ @@ -678,7 +766,7 @@ class DummyOptions(object): if __name__ == "__main__": if hildon is not None: - gtk.set_application_name("Dialer") + gtk.set_application_name(Dialpad.__pretty_app_name__) if optparse is not None: parser = optparse.OptionParser()