+++ /dev/null
-#!/usr/bin/env python
-
-import os
-import time
-import datetime
-import ConfigParser
-
-import dbus
-import osso.alarmd as alarmd
-
-
-class AlarmHandler(object):
-
- _INVALID_COOKIE = -1
- _TITLE = "Dialcentral Notifications"
- _LAUNCHER = os.path.abspath(os.path.join(os.path.dirname(__file__), "alarm_notify.py"))
- _REPEAT_FOREVER = -1
- _DEFAULT_FLAGS = (
- alarmd.ALARM_EVENT_NO_DIALOG |
- alarmd.ALARM_EVENT_NO_SNOOZE |
- alarmd.ALARM_EVENT_CONNECTED
- )
-
- def __init__(self):
- self._recurrence = 5
-
- bus = dbus.SystemBus()
- self._alarmdDBus = bus.get_object("com.nokia.alarmd", "/com/nokia/alarmd");
- self._alarmCookie = self._INVALID_COOKIE
- self._launcher = self._LAUNCHER
-
- def load_settings(self, config, sectionName):
- try:
- self._recurrence = config.getint(sectionName, "recurrence")
- self._alarmCookie = config.getint(sectionName, "alarmCookie")
- launcher = config.get(sectionName, "notifier")
- if launcher:
- self._launcher = launcher
- except ConfigParser.NoOptionError:
- pass
-
- def save_settings(self, config, sectionName):
- config.set(sectionName, "recurrence", str(self._recurrence))
- config.set(sectionName, "alarmCookie", str(self._alarmCookie))
- launcher = self._launcher if self._launcher != self._LAUNCHER else ""
- config.set(sectionName, "notifier", launcher)
-
- def apply_settings(self, enabled, recurrence):
- if recurrence != self._recurrence or enabled != self.isEnabled:
- if self.isEnabled:
- self._clear_alarm()
- if enabled:
- self._set_alarm(recurrence)
- self._recurrence = int(recurrence)
-
- @property
- def recurrence(self):
- return self._recurrence
-
- @property
- def isEnabled(self):
- return self._alarmCookie != self._INVALID_COOKIE
-
- def _get_start_time(self, recurrence):
- now = datetime.datetime.now()
- startTimeMinute = now.minute + max(recurrence, 5) # being safe
- startTimeHour = now.hour + int(startTimeMinute / 60)
- startTimeMinute = startTimeMinute % 59
- now.replace(minute=startTimeMinute)
- timestamp = int(time.mktime(now.timetuple()))
- return timestamp
-
- def _set_alarm(self, recurrence):
- assert 1 <= recurrence, "Notifications set to occur too frequently: %d" % recurrence
- alarmTime = self._get_start_time(recurrence)
-
- #Setup the alarm arguments so that they can be passed to the D-Bus add_event method
- action = []
- action.extend(['flags', self._DEFAULT_FLAGS])
- action.extend(['title', self._TITLE])
- action.extend(['path', self._launcher])
- action.extend([
- 'arguments',
- dbus.Array(
- [alarmTime, int(27)],
- signature=dbus.Signature('v')
- )
- ]) #int(27) used in place of alarm_index
-
- event = []
- event.extend([dbus.ObjectPath('/AlarmdEventRecurring'), dbus.UInt32(4)])
- event.extend(['action', dbus.ObjectPath('/AlarmdActionExec')]) #use AlarmdActionExec instead of AlarmdActionDbus
- event.append(dbus.UInt32(len(action) / 2))
- event.extend(action)
- event.extend(['time', dbus.Int64(alarmTime)])
- event.extend(['recurr_interval', dbus.UInt32(recurrence)])
- event.extend(['recurr_count', dbus.Int32(self._REPEAT_FOREVER)])
-
- self._alarmCookie = self._alarmdDBus.add_event(*event);
-
- def _clear_alarm(self):
- if self._alarmCookie == self._INVALID_COOKIE:
- return
- deleteResult = self._alarmdDBus.del_event(dbus.Int32(self._alarmCookie))
- self._alarmCookie = self._INVALID_COOKIE
- assert deleteResult != -1, "Deleting of alarm event failed"
-
-
-def main():
- import ConfigParser
- import constants
- try:
- import optparse
- except ImportError:
- return
-
- parser = optparse.OptionParser()
- parser.add_option("-x", "--display", action="store_true", dest="display", help="Display data")
- parser.add_option("-e", "--enable", action="store_true", dest="enabled", help="Whether the alarm should be enabled or not", default=False)
- parser.add_option("-d", "--disable", action="store_false", dest="enabled", help="Whether the alarm should be enabled or not", default=False)
- parser.add_option("-r", "--recurrence", action="store", type="int", dest="recurrence", help="How often the alarm occurs", default=5)
- (commandOptions, commandArgs) = parser.parse_args()
-
- alarmHandler = AlarmHandler()
- config = ConfigParser.SafeConfigParser()
- config.read(constants._user_settings_)
- alarmHandler.load_settings(config, "alarm")
-
- if commandOptions.display:
- print "Alarm (%s) is %s for every %d minutes" % (
- alarmHandler._alarmCookie,
- "enabled" if alarmHandler.isEnabled else "disabled",
- alarmHandler.recurrence,
- )
- else:
- isEnabled = commandOptions.enabled
- recurrence = commandOptions.recurrence
- alarmHandler.apply_settings(isEnabled, recurrence)
-
- alarmHandler.save_settings(config, "alarm")
- configFile = open(constants._user_settings_, "wb")
- try:
- config.write(configFile)
- finally:
- configFile.close()
-
-
-if __name__ == "__main__":
- main()
+++ /dev/null
-#!/usr/bin/env python
-
-import os
-import filecmp
-import ConfigParser
-import pprint
-
-import constants
-import gv_backend
-
-
-def get_missed(backend):
- missedPage = backend._browser.download(backend._missedCallsURL)
- missedJson = backend._grab_json(missedPage)
- return missedJson
-
-
-def get_voicemail(backend):
- voicemailPage = backend._browser.download(backend._voicemailURL)
- voicemailJson = backend._grab_json(voicemailPage)
- return voicemailJson
-
-
-def get_sms(backend):
- smsPage = backend._browser.download(backend._smsURL)
- smsJson = backend._grab_json(smsPage)
- return smsJson
-
-
-def remove_reltime(data):
- for messageData in data["messages"].itervalues():
- del messageData["relativeStartTime"]
-
-
-def is_type_changed(backend, type, get_material):
- jsonMaterial = get_material(backend)
- unreadCount = jsonMaterial["unreadCounts"][type]
-
- previousSnapshotPath = os.path.join(constants._data_path_, "snapshot_%s.old.json" % type)
- currentSnapshotPath = os.path.join(constants._data_path_, "snapshot_%s.json" % type)
-
- try:
- os.remove(previousSnapshotPath)
- except OSError, e:
- # check if failed purely because the old file didn't exist, which is fine
- if e.errno != 2:
- raise
- try:
- os.rename(currentSnapshotPath, previousSnapshotPath)
- previousExists = True
- except OSError, e:
- # check if failed purely because the new old file didn't exist, which is fine
- if e.errno != 2:
- raise
- previousExists = False
-
- remove_reltime(jsonMaterial)
- textMaterial = pprint.pformat(jsonMaterial)
- currentSnapshot = file(currentSnapshotPath, "w")
- try:
- currentSnapshot.write(textMaterial)
- finally:
- currentSnapshot.close()
-
- if unreadCount == 0 or not previousExists:
- return False
-
- seemEqual = filecmp.cmp(previousSnapshotPath, currentSnapshotPath)
- return not seemEqual
-
-
-def is_changed():
- gvCookiePath = os.path.join(constants._data_path_, "gv_cookies.txt")
- backend = gv_backend.GVDialer(gvCookiePath)
-
- loggedIn = False
-
- if not loggedIn:
- loggedIn = backend.is_authed()
-
- config = ConfigParser.SafeConfigParser()
- config.read(constants._user_settings_)
- if not loggedIn:
- import base64
- try:
- blobs = (
- config.get(constants.__pretty_app_name__, "bin_blob_%i" % i)
- for i in xrange(2)
- )
- creds = (
- base64.b64decode(blob)
- for blob in blobs
- )
- username, password = tuple(creds)
- loggedIn = backend.login(username, password)
- except ConfigParser.NoOptionError, e:
- pass
- except ConfigParser.NoSectionError, e:
- pass
-
- try:
- notifyOnMissed = config.getboolean("2 - Account Info", "notifyOnMissed")
- notifyOnVoicemail = config.getboolean("2 - Account Info", "notifyOnVoicemail")
- notifyOnSms = config.getboolean("2 - Account Info", "notifyOnSms")
- except ConfigParser.NoOptionError, e:
- notifyOnMissed = False
- notifyOnVoicemail = False
- notifyOnSms = False
- except ConfigParser.NoSectionError, e:
- notifyOnMissed = False
- notifyOnVoicemail = False
- notifyOnSms = False
-
- assert loggedIn
- notifySources = []
- if notifyOnMissed:
- notifySources.append(("missed", get_missed))
- if notifyOnVoicemail:
- notifySources.append(("voicemail", get_voicemail))
- if notifyOnSms:
- notifySources.append(("sms", get_sms))
-
- notifyUser = False
- for type, get_material in notifySources:
- if is_type_changed(backend, type, get_material):
- notifyUser = True
- return notifyUser
-
-
-def notify_on_change():
- notifyUser = is_changed()
-
- if notifyUser:
- import led_handler
- led = led_handler.LedHandler()
- led.on()
-
-
-if __name__ == "__main__":
- notify_on_change()
+++ /dev/null
-#!/usr/bin/python2.5
-
-"""
-DialCentral - Front end for Google's GoogleVoice 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
-
-@todo Add "login failed" and "attempting login" notifications
-"""
-
-
-from __future__ import with_statement
-
-import sys
-import gc
-import os
-import threading
-import base64
-import ConfigParser
-import itertools
-import logging
-
-import gtk
-import gtk.glade
-
-import constants
-import hildonize
-import gtk_toolbox
-
-
-def getmtime_nothrow(path):
- try:
- return os.path.getmtime(path)
- except Exception:
- return 0
-
-
-def display_error_message(msg):
- error_dialog = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, msg)
-
- def close(dialog, response):
- dialog.destroy()
- error_dialog.connect("response", close)
- error_dialog.run()
-
-
-class Dialcentral(object):
-
- _glade_files = [
- os.path.join(os.path.dirname(__file__), "dialcentral.glade"),
- os.path.join(os.path.dirname(__file__), "../lib/dialcentral.glade"),
- '/usr/lib/dialcentral/dialcentral.glade',
- ]
-
- KEYPAD_TAB = 0
- RECENT_TAB = 1
- MESSAGES_TAB = 2
- CONTACTS_TAB = 3
- ACCOUNT_TAB = 4
-
- NULL_BACKEND = 0
- GV_BACKEND = 2
- BACKENDS = (NULL_BACKEND, GV_BACKEND)
-
- def __init__(self):
- self._initDone = False
- self._connection = None
- self._osso = None
- self._clipboard = gtk.clipboard_get()
-
- self._credentials = ("", "")
- self._selectedBackendId = self.NULL_BACKEND
- self._defaultBackendId = self.GV_BACKEND
- self._phoneBackends = None
- self._dialpads = None
- self._accountViews = None
- self._messagesViews = None
- self._recentViews = None
- self._contactsViews = None
- self._alarmHandler = None
- self._ledHandler = None
- self._originalCurrentLabels = []
-
- for path in self._glade_files:
- if os.path.isfile(path):
- self._widgetTree = gtk.glade.XML(path)
- break
- else:
- display_error_message("Cannot find dialcentral.glade")
- gtk.main_quit()
- return
-
- self._window = self._widgetTree.get_widget("mainWindow")
- self._notebook = self._widgetTree.get_widget("notebook")
- self._errorDisplay = gtk_toolbox.ErrorDisplay(self._widgetTree)
- self._credentialsDialog = gtk_toolbox.LoginWindow(self._widgetTree)
-
- self._isFullScreen = False
- self._app = hildonize.get_app_class()()
- self._window = hildonize.hildonize_window(self._app, self._window)
- hildonize.hildonize_text_entry(self._widgetTree.get_widget("usernameentry"))
- hildonize.hildonize_password_entry(self._widgetTree.get_widget("passwordentry"))
-
- for scrollingWidget in (
- 'recent_scrolledwindow',
- 'message_scrolledwindow',
- 'contacts_scrolledwindow',
- "phoneSelectionMessages_scrolledwindow",
- "smsMessages_scrolledwindow",
- ):
- hildonize.hildonize_scrollwindow(self._widgetTree.get_widget(scrollingWidget))
- for scrollingWidget in (
- "phonetypes_scrolledwindow",
- "smsMessage_scrolledEntry",
- ):
- hildonize.hildonize_scrollwindow_with_viewport(self._widgetTree.get_widget(scrollingWidget))
-
- replacementButtons = [gtk.Button("Test")]
- menu = hildonize.hildonize_menu(
- self._window,
- self._widgetTree.get_widget("dialpad_menubar"),
- replacementButtons
- )
-
- self._window.connect("key-press-event", self._on_key_press)
- self._window.connect("window-state-event", self._on_window_state_change)
- if not hildonize.IS_HILDON_SUPPORTED:
- logging.warning("No hildonization support")
-
- hildonize.set_application_title(self._window, "%s" % constants.__pretty_app_name__)
-
- self._window.connect("destroy", self._on_close)
- self._window.set_default_size(800, 300)
- self._window.show_all()
-
- self._loginSink = gtk_toolbox.threaded_stage(
- gtk_toolbox.comap(
- self._attempt_login,
- gtk_toolbox.null_sink(),
- )
- )
-
- backgroundSetup = threading.Thread(target=self._idle_setup)
- backgroundSetup.setDaemon(True)
- backgroundSetup.start()
-
- def _idle_setup(self):
- """
- If something can be done after the UI loads, push it here so it's not blocking the UI
- """
- # Barebones UI handlers
- try:
- import null_backend
- import null_views
-
- self._phoneBackends = {self.NULL_BACKEND: null_backend.NullDialer()}
- with gtk_toolbox.gtk_lock():
- self._dialpads = {self.NULL_BACKEND: null_views.Dialpad(self._widgetTree)}
- self._accountViews = {self.NULL_BACKEND: null_views.AccountInfo(self._widgetTree)}
- self._recentViews = {self.NULL_BACKEND: null_views.RecentCallsView(self._widgetTree)}
- self._messagesViews = {self.NULL_BACKEND: null_views.MessagesView(self._widgetTree)}
- self._contactsViews = {self.NULL_BACKEND: null_views.ContactsView(self._widgetTree)}
-
- self._dialpads[self._selectedBackendId].enable()
- self._accountViews[self._selectedBackendId].enable()
- self._recentViews[self._selectedBackendId].enable()
- self._messagesViews[self._selectedBackendId].enable()
- self._contactsViews[self._selectedBackendId].enable()
- except Exception, e:
- with gtk_toolbox.gtk_lock():
- self._errorDisplay.push_exception()
-
- # Setup maemo specifics
- try:
- try:
- import osso
- except (ImportError, OSError):
- osso = None
- self._osso = None
- if osso is not None:
- self._osso = osso.Context(constants.__app_name__, constants.__version__, False)
- device = osso.DeviceState(self._osso)
- device.set_device_state_callback(self._on_device_state_change, 0)
- else:
- logging.warning("No device state support")
-
- try:
- import alarm_handler
- self._alarmHandler = alarm_handler.AlarmHandler()
- except (ImportError, OSError):
- alarm_handler = None
- except Exception:
- with gtk_toolbox.gtk_lock():
- self._errorDisplay.push_exception()
- alarm_handler = None
- logging.warning("No notification support")
- if hildonize.IS_HILDON_SUPPORTED:
- try:
- import led_handler
- self._ledHandler = led_handler.LedHandler()
- except Exception, e:
- logging.exception('LED Handling failed: "%s"' % str(e))
- self._ledHandler = None
- else:
- self._ledHandler = None
-
- try:
- import conic
- except (ImportError, OSError):
- conic = None
- self._connection = None
- if conic is not None:
- self._connection = conic.Connection()
- self._connection.connect("connection-event", self._on_connection_change, constants.__app_magic__)
- self._connection.request_connection(conic.CONNECT_FLAG_NONE)
- else:
- logging.warning("No connection support")
- except Exception, e:
- with gtk_toolbox.gtk_lock():
- self._errorDisplay.push_exception()
-
- # Setup costly backends
- try:
- import gv_backend
- import file_backend
- import gv_views
-
- try:
- os.makedirs(constants._data_path_)
- except OSError, e:
- if e.errno != 17:
- raise
- gvCookiePath = os.path.join(constants._data_path_, "gv_cookies.txt")
-
- self._phoneBackends.update({
- self.GV_BACKEND: gv_backend.GVDialer(gvCookiePath),
- })
- with gtk_toolbox.gtk_lock():
- unifiedDialpad = gv_views.Dialpad(self._widgetTree, self._errorDisplay)
- self._dialpads.update({
- self.GV_BACKEND: unifiedDialpad,
- })
- self._accountViews.update({
- self.GV_BACKEND: gv_views.AccountInfo(
- self._widgetTree, self._phoneBackends[self.GV_BACKEND], self._alarmHandler, self._errorDisplay
- ),
- })
- self._accountViews[self.GV_BACKEND].save_everything = self._save_settings
- self._recentViews.update({
- self.GV_BACKEND: gv_views.RecentCallsView(
- self._widgetTree, self._phoneBackends[self.GV_BACKEND], self._errorDisplay
- ),
- })
- self._messagesViews.update({
- self.GV_BACKEND: gv_views.MessagesView(
- self._widgetTree, self._phoneBackends[self.GV_BACKEND], self._errorDisplay
- ),
- })
- self._contactsViews.update({
- self.GV_BACKEND: gv_views.ContactsView(
- self._widgetTree, self._phoneBackends[self.GV_BACKEND], self._errorDisplay
- ),
- })
-
- fsContactsPath = os.path.join(constants._data_path_, "contacts")
- fileBackend = file_backend.FilesystemAddressBookFactory(fsContactsPath)
-
- self._dialpads[self.GV_BACKEND].number_selected = self._select_action
- self._recentViews[self.GV_BACKEND].number_selected = self._select_action
- self._messagesViews[self.GV_BACKEND].number_selected = self._select_action
- self._contactsViews[self.GV_BACKEND].number_selected = self._select_action
-
- addressBooks = [
- self._phoneBackends[self.GV_BACKEND],
- fileBackend,
- ]
- mergedBook = gv_views.MergedAddressBook(addressBooks, gv_views.MergedAddressBook.advanced_lastname_sorter)
- self._contactsViews[self.GV_BACKEND].append(mergedBook)
- self._contactsViews[self.GV_BACKEND].extend(addressBooks)
- self._contactsViews[self.GV_BACKEND].open_addressbook(*self._contactsViews[self.GV_BACKEND].get_addressbooks().next()[0][0:2])
-
- callbackMapping = {
- "on_paste": self._on_paste,
- "on_refresh": self._on_menu_refresh,
- "on_clearcookies_clicked": self._on_clearcookies_clicked,
- "on_about_activate": self._on_about_activate,
- }
- if hildonize.GTK_MENU_USED:
- self._widgetTree.signal_autoconnect(callbackMapping)
- self._notebook.connect("switch-page", self._on_notebook_switch_page)
- self._widgetTree.get_widget("clearcookies").connect("clicked", self._on_clearcookies_clicked)
-
- with gtk_toolbox.gtk_lock():
- self._originalCurrentLabels = [
- self._notebook.get_tab_label(self._notebook.get_nth_page(pageIndex)).get_text()
- for pageIndex in xrange(self._notebook.get_n_pages())
- ]
- self._notebookTapHandler = gtk_toolbox.TapOrHold(self._notebook)
- self._notebookTapHandler.enable()
- self._notebookTapHandler.on_tap = self._reset_tab_refresh
- self._notebookTapHandler.on_hold = self._on_tab_refresh
- self._notebookTapHandler.on_holding = self._set_tab_refresh
- self._notebookTapHandler.on_cancel = self._reset_tab_refresh
-
- self._initDone = True
-
- config = ConfigParser.SafeConfigParser()
- config.read(constants._user_settings_)
- with gtk_toolbox.gtk_lock():
- self.load_settings(config)
- except Exception, e:
- with gtk_toolbox.gtk_lock():
- self._errorDisplay.push_exception()
- finally:
- self._spawn_attempt_login(2)
-
- def _spawn_attempt_login(self, *args):
- self._loginSink.send(args)
-
- def _attempt_login(self, numOfAttempts = 10, force = False):
- """
- @note This must be run outside of the UI lock
- """
- try:
- assert 0 <= numOfAttempts, "That was pointless having 0 or less login attempts"
- assert self._initDone, "Attempting login before app is fully loaded"
-
- serviceId = self.NULL_BACKEND
- loggedIn = False
- if not force:
- try:
- self.refresh_session()
- serviceId = self._defaultBackendId
- loggedIn = True
- except Exception, e:
- logging.exception('Session refresh failed with the following message "%s"' % str(e))
-
- if not loggedIn:
- loggedIn, serviceId = self._login_by_user(numOfAttempts)
-
- with gtk_toolbox.gtk_lock():
- self._change_loggedin_status(serviceId)
- if loggedIn:
- hildonize.show_information_banner(self._window, "Logged In")
- except Exception, e:
- with gtk_toolbox.gtk_lock():
- self._errorDisplay.push_exception()
-
- def refresh_session(self):
- """
- @note Thread agnostic
- """
- assert self._initDone, "Attempting login before app is fully loaded"
-
- loggedIn = False
- if not loggedIn:
- loggedIn = self._login_by_cookie()
- if not loggedIn:
- loggedIn = self._login_by_settings()
-
- if not loggedIn:
- raise RuntimeError("Login Failed")
-
- def _login_by_cookie(self):
- """
- @note Thread agnostic
- """
- loggedIn = self._phoneBackends[self._defaultBackendId].is_authed()
- if loggedIn:
- logging.info("Logged into %r through cookies" % self._phoneBackends[self._defaultBackendId])
- return loggedIn
-
- def _login_by_settings(self):
- """
- @note Thread agnostic
- """
- username, password = self._credentials
- loggedIn = self._phoneBackends[self._defaultBackendId].login(username, password)
- if loggedIn:
- self._credentials = username, password
- logging.info("Logged into %r through settings" % self._phoneBackends[self._defaultBackendId])
- return loggedIn
-
- def _login_by_user(self, numOfAttempts):
- """
- @note This must be run outside of the UI lock
- """
- loggedIn, (username, password) = False, self._credentials
- tmpServiceId = self.GV_BACKEND
- for attemptCount in xrange(numOfAttempts):
- if loggedIn:
- break
- with gtk_toolbox.gtk_lock():
- credentials = self._credentialsDialog.request_credentials(
- defaultCredentials = self._credentials
- )
- if not self._phoneBackends[tmpServiceId].get_callback_number():
- # subtle reminder to the users to configure things
- self._notebook.set_current_page(self.ACCOUNT_TAB)
- username, password = credentials
- loggedIn = self._phoneBackends[tmpServiceId].login(username, password)
-
- if loggedIn:
- serviceId = tmpServiceId
- self._credentials = username, password
- logging.info("Logged into %r through user request" % self._phoneBackends[serviceId])
- else:
- serviceId = self.NULL_BACKEND
- self._notebook.set_current_page(self.ACCOUNT_TAB)
-
- return loggedIn, serviceId
-
- def _select_action(self, action, number, message):
- self.refresh_session()
- if action == "select":
- self._dialpads[self._selectedBackendId].set_number(number)
- self._notebook.set_current_page(self.KEYPAD_TAB)
- elif action == "dial":
- self._on_dial_clicked(number)
- elif action == "sms":
- self._on_sms_clicked(number, message)
- else:
- assert False, "Unknown action: %s" % action
-
- def _change_loggedin_status(self, newStatus):
- oldStatus = self._selectedBackendId
- if oldStatus == newStatus:
- return
-
- self._dialpads[oldStatus].disable()
- self._accountViews[oldStatus].disable()
- self._recentViews[oldStatus].disable()
- self._messagesViews[oldStatus].disable()
- self._contactsViews[oldStatus].disable()
-
- self._dialpads[newStatus].enable()
- self._accountViews[newStatus].enable()
- self._recentViews[newStatus].enable()
- self._messagesViews[newStatus].enable()
- self._contactsViews[newStatus].enable()
-
- if self._phoneBackends[self._selectedBackendId].get_callback_number() is None:
- self._phoneBackends[self._selectedBackendId].set_sane_callback()
-
- self._selectedBackendId = newStatus
-
- self._accountViews[self._selectedBackendId].update()
- self._refresh_active_tab()
-
- def load_settings(self, config):
- """
- @note UI Thread
- """
- try:
- self._defaultBackendId = config.getint(constants.__pretty_app_name__, "active")
- blobs = (
- config.get(constants.__pretty_app_name__, "bin_blob_%i" % i)
- for i in xrange(len(self._credentials))
- )
- creds = (
- base64.b64decode(blob)
- for blob in blobs
- )
- self._credentials = tuple(creds)
-
- if self._alarmHandler is not None:
- self._alarmHandler.load_settings(config, "alarm")
- except ConfigParser.NoOptionError, e:
- logging.exception(
- "Settings file %s is missing section %s" % (
- constants._user_settings_,
- e.section,
- ),
- )
- except ConfigParser.NoSectionError, e:
- logging.exception(
- "Settings file %s is missing section %s" % (
- constants._user_settings_,
- e.section,
- ),
- )
-
- for backendId, view in itertools.chain(
- self._dialpads.iteritems(),
- self._accountViews.iteritems(),
- self._messagesViews.iteritems(),
- self._recentViews.iteritems(),
- self._contactsViews.iteritems(),
- ):
- sectionName = "%s - %s" % (backendId, view.name())
- try:
- view.load_settings(config, sectionName)
- except ConfigParser.NoOptionError, e:
- logging.exception(
- "Settings file %s is missing section %s" % (
- constants._user_settings_,
- e.section,
- ),
- )
- except ConfigParser.NoSectionError, e:
- logging.exception(
- "Settings file %s is missing section %s" % (
- constants._user_settings_,
- e.section,
- ),
- )
-
- try:
- previousOrientation = config.getint(constants.__pretty_app_name__, "orientation")
- if previousOrientation == gtk.ORIENTATION_HORIZONTAL:
- hildonize.window_to_landscape(self._window)
- elif previousOrientation == gtk.ORIENTATION_VERTICAL:
- hildonize.window_to_portrait(self._window)
- except ConfigParser.NoOptionError, e:
- logging.exception(
- "Settings file %s is missing section %s" % (
- constants._user_settings_,
- e.section,
- ),
- )
- except ConfigParser.NoSectionError, e:
- logging.exception(
- "Settings file %s is missing section %s" % (
- constants._user_settings_,
- e.section,
- ),
- )
-
- def save_settings(self, config):
- """
- @note Thread Agnostic
- """
- config.add_section(constants.__pretty_app_name__)
- config.set(constants.__pretty_app_name__, "active", str(self._selectedBackendId))
- config.set(constants.__pretty_app_name__, "orientation", str(int(gtk_toolbox.get_screen_orientation())))
- for i, value in enumerate(self._credentials):
- blob = base64.b64encode(value)
- config.set(constants.__pretty_app_name__, "bin_blob_%i" % i, blob)
- config.add_section("alarm")
- if self._alarmHandler is not None:
- self._alarmHandler.save_settings(config, "alarm")
-
- for backendId, view in itertools.chain(
- self._dialpads.iteritems(),
- self._accountViews.iteritems(),
- self._messagesViews.iteritems(),
- self._recentViews.iteritems(),
- self._contactsViews.iteritems(),
- ):
- sectionName = "%s - %s" % (backendId, view.name())
- config.add_section(sectionName)
- view.save_settings(config, sectionName)
-
- def _save_settings(self):
- """
- @note Thread Agnostic
- """
- config = ConfigParser.SafeConfigParser()
- self.save_settings(config)
- with open(constants._user_settings_, "wb") as configFile:
- config.write(configFile)
-
- def _refresh_active_tab(self):
- pageIndex = self._notebook.get_current_page()
- if pageIndex == self.CONTACTS_TAB:
- self._contactsViews[self._selectedBackendId].update(force=True)
- elif pageIndex == self.RECENT_TAB:
- self._recentViews[self._selectedBackendId].update(force=True)
- elif pageIndex == self.MESSAGES_TAB:
- self._messagesViews[self._selectedBackendId].update(force=True)
-
- if pageIndex in (self.RECENT_TAB, self.MESSAGES_TAB):
- if self._ledHandler is not None:
- self._ledHandler.off()
-
- def _on_close(self, *args, **kwds):
- try:
- if self._osso is not None:
- self._osso.close()
-
- if self._initDone:
- self._save_settings()
- finally:
- gtk.main_quit()
-
- 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
- """
- try:
- if memory_low:
- for backendId in self.BACKENDS:
- self._phoneBackends[backendId].clear_caches()
- self._contactsViews[self._selectedBackendId].clear_caches()
- gc.collect()
-
- if save_unsaved_data or shutdown:
- self._save_settings()
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_connection_change(self, connection, event, magicIdentifier):
- """
- @note Hildon specific
- """
- try:
- import conic
-
- status = event.get_status()
- error = event.get_error()
- iap_id = event.get_iap_id()
- bearer = event.get_bearer_type()
-
- if status == conic.STATUS_CONNECTED:
- if self._initDone:
- self._spawn_attempt_login(2)
- elif status == conic.STATUS_DISCONNECTED:
- if self._initDone:
- self._defaultBackendId = self._selectedBackendId
- self._change_loggedin_status(self.NULL_BACKEND)
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_window_state_change(self, widget, event, *args):
- """
- @note Hildon specific
- """
- try:
- if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
- self._isFullScreen = True
- else:
- self._isFullScreen = False
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_key_press(self, widget, event, *args):
- """
- @note Hildon specific
- """
- try:
- if (
- event.keyval == gtk.keysyms.F6 or
- event.keyval == gtk.keysyms.Return and event.get_state() & gtk.gdk.CONTROL_MASK
- ):
- if self._isFullScreen:
- self._window.unfullscreen()
- else:
- self._window.fullscreen()
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_clearcookies_clicked(self, *args):
- try:
- self._phoneBackends[self._selectedBackendId].logout()
- self._accountViews[self._selectedBackendId].clear()
- self._recentViews[self._selectedBackendId].clear()
- self._messagesViews[self._selectedBackendId].clear()
- self._contactsViews[self._selectedBackendId].clear()
- self._change_loggedin_status(self.NULL_BACKEND)
-
- self._spawn_attempt_login(2, True)
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_notebook_switch_page(self, notebook, page, pageIndex):
- try:
- self._reset_tab_refresh()
-
- didRecentUpdate = False
- didMessagesUpdate = False
-
- if pageIndex == self.RECENT_TAB:
- didRecentUpdate = self._recentViews[self._selectedBackendId].update()
- elif pageIndex == self.MESSAGES_TAB:
- didMessagesUpdate = self._messagesViews[self._selectedBackendId].update()
- elif pageIndex == self.CONTACTS_TAB:
- self._contactsViews[self._selectedBackendId].update()
- elif pageIndex == self.ACCOUNT_TAB:
- self._accountViews[self._selectedBackendId].update()
-
- if didRecentUpdate or didMessagesUpdate:
- if self._ledHandler is not None:
- self._ledHandler.off()
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _set_tab_refresh(self, *args):
- try:
- pageIndex = self._notebook.get_current_page()
- child = self._notebook.get_nth_page(pageIndex)
- self._notebook.get_tab_label(child).set_text("Refresh?")
- except Exception, e:
- self._errorDisplay.push_exception()
- return False
-
- def _reset_tab_refresh(self, *args):
- try:
- pageIndex = self._notebook.get_current_page()
- child = self._notebook.get_nth_page(pageIndex)
- self._notebook.get_tab_label(child).set_text(self._originalCurrentLabels[pageIndex])
- except Exception, e:
- self._errorDisplay.push_exception()
- return False
-
- def _on_tab_refresh(self, *args):
- try:
- self._refresh_active_tab()
- self._reset_tab_refresh()
- except Exception, e:
- self._errorDisplay.push_exception()
- return False
-
- def _on_sms_clicked(self, number, message):
- try:
- assert number, "No number specified"
- assert message, "Empty message"
- try:
- loggedIn = self._phoneBackends[self._selectedBackendId].is_authed()
- except Exception, e:
- loggedIn = False
- self._errorDisplay.push_exception()
- return
-
- if not loggedIn:
- self._errorDisplay.push_message(
- "Backend link with GoogleVoice is not working, please try again"
- )
- return
-
- dialed = False
- try:
- self._phoneBackends[self._selectedBackendId].send_sms(number, message)
- hildonize.show_information_banner(self._window, "Sending to %s" % number)
- dialed = True
- except Exception, e:
- self._errorDisplay.push_exception()
-
- if dialed:
- self._dialpads[self._selectedBackendId].clear()
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_dial_clicked(self, number):
- try:
- assert number, "No number to call"
- try:
- loggedIn = self._phoneBackends[self._selectedBackendId].is_authed()
- except Exception, e:
- loggedIn = False
- self._errorDisplay.push_exception()
- return
-
- if not loggedIn:
- self._errorDisplay.push_message(
- "Backend link with GoogleVoice is not working, please try again"
- )
- return
-
- dialed = False
- try:
- assert self._phoneBackends[self._selectedBackendId].get_callback_number() != "", "No callback number specified"
- self._phoneBackends[self._selectedBackendId].dial(number)
- hildonize.show_information_banner(self._window, "Calling %s" % number)
- dialed = True
- except Exception, e:
- self._errorDisplay.push_exception()
-
- if dialed:
- self._dialpads[self._selectedBackendId].clear()
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_menu_refresh(self, *args):
- try:
- self._refresh_active_tab()
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_paste(self, *args):
- try:
- contents = self._clipboard.wait_for_text()
- if contents is not None:
- self._dialpads[self._selectedBackendId].set_number(contents)
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_about_activate(self, *args):
- try:
- dlg = gtk.AboutDialog()
- dlg.set_name(constants.__pretty_app_name__)
- dlg.set_version("%s-%d" % (constants.__version__, constants.__build__))
- dlg.set_copyright("Copyright 2008 - LGPL")
- dlg.set_comments("Dialcentral is a touch screen enhanced interface to your GoogleVoice account. This application is not affiliated with Google 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.run()
- dlg.destroy()
- except Exception, e:
- self._errorDisplay.push_exception()
-
-
-def run_doctest():
- import doctest
-
- failureCount, testCount = doctest.testmod()
- if not failureCount:
- print "Tests Successful"
- sys.exit(0)
- else:
- sys.exit(1)
-
-
-def run_dialpad():
- _lock_file = os.path.join(constants._data_path_, ".lock")
- #with gtk_toolbox.flock(_lock_file, 0):
- gtk.gdk.threads_init()
-
- if hildonize.IS_HILDON_SUPPORTED:
- gtk.set_application_name(constants.__pretty_app_name__)
- handle = Dialcentral()
- gtk.main()
-
-
-class DummyOptions(object):
-
- def __init__(self):
- self.test = False
-
-
-if __name__ == "__main__":
- logging.basicConfig(level=logging.DEBUG)
- try:
- if len(sys.argv) > 1:
- try:
- import optparse
- except ImportError:
- optparse = None
-
- if optparse is not None:
- parser = optparse.OptionParser()
- parser.add_option("-t", "--test", action="store_true", dest="test", help="Run tests")
- (commandOptions, commandArgs) = parser.parse_args()
- else:
- commandOptions = DummyOptions()
- commandArgs = []
-
- if commandOptions.test:
- run_doctest()
- else:
- run_dialpad()
- finally:
- logging.shutdown()
+++ /dev/null
-<?xml version="1.0"?>
-<glade-interface>
- <!-- interface-requires gtk+ 2.16 -->
- <!-- interface-naming-policy toplevel-contextual -->
- <widget class="GtkWindow" id="mainWindow">
- <property name="title" translatable="yes">Dialer</property>
- <property name="default_width">800</property>
- <property name="default_height">480</property>
- <child>
- <widget class="GtkVBox" id="mainLayout">
- <property name="visible">True</property>
- <child>
- <widget class="GtkMenuBar" id="dialpad_menubar">
- <property name="visible">True</property>
- <child>
- <widget class="GtkMenuItem" id="login_menu_item">
- <property name="visible">True</property>
- <property name="label">_Login</property>
- <property name="use_underline">True</property>
- <signal name="activate" handler="on_clearcookies_clicked"/>
- </widget>
- </child>
- <child>
- <widget class="GtkMenuItem" id="paste_menu_item">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Paste</property>
- <property name="use_underline">True</property>
- <signal name="activate" handler="on_paste"/>
- </widget>
- </child>
- <child>
- <widget class="GtkMenuItem" id="refreshMenuItem">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Refresh</property>
- <property name="use_underline">True</property>
- <signal name="activate" handler="on_refresh"/>
- </widget>
- </child>
- <child>
- <widget class="GtkMenuItem" id="about">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_About</property>
- <property name="use_underline">True</property>
- <signal name="activate" handler="on_about_activate"/>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkEventBox" id="errorEventBox">
- <property name="visible">True</property>
- <child>
- <widget class="GtkHBox" id="errorBox">
- <property name="visible">True</property>
- <child>
- <widget class="GtkImage" id="errorImage">
- <property name="visible">True</property>
- <property name="stock">gtk-dialog-error</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="errorDescription">
- <property name="visible">True</property>
- <property name="use_markup">True</property>
- <property name="ellipsize">end</property>
- <property name="single_line_mode">True</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkImage" id="errorClose">
- <property name="visible">True</property>
- <property name="stock">gtk-close</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkNotebook" id="notebook">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="tab_pos">left</property>
- <property name="show_border">False</property>
- <property name="homogeneous">True</property>
- <child>
- <widget class="GtkVBox" id="keypad_vbox">
- <property name="visible">True</property>
- <child>
- <widget class="GtkHBox" id="hbox3">
- <property name="visible">True</property>
- <child>
- <widget class="GtkLabel" id="numberdisplay">
- <property name="height_request">50</property>
- <property name="visible">True</property>
- <property name="label" translatable="yes"><span size="35000" weight="bold"></span></property>
- <property name="use_markup">True</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="back">
- <property name="label" translatable="yes">gtk-go-back</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- <property name="focus_on_click">False</property>
- <accelerator key="BackSpace" signal="clicked"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkTable" id="keypadview">
- <property name="visible">True</property>
- <property name="n_rows">4</property>
- <property name="n_columns">3</property>
- <property name="homogeneous">True</property>
- <child>
- <widget class="GtkButton" id="digit1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="receives_default">False</property>
- <property name="focus_on_click">False</property>
- <signal name="clicked" handler="on_digit_clicked"/>
- <accelerator key="1" signal="clicked"/>
- <child>
- <widget class="GtkLabel" id="label12">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><span size="33000" weight="bold">1</span>
-<span size="9000"> </span></property>
- <property name="use_markup">True</property>
- </widget>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkButton" id="digit2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="receives_default">False</property>
- <property name="focus_on_click">False</property>
- <signal name="clicked" handler="on_digit_clicked"/>
- <accelerator key="2" signal="clicked"/>
- <accelerator key="a" signal="clicked"/>
- <accelerator key="b" signal="clicked"/>
- <accelerator key="c" signal="clicked"/>
- <child>
- <widget class="GtkLabel" id="label10">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><span size="30000" weight="bold">2</span>
-<span size="12000">ABC</span></property>
- <property name="use_markup">True</property>
- <property name="justify">center</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="digit3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="receives_default">False</property>
- <property name="focus_on_click">False</property>
- <signal name="clicked" handler="on_digit_clicked"/>
- <accelerator key="3" signal="clicked"/>
- <accelerator key="d" signal="clicked"/>
- <accelerator key="e" signal="clicked"/>
- <accelerator key="f" signal="clicked"/>
- <child>
- <widget class="GtkLabel" id="label11">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><span size="30000" weight="bold" stretch="ultraexpanded">3</span>
-<span size="12000">DEF</span></property>
- <property name="use_markup">True</property>
- <property name="justify">center</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="digit4">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="receives_default">False</property>
- <property name="focus_on_click">False</property>
- <signal name="clicked" handler="on_digit_clicked"/>
- <accelerator key="4" signal="clicked"/>
- <accelerator key="g" signal="clicked"/>
- <accelerator key="h" signal="clicked"/>
- <accelerator key="i" signal="clicked"/>
- <child>
- <widget class="GtkLabel" id="label13">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><span size="30000" weight="bold">4</span>
-<span size="12000">GHI</span></property>
- <property name="use_markup">True</property>
- <property name="justify">center</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="digit5">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="receives_default">False</property>
- <property name="focus_on_click">False</property>
- <signal name="clicked" handler="on_digit_clicked"/>
- <accelerator key="5" signal="clicked"/>
- <accelerator key="j" signal="clicked"/>
- <accelerator key="k" signal="clicked"/>
- <accelerator key="l" signal="clicked"/>
- <child>
- <widget class="GtkLabel" id="label14">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><span size="30000" weight="bold">5</span>
-<span size="12000">JKL</span></property>
- <property name="use_markup">True</property>
- <property name="justify">center</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="digit6">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="receives_default">False</property>
- <property name="focus_on_click">False</property>
- <signal name="clicked" handler="on_digit_clicked"/>
- <accelerator key="6" signal="clicked"/>
- <accelerator key="m" signal="clicked"/>
- <accelerator key="n" signal="clicked"/>
- <accelerator key="o" signal="clicked"/>
- <child>
- <widget class="GtkLabel" id="label15">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><span size="30000" weight="bold">6</span>
-<span size="12000">MNO</span></property>
- <property name="use_markup">True</property>
- <property name="justify">center</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="digit7">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="receives_default">False</property>
- <property name="focus_on_click">False</property>
- <signal name="clicked" handler="on_digit_clicked"/>
- <accelerator key="7" signal="clicked"/>
- <accelerator key="p" signal="clicked"/>
- <accelerator key="q" signal="clicked"/>
- <accelerator key="r" signal="clicked"/>
- <accelerator key="s" signal="clicked"/>
- <child>
- <widget class="GtkLabel" id="label16">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><span size="30000" weight="bold">7</span>
-<span size="12000">PQRS</span></property>
- <property name="use_markup">True</property>
- <property name="justify">center</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="digit8">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="receives_default">False</property>
- <property name="focus_on_click">False</property>
- <signal name="clicked" handler="on_digit_clicked"/>
- <accelerator key="8" signal="clicked"/>
- <accelerator key="t" signal="clicked"/>
- <accelerator key="u" signal="clicked"/>
- <accelerator key="v" signal="clicked"/>
- <child>
- <widget class="GtkLabel" id="label17">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><span size="30000" weight="bold">8</span>
-<span size="12000">TUV</span></property>
- <property name="use_markup">True</property>
- <property name="justify">center</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="digit9">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="receives_default">False</property>
- <property name="focus_on_click">False</property>
- <signal name="clicked" handler="on_digit_clicked"/>
- <accelerator key="9" signal="clicked"/>
- <accelerator key="w" signal="clicked"/>
- <accelerator key="x" signal="clicked"/>
- <accelerator key="y" signal="clicked"/>
- <accelerator key="z" signal="clicked"/>
- <child>
- <widget class="GtkLabel" id="label18">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><span size="30000" weight="bold">9</span>
-<span size="12000">WXYZ</span></property>
- <property name="use_markup">True</property>
- <property name="justify">center</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="digit0">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="receives_default">False</property>
- <property name="focus_on_click">False</property>
- <signal name="clicked" handler="on_digit_clicked"/>
- <accelerator key="0" signal="clicked"/>
- <child>
- <widget class="GtkLabel" id="label19">
- <property name="visible">True</property>
- <property name="label" translatable="yes"><span size="33000" weight="bold">0</span>
-<span size="9000"></span></property>
- <property name="use_markup">True</property>
- <property name="justify">center</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="dial">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="receives_default">False</property>
- <accelerator key="Return" signal="clicked"/>
- <child>
- <widget class="GtkHBox" id="hbox1">
- <property name="visible">True</property>
- <child>
- <widget class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="stock">gtk-yes</property>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label8">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">5</property>
- <property name="label" translatable="yes"><span size="17000" weight="bold">Dial</span></property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="left_attach">2</property>
- <property name="right_attach">3</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="sms">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <accelerator key="Return" signal="clicked"/>
- <child>
- <widget class="GtkHBox" id="hbox2">
- <property name="visible">True</property>
- <child>
- <widget class="GtkImage" id="image2">
- <property name="visible">True</property>
- <property name="xalign">1</property>
- <property name="stock">gtk-file</property>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">5</property>
- <property name="label" translatable="yes"><span size="17000" weight="bold">SMS</span></property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="tab_expand">True</property>
- <property name="tab_fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="keypad">
- <property name="height_request">30</property>
- <property name="visible">True</property>
- <property name="label" translatable="yes">Keypad</property>
- </widget>
- <packing>
- <property name="tab_expand">True</property>
- <property name="tab_fill">False</property>
- <property name="type">tab</property>
- </packing>
- </child>
- <child>
- <widget class="GtkVBox" id="vbox2">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkScrolledWindow" id="recent_scrolledwindow">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <child>
- <widget class="GtkTreeView" id="recentview">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="rules_hint">True</property>
- <property name="enable_grid_lines">horizontal</property>
- <property name="enable_tree_lines">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- <property name="tab_expand">True</property>
- <property name="tab_fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="recent">
- <property name="height_request">30</property>
- <property name="visible">True</property>
- <property name="label" translatable="yes">Recent</property>
- </widget>
- <packing>
- <property name="position">1</property>
- <property name="tab_expand">True</property>
- <property name="tab_fill">False</property>
- <property name="type">tab</property>
- </packing>
- </child>
- <child>
- <widget class="GtkVBox" id="vbox3">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkScrolledWindow" id="message_scrolledwindow">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
- <child>
- <widget class="GtkTreeView" id="messages_view">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="rules_hint">True</property>
- <property name="enable_grid_lines">horizontal</property>
- <property name="enable_tree_lines">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="messages">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Messages</property>
- </widget>
- <packing>
- <property name="position">2</property>
- <property name="tab_expand">True</property>
- <property name="tab_fill">False</property>
- <property name="type">tab</property>
- </packing>
- </child>
- <child>
- <widget class="GtkVBox" id="vbox5">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkButton" id="addressbookSelectButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkScrolledWindow" id="contacts_scrolledwindow">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <child>
- <widget class="GtkTreeView" id="contactsview">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="headers_visible">False</property>
- <property name="rules_hint">True</property>
- <property name="fixed_height_mode">True</property>
- <property name="enable_grid_lines">horizontal</property>
- <property name="enable_tree_lines">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="contacts">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Contacts</property>
- </widget>
- <packing>
- <property name="position">3</property>
- <property name="tab_expand">True</property>
- <property name="tab_fill">False</property>
- <property name="type">tab</property>
- </packing>
- </child>
- <child>
- <widget class="GtkTable" id="accountview">
- <property name="visible">True</property>
- <property name="border_width">11</property>
- <property name="n_rows">7</property>
- <property name="n_columns">2</property>
- <child>
- <widget class="GtkLabel" id="gcnumber_display">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">No Number Available</property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="gcnumber_label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="yalign">0</property>
- <property name="ypad">10</property>
- <property name="label" translatable="yes">Account Number:</property>
- </widget>
- <packing>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="callback_number_label">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="yalign">0</property>
- <property name="ypad">10</property>
- <property name="label" translatable="yes">Callback Number:</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label4">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- </widget>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label5">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- </widget>
- <packing>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- </packing>
- </child>
- <child>
- <widget class="GtkVBox" id="vbox1">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkCheckButton" id="missedCheckbox">
- <property name="label" translatable="yes">Missed Calls</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="voicemailCheckbox">
- <property name="label" translatable="yes">Voicemail</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="smsCheckbox">
- <property name="label" translatable="yes">SMS</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">4</property>
- <property name="bottom_attach">5</property>
- </packing>
- </child>
- <child>
- <widget class="GtkCheckButton" id="notifyCheckbox">
- <property name="label" translatable="yes">Notifications</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="yalign">0</property>
- <property name="draw_indicator">True</property>
- </widget>
- <packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="clearcookies">
- <property name="label" translatable="yes">Login</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="focus_on_click">False</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">6</property>
- <property name="bottom_attach">7</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- </widget>
- <packing>
- <property name="top_attach">5</property>
- <property name="bottom_attach">6</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="minutesEntryButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="callbackSelectButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options"></property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- </widget>
- <packing>
- <property name="position">4</property>
- <property name="tab_expand">True</property>
- <property name="tab_fill">False</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="account">
- <property name="height_request">30</property>
- <property name="visible">True</property>
- <property name="label" translatable="yes">Account</property>
- </widget>
- <packing>
- <property name="position">4</property>
- <property name="tab_fill">False</property>
- <property name="type">tab</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <widget class="GtkDialog" id="loginDialog">
- <property name="border_width">5</property>
- <property name="title" translatable="yes">Login</property>
- <property name="resizable">False</property>
- <property name="modal">True</property>
- <property name="window_position">center-on-parent</property>
- <property name="destroy_with_parent">True</property>
- <property name="type_hint">dialog</property>
- <property name="skip_taskbar_hint">True</property>
- <property name="skip_pager_hint">True</property>
- <property name="deletable">False</property>
- <property name="transient_for">mainWindow</property>
- <property name="has_separator">False</property>
- <child internal-child="vbox">
- <widget class="GtkVBox" id="loginLayout">
- <property name="visible">True</property>
- <property name="spacing">2</property>
- <child>
- <widget class="GtkComboBox" id="serviceCombo">
- <property name="visible">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkTable" id="table1">
- <property name="visible">True</property>
- <property name="n_rows">2</property>
- <property name="n_columns">2</property>
- <child>
- <widget class="GtkLabel" id="username_label">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Username</property>
- </widget>
- </child>
- <child>
- <widget class="GtkLabel" id="password_label">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Password</property>
- </widget>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkEntry" id="usernameentry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkEntry" id="passwordentry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="visibility">False</property>
- </widget>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <widget class="GtkHButtonBox" id="dialog-action_area1">
- <property name="visible">True</property>
- <property name="layout_style">end</property>
- <child>
- <widget class="GtkButton" id="logins_close_button">
- <property name="label" translatable="yes">gtk-close</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="loginbutton">
- <property name="label" translatable="yes">gtk-ok</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <widget class="GtkDialog" id="phonetype_dialog">
- <property name="border_width">5</property>
- <property name="title" translatable="yes">Select Phone Type</property>
- <property name="modal">True</property>
- <property name="window_position">center-on-parent</property>
- <property name="default_width">500</property>
- <property name="default_height">300</property>
- <property name="destroy_with_parent">True</property>
- <property name="type_hint">dialog</property>
- <property name="skip_taskbar_hint">True</property>
- <property name="skip_pager_hint">True</property>
- <property name="has_separator">False</property>
- <child internal-child="vbox">
- <widget class="GtkVBox" id="phoneTypeLayout">
- <property name="visible">True</property>
- <property name="spacing">2</property>
- <child>
- <widget class="GtkVBox" id="vbox1">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkScrolledWindow" id="phoneSelectionMessages_scrolledwindow">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
- <child>
- <widget class="GtkTreeView" id="phoneSelectionMessages">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkHSeparator" id="hseparator1">
- <property name="visible">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkVBox" id="vbox2">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkScrolledWindow" id="phonetypes_scrolledwindow">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
- <child>
- <widget class="GtkTreeView" id="phonetypes">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="rules_hint">True</property>
- <property name="enable_search">False</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">3</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <widget class="GtkHButtonBox" id="dialog-action_area3">
- <property name="visible">True</property>
- <property name="layout_style">end</property>
- <child>
- <widget class="GtkButton" id="sms_button">
- <property name="label" translatable="yes">SMS</property>
- <property name="response_id">-4</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="dial_button">
- <property name="label" translatable="yes">Dial</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="select_button">
- <property name="label" translatable="yes">Select</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="cancel_button">
- <property name="label" translatable="yes">gtk-cancel</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">3</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- <widget class="GtkDialog" id="smsDialog">
- <property name="border_width">5</property>
- <property name="title" translatable="yes">Send SMS</property>
- <property name="modal">True</property>
- <property name="window_position">center-on-parent</property>
- <property name="default_width">500</property>
- <property name="default_height">300</property>
- <property name="destroy_with_parent">True</property>
- <property name="type_hint">dialog</property>
- <property name="skip_taskbar_hint">True</property>
- <property name="skip_pager_hint">True</property>
- <property name="has_separator">False</property>
- <child internal-child="vbox">
- <widget class="GtkVBox" id="smsLayout">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="spacing">2</property>
- <child>
- <widget class="GtkVBox" id="vbox1">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkScrolledWindow" id="smsMessages_scrolledwindow">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
- <child>
- <widget class="GtkTreeView" id="smsMessages">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkHSeparator" id="hseparator1">
- <property name="visible">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkVBox" id="vbox2">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkScrolledWindow" id="smsMessage_scrolledEntry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
- <child>
- <widget class="GtkTextView" id="smsEntry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="wrap_mode">word</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkHBox" id="smsCountBox">
- <property name="visible">True</property>
- <child>
- <widget class="GtkLabel" id="smsLetterCount1">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Letters Left:</property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="smsLetterCount">
- <property name="visible">True</property>
- <property name="use_markup">True</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">4</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <widget class="GtkHButtonBox" id="dialog-action_area3">
- <property name="visible">True</property>
- <property name="layout_style">end</property>
- <child>
- <widget class="GtkButton" id="sendSmsButton">
- <property name="label" translatable="yes">Send</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="cancelSmsButton">
- <property name="label" translatable="yes">gtk-cancel</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
-</glade-interface>
+++ /dev/null
-#!/usr/bin/python
-
-import os
-import sys
-import logging
-
-
-sys.path.insert(0,"/usr/lib/dialcentral/")
-
-
-import constants
-import dc_glade
-
-
-try:
- os.makedirs(constants._data_path_)
-except OSError, e:
- if e.errno != 17:
- raise
-
-userLogPath = "%s/dialcentral.log" % constants._data_path_
-logging.basicConfig(level=logging.DEBUG, filename=userLogPath)
-logging.info("Dialcentral %s-%s" % (constants.__version__, constants.__build__))
-
-try:
- dc_glade.run_dialpad()
-finally:
- logging.shutdown()
+++ /dev/null
-#!/usr/bin/env python
-
-import sys
-
-
-sys.path.insert(0,"/usr/lib/dialcentral/")
-
-
-import alarm_notify
-
-
-def notify_on_change():
- notifyUser = alarm_notify.is_changed()
-
- if notifyUser:
- import subprocess
- import led_handler
- led = led_handler.LedHandler()
- led.on()
- soundOn = subprocess.call("/usr/bin/dbus-send --dest=com.nokia.osso_media_server --print-reply /com/nokia/osso_media_server com.nokia.osso_media_server.music.play_media string:file:///usr/lib/gv-notifier/alert.mp3",shell=True)
-
-
-if __name__ == "__main__":
- notify_on_change()
+++ /dev/null
-#!/usr/bin/python
-
-"""
-DialCentral - 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
-
-Filesystem backend for contact support
-"""
-
-
-import os
-import re
-import csv
-
-
-class CsvAddressBook(object):
- """
- Currently supported file format
- @li Has the first line as a header
- @li Escapes with quotes
- @li Comma as delimiter
- @li Column 0 is name, column 1 is number
- """
-
- _nameRe = re.compile("name", re.IGNORECASE)
- _phoneRe = re.compile("phone", re.IGNORECASE)
- _mobileRe = re.compile("mobile", re.IGNORECASE)
-
- def __init__(self, csvPath):
- self.__csvPath = csvPath
- self.__contacts = list(
- self.read_csv(csvPath)
- )
-
- @classmethod
- def read_csv(cls, csvPath):
- try:
- csvReader = iter(csv.reader(open(csvPath, "rU")))
- except IOError, e:
- if e.errno != 2:
- raise
- return
-
- header = csvReader.next()
- nameColumn, phoneColumns = cls._guess_columns(header)
-
- yieldCount = 0
- for row in csvReader:
- contactDetails = []
- for (phoneType, phoneColumn) in phoneColumns:
- try:
- if len(row[phoneColumn]) == 0:
- continue
- contactDetails.append((phoneType, row[phoneColumn]))
- except IndexError:
- pass
- if len(contactDetails) != 0:
- yield str(yieldCount), row[nameColumn], contactDetails
- yieldCount += 1
-
- @classmethod
- def _guess_columns(cls, row):
- names = []
- phones = []
- for i, item in enumerate(row):
- if cls._nameRe.search(item) is not None:
- names.append((item, i))
- elif cls._phoneRe.search(item) is not None:
- phones.append((item, i))
- elif cls._mobileRe.search(item) is not None:
- phones.append((item, i))
- if len(names) == 0:
- names.append(("Name", 0))
- if len(phones) == 0:
- phones.append(("Phone", 1))
-
- return names[0][1], phones
-
- def clear_caches(self):
- pass
-
- @staticmethod
- def factory_name():
- return "csv"
-
- @staticmethod
- def contact_source_short_name(contactId):
- return "csv"
-
- def get_contacts(self):
- """
- @returns Iterable of (contact id, contact name)
- """
- for contact in self.__contacts:
- yield contact[0:2]
-
- def get_contact_details(self, contactId):
- """
- @returns Iterable of (Phone Type, Phone Number)
- """
- contactId = int(contactId)
- return iter(self.__contacts[contactId][2])
-
-
-class FilesystemAddressBookFactory(object):
-
- FILETYPE_SUPPORT = {
- "csv": CsvAddressBook,
- }
-
- def __init__(self, path):
- self.__path = path
-
- def clear_caches(self):
- pass
-
- def get_addressbooks(self):
- """
- @returns Iterable of (Address Book Factory, Book Id, Book Name)
- """
- for root, dirs, filenames in os.walk(self.__path):
- for filename in filenames:
- try:
- name, ext = filename.rsplit(".", 1)
- except ValueError:
- continue
-
- if ext in self.FILETYPE_SUPPORT:
- yield self, os.path.join(root, filename), name
-
- def open_addressbook(self, bookId):
- name, ext = bookId.rsplit(".", 1)
- assert ext in self.FILETYPE_SUPPORT, "Unsupported file extension %s" % ext
- return self.FILETYPE_SUPPORT[ext](bookId)
-
- @staticmethod
- def factory_name():
- return "File"
-
-
-def print_filebooks(contactPath = None):
- """
- Included here for debugging.
-
- Either insert it into the code or launch python with the "-i" flag
- """
- if contactPath is None:
- contactPath = os.path.join(os.path.expanduser("~"), ".dialcentral", "contacts")
-
- abf = FilesystemAddressBookFactory(contactPath)
- for book in abf.get_addressbooks():
- ab = abf.open_addressbook(book[1])
- print book
- for contact in ab.get_contacts():
- print "\t", contact
- for details in ab.get_contact_details(contact[0]):
- print "\t\t", details
+++ /dev/null
-#!/usr/bin/python2.5
-
-"""
-DialCentral - Front end for Google's GoogleVoice 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
-
-@todo Alternate UI for dialogs (stackables)
-"""
-
-from __future__ import with_statement
-
-import ConfigParser
-import logging
-
-import gobject
-import pango
-import gtk
-
-import gtk_toolbox
-import hildonize
-import null_backend
-
-
-def make_ugly(prettynumber):
- """
- function to take a phone number and strip out all non-numeric
- characters
-
- >>> make_ugly("+012-(345)-678-90")
- '01234567890'
- """
- import re
- uglynumber = re.sub('\D', '', prettynumber)
- return uglynumber
-
-
-def make_pretty(phonenumber):
- """
- Function to take a phone number and return the pretty version
- pretty numbers:
- if phonenumber begins with 0:
- ...-(...)-...-....
- if phonenumber begins with 1: ( for gizmo callback numbers )
- 1 (...)-...-....
- if phonenumber is 13 digits:
- (...)-...-....
- if phonenumber is 10 digits:
- ...-....
- >>> make_pretty("12")
- '12'
- >>> make_pretty("1234567")
- '123-4567'
- >>> make_pretty("2345678901")
- '(234)-567-8901'
- >>> make_pretty("12345678901")
- '1 (234)-567-8901'
- >>> make_pretty("01234567890")
- '+012-(345)-678-90'
- """
- if phonenumber is None or phonenumber is "":
- return ""
-
- phonenumber = make_ugly(phonenumber)
-
- if len(phonenumber) < 3:
- return phonenumber
-
- if phonenumber[0] == "0":
- prettynumber = ""
- prettynumber += "+%s" % phonenumber[0:3]
- if 3 < len(phonenumber):
- prettynumber += "-(%s)" % phonenumber[3:6]
- if 6 < len(phonenumber):
- prettynumber += "-%s" % phonenumber[6:9]
- if 9 < len(phonenumber):
- prettynumber += "-%s" % phonenumber[9:]
- return prettynumber
- 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:])
- elif len(phonenumber) > 7:
- prettynumber = "(%s)-%s-%s" % (phonenumber[0:3], phonenumber[3:6], phonenumber[6:])
- return prettynumber
-
-
-def abbrev_relative_date(date):
- """
- >>> abbrev_relative_date("42 hours ago")
- '42 h'
- >>> abbrev_relative_date("2 days ago")
- '2 d'
- >>> abbrev_relative_date("4 weeks ago")
- '4 w'
- """
- parts = date.split(" ")
- return "%s %s" % (parts[0], parts[1][0])
-
-
-class MergedAddressBook(object):
- """
- Merger of all addressbooks
- """
-
- def __init__(self, addressbookFactories, sorter = None):
- self.__addressbookFactories = addressbookFactories
- self.__addressbooks = None
- self.__sort_contacts = sorter if sorter is not None else self.null_sorter
-
- def clear_caches(self):
- self.__addressbooks = None
- for factory in self.__addressbookFactories:
- factory.clear_caches()
-
- 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):
- if self.__addressbooks is None:
- return ""
- 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)
- """
- if self.__addressbooks is None:
- self.__addressbooks = list(
- factory.open_addressbook(id)
- for factory in self.__addressbookFactories
- for (f, id, name) in factory.get_addressbooks()
- )
- 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
-
- def get_contact_details(self, contactId):
- """
- @returns Iterable of (Phone Type, Phone Number)
- """
- if self.__addressbooks is None:
- return []
- bookIndex, originalId = contactId.split("-", 1)
- return self.__addressbooks[int(bookIndex)].get_contact_details(originalId)
-
- @staticmethod
- def null_sorter(contacts):
- """
- Good for speed/low memory
- """
- return contacts
-
- @staticmethod
- def basic_firtname_sorter(contacts):
- """
- Expects names in "First Last" format
- """
- contactsWithKey = [
- (contactName.rsplit(" ", 1)[0], (contactId, contactName))
- for (contactId, contactName) in contacts
- ]
- contactsWithKey.sort()
- return (contactData for (lastName, contactData) in contactsWithKey)
-
- @staticmethod
- def basic_lastname_sorter(contacts):
- """
- Expects names in "First Last" format
- """
- contactsWithKey = [
- (contactName.rsplit(" ", 1)[-1], (contactId, contactName))
- for (contactId, contactName) in contacts
- ]
- contactsWithKey.sort()
- return (contactData for (lastName, contactData) in contactsWithKey)
-
- @staticmethod
- def reversed_firtname_sorter(contacts):
- """
- Expects names in "Last, First" format
- """
- contactsWithKey = [
- (contactName.split(", ", 1)[-1], (contactId, contactName))
- for (contactId, contactName) in contacts
- ]
- contactsWithKey.sort()
- return (contactData for (lastName, contactData) in contactsWithKey)
-
- @staticmethod
- def reversed_lastname_sorter(contacts):
- """
- Expects names in "Last, First" format
- """
- contactsWithKey = [
- (contactName.split(", ", 1)[0], (contactId, contactName))
- for (contactId, contactName) in contacts
- ]
- contactsWithKey.sort()
- return (contactData for (lastName, contactData) in contactsWithKey)
-
- @staticmethod
- def guess_firstname(name):
- if ", " in name:
- return name.split(", ", 1)[-1]
- else:
- return name.rsplit(" ", 1)[0]
-
- @staticmethod
- def guess_lastname(name):
- if ", " in name:
- return name.split(", ", 1)[0]
- else:
- return name.rsplit(" ", 1)[-1]
-
- @classmethod
- def advanced_firstname_sorter(cls, contacts):
- contactsWithKey = [
- (cls.guess_firstname(contactName), (contactId, contactName))
- for (contactId, contactName) in contacts
- ]
- contactsWithKey.sort()
- return (contactData for (lastName, contactData) in contactsWithKey)
-
- @classmethod
- def advanced_lastname_sorter(cls, contacts):
- contactsWithKey = [
- (cls.guess_lastname(contactName), (contactId, contactName))
- for (contactId, contactName) in contacts
- ]
- contactsWithKey.sort()
- return (contactData for (lastName, contactData) in contactsWithKey)
-
-
-class PhoneTypeSelector(object):
-
- ACTION_CANCEL = "cancel"
- ACTION_SELECT = "select"
- ACTION_DIAL = "dial"
- ACTION_SEND_SMS = "sms"
-
- def __init__(self, widgetTree, gcBackend):
- self._gcBackend = gcBackend
- self._widgetTree = widgetTree
-
- self._dialog = self._widgetTree.get_widget("phonetype_dialog")
- self._smsDialog = SmsEntryDialog(self._widgetTree)
-
- self._smsButton = self._widgetTree.get_widget("sms_button")
- self._smsButton.connect("clicked", self._on_phonetype_send_sms)
-
- self._dialButton = self._widgetTree.get_widget("dial_button")
- self._dialButton.connect("clicked", self._on_phonetype_dial)
-
- 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._messagemodel = gtk.ListStore(gobject.TYPE_STRING)
- self._messagesView = self._widgetTree.get_widget("phoneSelectionMessages")
- self._scrollWindow = self._messagesView.get_parent()
-
- self._typemodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
- self._typeviewselection = None
- self._typeview = self._widgetTree.get_widget("phonetypes")
- self._typeview.connect("row-activated", self._on_phonetype_select)
-
- self._action = self.ACTION_CANCEL
-
- def run(self, contactDetails, messages = (), parent = None):
- self._action = self.ACTION_CANCEL
-
- # Add the column to the phone selection tree view
- self._typemodel.clear()
- self._typeview.set_model(self._typemodel)
-
- textrenderer = gtk.CellRendererText()
- numberColumn = gtk.TreeViewColumn("Phone Numbers", textrenderer, text=0)
- self._typeview.append_column(numberColumn)
-
- textrenderer = gtk.CellRendererText()
- typeColumn = gtk.TreeViewColumn("Phone Type", textrenderer, text=1)
- self._typeview.append_column(typeColumn)
-
- for phoneType, phoneNumber in contactDetails:
- display = " - ".join((phoneNumber, phoneType))
- display = phoneType
- row = (phoneNumber, display)
- self._typemodel.append(row)
-
- self._typeviewselection = self._typeview.get_selection()
- self._typeviewselection.set_mode(gtk.SELECTION_SINGLE)
- self._typeviewselection.select_iter(self._typemodel.get_iter_first())
-
- # Add the column to the messages tree view
- self._messagemodel.clear()
- self._messagesView.set_model(self._messagemodel)
-
- textrenderer = gtk.CellRendererText()
- textrenderer.set_property("wrap-mode", pango.WRAP_WORD)
- textrenderer.set_property("wrap-width", 450)
- messageColumn = gtk.TreeViewColumn("")
- messageColumn.pack_start(textrenderer, expand=True)
- messageColumn.add_attribute(textrenderer, "markup", 0)
- messageColumn.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
- self._messagesView.append_column(messageColumn)
- self._messagesView.set_headers_visible(False)
-
- if messages:
- for message in messages:
- row = (message, )
- self._messagemodel.append(row)
- self._messagesView.show()
- self._scrollWindow.show()
- messagesSelection = self._messagesView.get_selection()
- messagesSelection.select_path((len(messages)-1, ))
- else:
- self._messagesView.hide()
- self._scrollWindow.hide()
-
- if parent is not None:
- self._dialog.set_transient_for(parent)
-
- try:
- self._dialog.show()
- if messages:
- self._messagesView.scroll_to_cell((len(messages)-1, ))
-
- userResponse = self._dialog.run()
- finally:
- self._dialog.hide()
-
- if userResponse == gtk.RESPONSE_OK:
- phoneNumber = self._get_number()
- phoneNumber = make_ugly(phoneNumber)
- else:
- phoneNumber = ""
- if not phoneNumber:
- self._action = self.ACTION_CANCEL
-
- if self._action == self.ACTION_SEND_SMS:
- smsMessage = self._smsDialog.run(phoneNumber, messages, parent)
- if not smsMessage:
- phoneNumber = ""
- self._action = self.ACTION_CANCEL
- else:
- smsMessage = ""
-
- self._messagesView.remove_column(messageColumn)
- self._messagesView.set_model(None)
-
- self._typeviewselection.unselect_all()
- self._typeview.remove_column(numberColumn)
- self._typeview.remove_column(typeColumn)
- self._typeview.set_model(None)
-
- return self._action, phoneNumber, smsMessage
-
- def _get_number(self):
- model, itr = self._typeviewselection.get_selected()
- if not itr:
- return ""
-
- phoneNumber = self._typemodel.get_value(itr, 0)
- return phoneNumber
-
- def _on_phonetype_dial(self, *args):
- self._dialog.response(gtk.RESPONSE_OK)
- self._action = self.ACTION_DIAL
-
- def _on_phonetype_send_sms(self, *args):
- self._dialog.response(gtk.RESPONSE_OK)
- self._action = self.ACTION_SEND_SMS
-
- def _on_phonetype_select(self, *args):
- self._dialog.response(gtk.RESPONSE_OK)
- self._action = self.ACTION_SELECT
-
- def _on_phonetype_cancel(self, *args):
- self._dialog.response(gtk.RESPONSE_CANCEL)
- self._action = self.ACTION_CANCEL
-
-
-class SmsEntryDialog(object):
- """
- @todo Add multi-SMS messages like GoogleVoice
- """
-
- MAX_CHAR = 160
-
- def __init__(self, widgetTree):
- self._widgetTree = widgetTree
- self._dialog = self._widgetTree.get_widget("smsDialog")
-
- self._smsButton = self._widgetTree.get_widget("sendSmsButton")
- self._smsButton.connect("clicked", self._on_send)
-
- self._cancelButton = self._widgetTree.get_widget("cancelSmsButton")
- self._cancelButton.connect("clicked", self._on_cancel)
-
- self._letterCountLabel = self._widgetTree.get_widget("smsLetterCount")
-
- self._messagemodel = gtk.ListStore(gobject.TYPE_STRING)
- self._messagesView = self._widgetTree.get_widget("smsMessages")
- self._scrollWindow = self._messagesView.get_parent()
-
- self._smsEntry = self._widgetTree.get_widget("smsEntry")
- self._smsEntry.get_buffer().connect("changed", self._on_entry_changed)
-
- def run(self, number, messages = (), parent = None):
- # Add the column to the messages tree view
- self._messagemodel.clear()
- self._messagesView.set_model(self._messagemodel)
-
- textrenderer = gtk.CellRendererText()
- textrenderer.set_property("wrap-mode", pango.WRAP_WORD)
- textrenderer.set_property("wrap-width", 450)
- messageColumn = gtk.TreeViewColumn("")
- messageColumn.pack_start(textrenderer, expand=True)
- messageColumn.add_attribute(textrenderer, "markup", 0)
- messageColumn.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
- self._messagesView.append_column(messageColumn)
- self._messagesView.set_headers_visible(False)
-
- if messages:
- for message in messages:
- row = (message, )
- self._messagemodel.append(row)
- self._messagesView.show()
- self._scrollWindow.show()
- messagesSelection = self._messagesView.get_selection()
- messagesSelection.select_path((len(messages)-1, ))
- else:
- self._messagesView.hide()
- self._scrollWindow.hide()
-
- self._smsEntry.get_buffer().set_text("")
- self._update_letter_count()
-
- if parent is not None:
- self._dialog.set_transient_for(parent)
-
- try:
- self._dialog.show()
- if messages:
- self._messagesView.scroll_to_cell((len(messages)-1, ))
- self._smsEntry.grab_focus()
-
- userResponse = self._dialog.run()
- finally:
- self._dialog.hide()
-
- if userResponse == gtk.RESPONSE_OK:
- entryBuffer = self._smsEntry.get_buffer()
- enteredMessage = entryBuffer.get_text(entryBuffer.get_start_iter(), entryBuffer.get_end_iter())
- enteredMessage = enteredMessage[0:self.MAX_CHAR]
- else:
- enteredMessage = ""
-
- self._messagesView.remove_column(messageColumn)
- self._messagesView.set_model(None)
-
- return enteredMessage.strip()
-
- def _update_letter_count(self, *args):
- entryLength = self._smsEntry.get_buffer().get_char_count()
- charsLeft = self.MAX_CHAR - entryLength
- self._letterCountLabel.set_text(str(charsLeft))
- if charsLeft < 0:
- self._smsButton.set_sensitive(False)
- else:
- self._smsButton.set_sensitive(True)
-
- def _on_entry_changed(self, *args):
- self._update_letter_count()
-
- def _on_send(self, *args):
- self._dialog.response(gtk.RESPONSE_OK)
-
- def _on_cancel(self, *args):
- self._dialog.response(gtk.RESPONSE_CANCEL)
-
-
-class Dialpad(object):
-
- def __init__(self, widgetTree, errorDisplay):
- self._clipboard = gtk.clipboard_get()
- self._errorDisplay = errorDisplay
- self._smsDialog = SmsEntryDialog(widgetTree)
-
- self._numberdisplay = widgetTree.get_widget("numberdisplay")
- self._smsButton = widgetTree.get_widget("sms")
- self._dialButton = widgetTree.get_widget("dial")
- self._backButton = widgetTree.get_widget("back")
- self._phonenumber = ""
- self._prettynumber = ""
-
- callbackMapping = {
- "on_digit_clicked": self._on_digit_clicked,
- }
- widgetTree.signal_autoconnect(callbackMapping)
- self._dialButton.connect("clicked", self._on_dial_clicked)
- self._smsButton.connect("clicked", self._on_sms_clicked)
-
- self._originalLabel = self._backButton.get_label()
- self._backTapHandler = gtk_toolbox.TapOrHold(self._backButton)
- self._backTapHandler.on_tap = self._on_backspace
- self._backTapHandler.on_hold = self._on_clearall
- self._backTapHandler.on_holding = self._set_clear_button
- self._backTapHandler.on_cancel = self._reset_back_button
-
- self._window = gtk_toolbox.find_parent_window(self._numberdisplay)
- self._keyPressEventId = 0
-
- def enable(self):
- self._dialButton.grab_focus()
- self._backTapHandler.enable()
- self._keyPressEventId = self._window.connect("key-press-event", self._on_key_press)
-
- def disable(self):
- self._window.disconnect(self._keyPressEventId)
- self._keyPressEventId = 0
- self._reset_back_button()
- self._backTapHandler.disable()
-
- def number_selected(self, action, number, message):
- """
- @note Actual dial function is patched in later
- """
- raise NotImplementedError("Horrible unknown error has occurred")
-
- def get_number(self):
- return self._phonenumber
-
- def set_number(self, number):
- """
- Set the number to dial
- """
- try:
- self._phonenumber = make_ugly(number)
- self._prettynumber = make_pretty(self._phonenumber)
- self._numberdisplay.set_label("<span size='30000' weight='bold'>%s</span>" % (self._prettynumber))
- except TypeError, e:
- self._errorDisplay.push_exception()
-
- def clear(self):
- self.set_number("")
-
- @staticmethod
- def name():
- return "Dialpad"
-
- def load_settings(self, config, section):
- pass
-
- def save_settings(self, config, section):
- """
- @note Thread Agnostic
- """
- pass
-
- def _on_key_press(self, widget, event):
- try:
- if event.keyval == ord("v") and event.get_state() & gtk.gdk.CONTROL_MASK:
- contents = self._clipboard.wait_for_text()
- if contents is not None:
- self.set_number(contents)
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_sms_clicked(self, widget):
- try:
- action = PhoneTypeSelector.ACTION_SEND_SMS
- phoneNumber = self.get_number()
-
- message = self._smsDialog.run(phoneNumber, (), self._window)
- if not message:
- phoneNumber = ""
- action = PhoneTypeSelector.ACTION_CANCEL
-
- if action == PhoneTypeSelector.ACTION_CANCEL:
- return
- self.number_selected(action, phoneNumber, message)
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_dial_clicked(self, widget):
- try:
- action = PhoneTypeSelector.ACTION_DIAL
- phoneNumber = self.get_number()
- message = ""
- self.number_selected(action, phoneNumber, message)
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_digit_clicked(self, widget):
- try:
- self.set_number(self._phonenumber + widget.get_name()[-1])
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_backspace(self, taps):
- try:
- self.set_number(self._phonenumber[:-taps])
- self._reset_back_button()
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_clearall(self, taps):
- try:
- self.clear()
- self._reset_back_button()
- except Exception, e:
- self._errorDisplay.push_exception()
- return False
-
- def _set_clear_button(self):
- try:
- self._backButton.set_label("gtk-clear")
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _reset_back_button(self):
- try:
- self._backButton.set_label(self._originalLabel)
- except Exception, e:
- self._errorDisplay.push_exception()
-
-
-class AccountInfo(object):
-
- def __init__(self, widgetTree, backend, alarmHandler, errorDisplay):
- self._errorDisplay = errorDisplay
- self._backend = backend
- self._isPopulated = False
- self._alarmHandler = alarmHandler
- self._notifyOnMissed = False
- self._notifyOnVoicemail = False
- self._notifyOnSms = False
-
- self._callbackList = []
- self._accountViewNumberDisplay = widgetTree.get_widget("gcnumber_display")
- self._callbackSelectButton = widgetTree.get_widget("callbackSelectButton")
- self._onCallbackSelectChangedId = 0
-
- self._notifyCheckbox = widgetTree.get_widget("notifyCheckbox")
- self._minutesEntryButton = widgetTree.get_widget("minutesEntryButton")
- self._missedCheckbox = widgetTree.get_widget("missedCheckbox")
- self._voicemailCheckbox = widgetTree.get_widget("voicemailCheckbox")
- self._smsCheckbox = widgetTree.get_widget("smsCheckbox")
- self._onNotifyToggled = 0
- self._onMinutesChanged = 0
- self._onMissedToggled = 0
- self._onVoicemailToggled = 0
- self._onSmsToggled = 0
- self._applyAlarmTimeoutId = None
-
- self._window = gtk_toolbox.find_parent_window(self._minutesEntryButton)
- self._defaultCallback = ""
-
- def enable(self):
- assert self._backend.is_authed(), "Attempting to enable backend while not logged in"
-
- self._accountViewNumberDisplay.set_use_markup(True)
- self.set_account_number("")
-
- del self._callbackList[:]
- self._onCallbackSelectChangedId = self._callbackSelectButton.connect("clicked", self._on_callbackentry_clicked)
-
- if self._alarmHandler is not None:
- self._notifyCheckbox.set_active(self._alarmHandler.isEnabled)
- self._minutesEntryButton.set_label("%d minutes" % self._alarmHandler.recurrence)
- self._missedCheckbox.set_active(self._notifyOnMissed)
- self._voicemailCheckbox.set_active(self._notifyOnVoicemail)
- self._smsCheckbox.set_active(self._notifyOnSms)
-
- self._onNotifyToggled = self._notifyCheckbox.connect("toggled", self._on_notify_toggled)
- self._onMinutesChanged = self._minutesEntryButton.connect("clicked", self._on_minutes_clicked)
- self._onMissedToggled = self._missedCheckbox.connect("toggled", self._on_missed_toggled)
- self._onVoicemailToggled = self._voicemailCheckbox.connect("toggled", self._on_voicemail_toggled)
- self._onSmsToggled = self._smsCheckbox.connect("toggled", self._on_sms_toggled)
- else:
- self._notifyCheckbox.set_sensitive(False)
- self._minutesEntryButton.set_sensitive(False)
- self._missedCheckbox.set_sensitive(False)
- self._voicemailCheckbox.set_sensitive(False)
- self._smsCheckbox.set_sensitive(False)
-
- self.update(force=True)
-
- def disable(self):
- self._callbackSelectButton.disconnect(self._onCallbackSelectChangedId)
- self._onCallbackSelectChangedId = 0
-
- if self._alarmHandler is not None:
- self._notifyCheckbox.disconnect(self._onNotifyToggled)
- self._minutesEntryButton.disconnect(self._onMinutesChanged)
- self._missedCheckbox.disconnect(self._onNotifyToggled)
- self._voicemailCheckbox.disconnect(self._onNotifyToggled)
- self._smsCheckbox.disconnect(self._onNotifyToggled)
- self._onNotifyToggled = 0
- self._onMinutesChanged = 0
- self._onMissedToggled = 0
- self._onVoicemailToggled = 0
- self._onSmsToggled = 0
- else:
- self._notifyCheckbox.set_sensitive(True)
- self._minutesEntryButton.set_sensitive(True)
- self._missedCheckbox.set_sensitive(True)
- self._voicemailCheckbox.set_sensitive(True)
- self._smsCheckbox.set_sensitive(True)
-
- self.clear()
- del self._callbackList[:]
-
- def get_selected_callback_number(self):
- currentLabel = self._callbackSelectButton.get_label()
- if currentLabel is not None:
- return make_ugly(currentLabel)
- else:
- return ""
-
- def set_account_number(self, number):
- """
- Displays current account number
- """
- self._accountViewNumberDisplay.set_label("<span size='23000' weight='bold'>%s</span>" % (number))
-
- def update(self, force = False):
- if not force and self._isPopulated:
- return False
- self._populate_callback_combo()
- self.set_account_number(self._backend.get_account_number())
- return True
-
- def clear(self):
- self._callbackSelectButton.set_label("")
- self.set_account_number("")
- self._isPopulated = False
-
- def save_everything(self):
- raise NotImplementedError
-
- @staticmethod
- def name():
- return "Account Info"
-
- def load_settings(self, config, section):
- self._defaultCallback = config.get(section, "callback")
- self._notifyOnMissed = config.getboolean(section, "notifyOnMissed")
- self._notifyOnVoicemail = config.getboolean(section, "notifyOnVoicemail")
- self._notifyOnSms = config.getboolean(section, "notifyOnSms")
-
- def save_settings(self, config, section):
- """
- @note Thread Agnostic
- """
- callback = self.get_selected_callback_number()
- config.set(section, "callback", callback)
- config.set(section, "notifyOnMissed", repr(self._notifyOnMissed))
- config.set(section, "notifyOnVoicemail", repr(self._notifyOnVoicemail))
- config.set(section, "notifyOnSms", repr(self._notifyOnSms))
-
- def _populate_callback_combo(self):
- self._isPopulated = True
- del self._callbackList[:]
- try:
- callbackNumbers = self._backend.get_callback_numbers()
- except Exception, e:
- self._errorDisplay.push_exception()
- self._isPopulated = False
- return
-
- for number, description in callbackNumbers.iteritems():
- self._callbackList.append(make_pretty(number))
-
- if not self.get_selected_callback_number():
- self._set_callback_number(self._defaultCallback)
-
- def _set_callback_number(self, number):
- try:
- if not self._backend.is_valid_syntax(number) and 0 < len(number):
- self._errorDisplay.push_message("%s is not a valid callback number" % number)
- elif number == self._backend.get_callback_number():
- logging.warning(
- "Callback number already is %s" % (
- self._backend.get_callback_number(),
- ),
- )
- else:
- self._backend.set_callback_number(number)
- assert make_ugly(number) == make_ugly(self._backend.get_callback_number()), "Callback number should be %s but instead is %s" % (
- make_pretty(number), make_pretty(self._backend.get_callback_number())
- )
- self._callbackSelectButton.set_label(make_pretty(number))
- logging.info(
- "Callback number set to %s" % (
- self._backend.get_callback_number(),
- ),
- )
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _update_alarm_settings(self, recurrence):
- try:
- isEnabled = self._notifyCheckbox.get_active()
- if isEnabled != self._alarmHandler.isEnabled or recurrence != self._alarmHandler.recurrence:
- self._alarmHandler.apply_settings(isEnabled, recurrence)
- finally:
- self.save_everything()
- self._notifyCheckbox.set_active(self._alarmHandler.isEnabled)
- self._minutesEntryButton.set_label("%d Minutes" % self._alarmHandler.recurrence)
-
- def _on_callbackentry_clicked(self, *args):
- try:
- actualSelection = make_pretty(self.get_selected_callback_number())
-
- userSelection = hildonize.touch_selector_entry(
- self._window,
- "Callback Number",
- self._callbackList,
- actualSelection,
- )
- number = make_ugly(userSelection)
- self._set_callback_number(number)
- except RuntimeError, e:
- logging.exception("%s" % str(e))
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_notify_toggled(self, *args):
- try:
- if self._applyAlarmTimeoutId is not None:
- gobject.source_remove(self._applyAlarmTimeoutId)
- self._applyAlarmTimeoutId = None
- self._applyAlarmTimeoutId = gobject.timeout_add(500, self._on_apply_timeout)
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_minutes_clicked(self, *args):
- recurrenceChoices = [
- (1, "1 minute"),
- (2, "2 minutes"),
- (3, "3 minutes"),
- (5, "5 minutes"),
- (8, "8 minutes"),
- (10, "10 minutes"),
- (15, "15 minutes"),
- (30, "30 minutes"),
- (45, "45 minutes"),
- (60, "1 hour"),
- (3*60, "3 hours"),
- (6*60, "6 hours"),
- (12*60, "12 hours"),
- ]
- try:
- actualSelection = self._alarmHandler.recurrence
-
- closestSelectionIndex = 0
- for i, possible in enumerate(recurrenceChoices):
- if possible[0] <= actualSelection:
- closestSelectionIndex = i
- recurrenceIndex = hildonize.touch_selector(
- self._window,
- "Minutes",
- (("%s" % m[1]) for m in recurrenceChoices),
- closestSelectionIndex,
- )
- recurrence = recurrenceChoices[recurrenceIndex][0]
-
- self._update_alarm_settings(recurrence)
- except RuntimeError, e:
- logging.exception("%s" % str(e))
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_apply_timeout(self, *args):
- try:
- self._applyAlarmTimeoutId = None
-
- self._update_alarm_settings(self._alarmHandler.recurrence)
- except Exception, e:
- self._errorDisplay.push_exception()
- return False
-
- def _on_missed_toggled(self, *args):
- try:
- self._notifyOnMissed = self._missedCheckbox.get_active()
- self.save_everything()
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_voicemail_toggled(self, *args):
- try:
- self._notifyOnVoicemail = self._voicemailCheckbox.get_active()
- self.save_everything()
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_sms_toggled(self, *args):
- try:
- self._notifyOnSms = self._smsCheckbox.get_active()
- self.save_everything()
- except Exception, e:
- self._errorDisplay.push_exception()
-
-
-class RecentCallsView(object):
-
- NUMBER_IDX = 0
- DATE_IDX = 1
- ACTION_IDX = 2
- FROM_IDX = 3
-
- def __init__(self, widgetTree, backend, errorDisplay):
- self._errorDisplay = errorDisplay
- self._backend = backend
-
- self._isPopulated = False
- self._recentmodel = gtk.ListStore(
- gobject.TYPE_STRING, # number
- gobject.TYPE_STRING, # date
- gobject.TYPE_STRING, # action
- gobject.TYPE_STRING, # from
- )
- self._recentview = widgetTree.get_widget("recentview")
- self._recentviewselection = None
- self._onRecentviewRowActivatedId = 0
-
- textrenderer = gtk.CellRendererText()
- textrenderer.set_property("yalign", 0)
- self._dateColumn = gtk.TreeViewColumn("Date")
- self._dateColumn.pack_start(textrenderer, expand=True)
- self._dateColumn.add_attribute(textrenderer, "text", self.DATE_IDX)
-
- textrenderer = gtk.CellRendererText()
- textrenderer.set_property("yalign", 0)
- self._actionColumn = gtk.TreeViewColumn("Action")
- self._actionColumn.pack_start(textrenderer, expand=True)
- self._actionColumn.add_attribute(textrenderer, "text", self.ACTION_IDX)
-
- textrenderer = gtk.CellRendererText()
- textrenderer.set_property("yalign", 0)
- textrenderer.set_property("ellipsize", pango.ELLIPSIZE_END)
- textrenderer.set_property("width-chars", len("1 (555) 555-1234"))
- self._numberColumn = gtk.TreeViewColumn("Number")
- self._numberColumn.pack_start(textrenderer, expand=True)
- self._numberColumn.add_attribute(textrenderer, "text", self.NUMBER_IDX)
-
- textrenderer = gtk.CellRendererText()
- textrenderer.set_property("yalign", 0)
- hildonize.set_cell_thumb_selectable(textrenderer)
- self._nameColumn = gtk.TreeViewColumn("From")
- self._nameColumn.pack_start(textrenderer, expand=True)
- self._nameColumn.add_attribute(textrenderer, "text", self.FROM_IDX)
- self._nameColumn.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
-
- self._window = gtk_toolbox.find_parent_window(self._recentview)
- self._phoneTypeSelector = PhoneTypeSelector(widgetTree, self._backend)
-
- self._updateSink = gtk_toolbox.threaded_stage(
- gtk_toolbox.comap(
- self._idly_populate_recentview,
- gtk_toolbox.null_sink(),
- )
- )
-
- def enable(self):
- assert self._backend.is_authed(), "Attempting to enable backend while not logged in"
- self._recentview.set_model(self._recentmodel)
-
- self._recentview.append_column(self._dateColumn)
- self._recentview.append_column(self._actionColumn)
- self._recentview.append_column(self._numberColumn)
- self._recentview.append_column(self._nameColumn)
- self._recentviewselection = self._recentview.get_selection()
- self._recentviewselection.set_mode(gtk.SELECTION_SINGLE)
-
- self._onRecentviewRowActivatedId = self._recentview.connect("row-activated", self._on_recentview_row_activated)
-
- def disable(self):
- self._recentview.disconnect(self._onRecentviewRowActivatedId)
-
- self.clear()
-
- self._recentview.remove_column(self._dateColumn)
- self._recentview.remove_column(self._actionColumn)
- self._recentview.remove_column(self._nameColumn)
- self._recentview.remove_column(self._numberColumn)
- self._recentview.set_model(None)
-
- def number_selected(self, action, number, message):
- """
- @note Actual dial function is patched in later
- """
- raise NotImplementedError("Horrible unknown error has occurred")
-
- def update(self, force = False):
- if not force and self._isPopulated:
- return False
- self._updateSink.send(())
- return True
-
- def clear(self):
- self._isPopulated = False
- self._recentmodel.clear()
-
- @staticmethod
- def name():
- return "Recent Calls"
-
- def load_settings(self, config, section):
- pass
-
- def save_settings(self, config, section):
- """
- @note Thread Agnostic
- """
- pass
-
- def _idly_populate_recentview(self):
- with gtk_toolbox.gtk_lock():
- banner = hildonize.show_busy_banner_start(self._window, "Loading Recent History")
- try:
- self._recentmodel.clear()
- self._isPopulated = True
-
- try:
- recentItems = self._backend.get_recent()
- except Exception, e:
- self._errorDisplay.push_exception_with_lock()
- self._isPopulated = False
- recentItems = []
-
- for personName, phoneNumber, date, action in recentItems:
- if not personName:
- personName = "Unknown"
- date = abbrev_relative_date(date)
- prettyNumber = phoneNumber[2:] if phoneNumber.startswith("+1") else phoneNumber
- prettyNumber = make_pretty(prettyNumber)
- item = (prettyNumber, date, action.capitalize(), personName)
- with gtk_toolbox.gtk_lock():
- self._recentmodel.append(item)
- except Exception, e:
- self._errorDisplay.push_exception_with_lock()
- finally:
- with gtk_toolbox.gtk_lock():
- hildonize.show_busy_banner_end(banner)
-
- return False
-
- def _on_recentview_row_activated(self, treeview, path, view_column):
- try:
- model, itr = self._recentviewselection.get_selected()
- if not itr:
- return
-
- number = self._recentmodel.get_value(itr, self.NUMBER_IDX)
- number = make_ugly(number)
- contactPhoneNumbers = [("Phone", number)]
- description = self._recentmodel.get_value(itr, self.FROM_IDX)
-
- action, phoneNumber, message = self._phoneTypeSelector.run(
- contactPhoneNumbers,
- messages = (description, ),
- parent = self._window,
- )
- if action == PhoneTypeSelector.ACTION_CANCEL:
- return
- assert phoneNumber, "A lack of phone number exists"
-
- self.number_selected(action, phoneNumber, message)
- self._recentviewselection.unselect_all()
- except Exception, e:
- self._errorDisplay.push_exception()
-
-
-class MessagesView(object):
-
- NUMBER_IDX = 0
- DATE_IDX = 1
- HEADER_IDX = 2
- MESSAGE_IDX = 3
- MESSAGES_IDX = 4
-
- def __init__(self, widgetTree, backend, errorDisplay):
- self._errorDisplay = errorDisplay
- self._backend = backend
-
- self._isPopulated = False
- self._messagemodel = gtk.ListStore(
- gobject.TYPE_STRING, # number
- gobject.TYPE_STRING, # date
- gobject.TYPE_STRING, # header
- gobject.TYPE_STRING, # message
- object, # messages
- )
- self._messageview = widgetTree.get_widget("messages_view")
- self._messageviewselection = None
- self._onMessageviewRowActivatedId = 0
-
- self._messageRenderer = gtk.CellRendererText()
- self._messageRenderer.set_property("wrap-mode", pango.WRAP_WORD)
- self._messageRenderer.set_property("wrap-width", 500)
- self._messageColumn = gtk.TreeViewColumn("Messages")
- self._messageColumn.pack_start(self._messageRenderer, expand=True)
- self._messageColumn.add_attribute(self._messageRenderer, "markup", self.MESSAGE_IDX)
- self._messageColumn.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
-
- self._window = gtk_toolbox.find_parent_window(self._messageview)
- self._phoneTypeSelector = PhoneTypeSelector(widgetTree, self._backend)
-
- self._updateSink = gtk_toolbox.threaded_stage(
- gtk_toolbox.comap(
- self._idly_populate_messageview,
- gtk_toolbox.null_sink(),
- )
- )
-
- def enable(self):
- assert self._backend.is_authed(), "Attempting to enable backend while not logged in"
- self._messageview.set_model(self._messagemodel)
- self._messageview.set_headers_visible(False)
-
- self._messageview.append_column(self._messageColumn)
- self._messageviewselection = self._messageview.get_selection()
- self._messageviewselection.set_mode(gtk.SELECTION_SINGLE)
-
- self._onMessageviewRowActivatedId = self._messageview.connect("row-activated", self._on_messageview_row_activated)
-
- def disable(self):
- self._messageview.disconnect(self._onMessageviewRowActivatedId)
-
- self.clear()
-
- self._messageview.remove_column(self._messageColumn)
- self._messageview.set_model(None)
-
- def number_selected(self, action, number, message):
- """
- @note Actual dial function is patched in later
- """
- raise NotImplementedError("Horrible unknown error has occurred")
-
- def update(self, force = False):
- if not force and self._isPopulated:
- return False
- self._updateSink.send(())
- return True
-
- def clear(self):
- self._isPopulated = False
- self._messagemodel.clear()
-
- @staticmethod
- def name():
- return "Messages"
-
- def load_settings(self, config, section):
- pass
-
- def save_settings(self, config, section):
- """
- @note Thread Agnostic
- """
- pass
-
- def _idly_populate_messageview(self):
- with gtk_toolbox.gtk_lock():
- banner = hildonize.show_busy_banner_start(self._window, "Loading Messages")
- try:
- self._messagemodel.clear()
- self._isPopulated = True
-
- try:
- messageItems = self._backend.get_messages()
- except Exception, e:
- self._errorDisplay.push_exception_with_lock()
- self._isPopulated = False
- messageItems = []
-
- for header, number, relativeDate, messages in messageItems:
- prettyNumber = number[2:] if number.startswith("+1") else number
- prettyNumber = make_pretty(prettyNumber)
-
- firstMessage = "<b>%s - %s</b> <i>(%s)</i>" % (header, prettyNumber, relativeDate)
- newMessages = [firstMessage]
- newMessages.extend(messages)
-
- number = make_ugly(number)
-
- row = (number, relativeDate, header, "\n".join(newMessages), newMessages)
- with gtk_toolbox.gtk_lock():
- self._messagemodel.append(row)
- except Exception, e:
- self._errorDisplay.push_exception_with_lock()
- finally:
- with gtk_toolbox.gtk_lock():
- hildonize.show_busy_banner_end(banner)
-
- return False
-
- def _on_messageview_row_activated(self, treeview, path, view_column):
- try:
- model, itr = self._messageviewselection.get_selected()
- if not itr:
- return
-
- contactPhoneNumbers = [("Phone", self._messagemodel.get_value(itr, self.NUMBER_IDX))]
- description = self._messagemodel.get_value(itr, self.MESSAGES_IDX)
-
- action, phoneNumber, message = self._phoneTypeSelector.run(
- contactPhoneNumbers,
- messages = description,
- parent = self._window,
- )
- if action == PhoneTypeSelector.ACTION_CANCEL:
- return
- assert phoneNumber, "A lock of phone number exists"
-
- self.number_selected(action, phoneNumber, message)
- self._messageviewselection.unselect_all()
- except Exception, e:
- self._errorDisplay.push_exception()
-
-
-class ContactsView(object):
-
- def __init__(self, widgetTree, backend, errorDisplay):
- self._errorDisplay = errorDisplay
- self._backend = backend
-
- self._addressBook = None
- self._selectedComboIndex = 0
- self._addressBookFactories = [null_backend.NullAddressBook()]
-
- self._booksList = []
- self._bookSelectionButton = widgetTree.get_widget("addressbookSelectButton")
-
- self._isPopulated = False
- self._contactsmodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
- self._contactsviewselection = None
- self._contactsview = widgetTree.get_widget("contactsview")
-
- self._contactColumn = gtk.TreeViewColumn("Contact")
- displayContactSource = False
- if displayContactSource:
- textrenderer = gtk.CellRendererText()
- self._contactColumn.pack_start(textrenderer, expand=False)
- self._contactColumn.add_attribute(textrenderer, 'text', 0)
- textrenderer = gtk.CellRendererText()
- hildonize.set_cell_thumb_selectable(textrenderer)
- self._contactColumn.pack_start(textrenderer, expand=True)
- self._contactColumn.add_attribute(textrenderer, 'text', 1)
- textrenderer = gtk.CellRendererText()
- self._contactColumn.pack_start(textrenderer, expand=True)
- self._contactColumn.add_attribute(textrenderer, 'text', 4)
- self._contactColumn.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
- self._contactColumn.set_sort_column_id(1)
- self._contactColumn.set_visible(True)
-
- self._onContactsviewRowActivatedId = 0
- self._onAddressbookButtonChangedId = 0
- self._window = gtk_toolbox.find_parent_window(self._contactsview)
- self._phoneTypeSelector = PhoneTypeSelector(widgetTree, self._backend)
-
- self._updateSink = gtk_toolbox.threaded_stage(
- gtk_toolbox.comap(
- self._idly_populate_contactsview,
- gtk_toolbox.null_sink(),
- )
- )
-
- def enable(self):
- assert self._backend.is_authed(), "Attempting to enable backend while not logged in"
-
- self._contactsview.set_model(self._contactsmodel)
- self._contactsview.append_column(self._contactColumn)
- self._contactsviewselection = self._contactsview.get_selection()
- self._contactsviewselection.set_mode(gtk.SELECTION_SINGLE)
-
- del self._booksList[:]
- 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)
-
- self._onContactsviewRowActivatedId = self._contactsview.connect("row-activated", self._on_contactsview_row_activated)
- self._onAddressbookButtonChangedId = self._bookSelectionButton.connect("clicked", self._on_addressbook_button_changed)
-
- if len(self._booksList) <= self._selectedComboIndex:
- self._selectedComboIndex = 0
- self._bookSelectionButton.set_label(self._booksList[self._selectedComboIndex][2])
-
- selectedFactoryId = self._booksList[self._selectedComboIndex][0]
- selectedBookId = self._booksList[self._selectedComboIndex][1]
- self.open_addressbook(selectedFactoryId, selectedBookId)
-
- def disable(self):
- self._contactsview.disconnect(self._onContactsviewRowActivatedId)
- self._bookSelectionButton.disconnect(self._onAddressbookButtonChangedId)
-
- self.clear()
-
- self._bookSelectionButton.set_label("")
- self._contactsview.set_model(None)
- self._contactsview.remove_column(self._contactColumn)
-
- def number_selected(self, action, number, message):
- """
- @note Actual dial function is patched in later
- """
- raise NotImplementedError("Horrible unknown error has occurred")
-
- 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 (str(i), bookId), (factory.factory_name(), bookName)
-
- def open_addressbook(self, bookFactoryId, bookId):
- bookFactoryIndex = int(bookFactoryId)
- addressBook = self._addressBookFactories[bookFactoryIndex].open_addressbook(bookId)
-
- forceUpdate = True if addressBook is not self._addressBook else False
-
- self._addressBook = addressBook
- self.update(force=forceUpdate)
-
- def update(self, force = False):
- if not force and self._isPopulated:
- return False
- self._updateSink.send(())
- return True
-
- def clear(self):
- self._isPopulated = False
- self._contactsmodel.clear()
- for factory in self._addressBookFactories:
- factory.clear_caches()
- self._addressBook.clear_caches()
-
- def append(self, book):
- self._addressBookFactories.append(book)
-
- def extend(self, books):
- self._addressBookFactories.extend(books)
-
- @staticmethod
- def name():
- return "Contacts"
-
- def load_settings(self, config, sectionName):
- try:
- self._selectedComboIndex = config.getint(sectionName, "selectedAddressbook")
- except ConfigParser.NoOptionError:
- self._selectedComboIndex = 0
-
- def save_settings(self, config, sectionName):
- config.set(sectionName, "selectedAddressbook", str(self._selectedComboIndex))
-
- def _idly_populate_contactsview(self):
- with gtk_toolbox.gtk_lock():
- banner = hildonize.show_busy_banner_start(self._window, "Loading Contacts")
- try:
- addressBook = None
- while addressBook is not self._addressBook:
- addressBook = self._addressBook
- with gtk_toolbox.gtk_lock():
- self._contactsview.set_model(None)
- self.clear()
-
- try:
- contacts = addressBook.get_contacts()
- except Exception, e:
- contacts = []
- self._isPopulated = False
- self._errorDisplay.push_exception_with_lock()
- for contactId, contactName in contacts:
- contactType = (addressBook.contact_source_short_name(contactId), )
- self._contactsmodel.append(contactType + (contactName, "", contactId) + ("", ))
-
- with gtk_toolbox.gtk_lock():
- self._contactsview.set_model(self._contactsmodel)
-
- self._isPopulated = True
- except Exception, e:
- self._errorDisplay.push_exception_with_lock()
- finally:
- with gtk_toolbox.gtk_lock():
- hildonize.show_busy_banner_end(banner)
- return False
-
- def _on_addressbook_button_changed(self, *args, **kwds):
- try:
- try:
- newSelectedComboIndex = hildonize.touch_selector(
- self._window,
- "Addressbook",
- (("%s" % m[2]) for m in self._booksList),
- self._selectedComboIndex,
- )
- except RuntimeError:
- return
-
- selectedFactoryId = self._booksList[newSelectedComboIndex][0]
- selectedBookId = self._booksList[newSelectedComboIndex][1]
- self.open_addressbook(selectedFactoryId, selectedBookId)
- self._selectedComboIndex = newSelectedComboIndex
- self._bookSelectionButton.set_label(self._booksList[self._selectedComboIndex][2])
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_contactsview_row_activated(self, treeview, path, view_column):
- try:
- model, itr = self._contactsviewselection.get_selected()
- if not itr:
- return
-
- contactId = self._contactsmodel.get_value(itr, 3)
- contactName = self._contactsmodel.get_value(itr, 1)
- try:
- contactDetails = self._addressBook.get_contact_details(contactId)
- except Exception, e:
- contactDetails = []
- self._errorDisplay.push_exception()
- contactPhoneNumbers = [phoneNumber for phoneNumber in contactDetails]
-
- if len(contactPhoneNumbers) == 0:
- return
-
- action, phoneNumber, message = self._phoneTypeSelector.run(
- contactPhoneNumbers,
- messages = (contactName, ),
- parent = self._window,
- )
- if action == PhoneTypeSelector.ACTION_CANCEL:
- return
- assert phoneNumber, "A lack of phone number exists"
-
- self.number_selected(action, phoneNumber, message)
- self._contactsviewselection.unselect_all()
- except Exception, e:
- self._errorDisplay.push_exception()
+++ /dev/null
-#!/usr/bin/env python
-
-
-import gobject
-import gtk
-import dbus
-
-
-class _NullHildonModule(object):
- pass
-
-
-try:
- import hildon as _hildon
- hildon = _hildon # Dumb but gets around pyflakiness
-except (ImportError, OSError):
- hildon = _NullHildonModule
-
-
-IS_HILDON_SUPPORTED = hildon is not _NullHildonModule
-
-
-class _NullHildonProgram(object):
-
- def add_window(self, window):
- pass
-
-
-def _hildon_get_app_class():
- return hildon.Program
-
-
-def _null_get_app_class():
- return _NullHildonProgram
-
-
-try:
- hildon.Program
- get_app_class = _hildon_get_app_class
-except AttributeError:
- get_app_class = _null_get_app_class
-
-
-def _hildon_set_application_title(window, title):
- pass
-
-
-def _null_set_application_title(window, title):
- window.set_title(title)
-
-
-if IS_HILDON_SUPPORTED:
- set_application_title = _hildon_set_application_title
-else:
- set_application_title = _null_set_application_title
-
-
-def _fremantle_hildonize_window(app, window):
- oldWindow = window
- newWindow = hildon.StackableWindow()
- oldWindow.get_child().reparent(newWindow)
- app.add_window(newWindow)
- return newWindow
-
-
-def _hildon_hildonize_window(app, window):
- oldWindow = window
- newWindow = hildon.Window()
- oldWindow.get_child().reparent(newWindow)
- app.add_window(newWindow)
- return newWindow
-
-
-def _null_hildonize_window(app, window):
- return window
-
-
-try:
- hildon.StackableWindow
- hildonize_window = _fremantle_hildonize_window
-except AttributeError:
- try:
- hildon.Window
- hildonize_window = _hildon_hildonize_window
- except AttributeError:
- hildonize_window = _null_hildonize_window
-
-
-def _fremantle_hildonize_menu(window, gtkMenu, buttons):
- appMenu = hildon.AppMenu()
- for button in buttons:
- appMenu.append(button)
- window.set_app_menu(appMenu)
- gtkMenu.get_parent().remove(gtkMenu)
- return appMenu
-
-
-def _hildon_hildonize_menu(window, gtkMenu, ignoredButtons):
- hildonMenu = gtk.Menu()
- for child in gtkMenu.get_children():
- child.reparent(hildonMenu)
- window.set_menu(hildonMenu)
- gtkMenu.destroy()
- return hildonMenu
-
-
-def _null_hildonize_menu(window, gtkMenu, ignoredButtons):
- return gtkMenu
-
-
-try:
- hildon.AppMenu
- GTK_MENU_USED = False
- IS_FREMANTLE_SUPPORTED = True
- hildonize_menu = _fremantle_hildonize_menu
-except AttributeError:
- GTK_MENU_USED = True
- IS_FREMANTLE_SUPPORTED = False
- if IS_HILDON_SUPPORTED:
- hildonize_menu = _hildon_hildonize_menu
- else:
- hildonize_menu = _null_hildonize_menu
-
-
-def _hildon_set_cell_thumb_selectable(renderer):
- renderer.set_property("scale", 1.5)
-
-
-def _null_set_cell_thumb_selectable(renderer):
- pass
-
-
-if IS_HILDON_SUPPORTED:
- set_cell_thumb_selectable = _hildon_set_cell_thumb_selectable
-else:
- set_cell_thumb_selectable = _null_set_cell_thumb_selectable
-
-
-def _fremantle_show_information_banner(parent, message):
- hildon.hildon_banner_show_information(parent, "", message)
-
-
-def _hildon_show_information_banner(parent, message):
- hildon.hildon_banner_show_information(parent, None, message)
-
-
-def _null_show_information_banner(parent, message):
- pass
-
-
-if IS_FREMANTLE_SUPPORTED:
- show_information_banner = _fremantle_show_information_banner
-else:
- try:
- hildon.hildon_banner_show_information
- show_information_banner = _hildon_show_information_banner
- except AttributeError:
- show_information_banner = _null_show_information_banner
-
-
-def _fremantle_show_busy_banner_start(parent, message):
- hildon.hildon_gtk_window_set_progress_indicator(parent, True)
- return parent
-
-
-def _fremantle_show_busy_banner_end(banner):
- hildon.hildon_gtk_window_set_progress_indicator(banner, False)
-
-
-def _hildon_show_busy_banner_start(parent, message):
- return hildon.hildon_banner_show_animation(parent, None, message)
-
-
-def _hildon_show_busy_banner_end(banner):
- banner.destroy()
-
-
-def _null_show_busy_banner_start(parent, message):
- return None
-
-
-def _null_show_busy_banner_end(banner):
- assert banner is None
-
-
-try:
- hildon.hildon_gtk_window_set_progress_indicator
- show_busy_banner_start = _fremantle_show_busy_banner_start
- show_busy_banner_end = _fremantle_show_busy_banner_end
-except AttributeError:
- try:
- hildon.hildon_banner_show_animation
- show_busy_banner_start = _hildon_show_busy_banner_start
- show_busy_banner_end = _hildon_show_busy_banner_end
- except AttributeError:
- show_busy_banner_start = _null_show_busy_banner_start
- show_busy_banner_end = _null_show_busy_banner_end
-
-
-def _hildon_hildonize_text_entry(textEntry):
- textEntry.set_property('hildon-input-mode', 7)
-
-
-def _null_hildonize_text_entry(textEntry):
- pass
-
-
-if IS_HILDON_SUPPORTED:
- hildonize_text_entry = _hildon_hildonize_text_entry
-else:
- hildonize_text_entry = _null_hildonize_text_entry
-
-
-def _hildon_mark_window_rotatable(window):
- # gtk documentation is unclear whether this does a "=" or a "|="
- window.set_flags(hildon.HILDON_PORTRAIT_MODE_SUPPORT)
-
-
-def _null_mark_window_rotatable(window):
- pass
-
-
-try:
- hildon.HILDON_PORTRAIT_MODE_SUPPORT
- mark_window_rotatable = _hildon_mark_window_rotatable
-except AttributeError:
- mark_window_rotatable = _null_mark_window_rotatable
-
-
-def _hildon_window_to_portrait(window):
- # gtk documentation is unclear whether this does a "=" or a "|="
- window.set_flags(hildon.HILDON_PORTRAIT_MODE_SUPPORT)
-
-
-def _hildon_window_to_landscape(window):
- # gtk documentation is unclear whether this does a "=" or a "&= ~"
- window.unset_flags(hildon.HILDON_PORTRAIT_MODE_REQUEST)
-
-
-def _null_window_to_portrait(window):
- pass
-
-
-def _null_window_to_landscape(window):
- pass
-
-
-try:
- hildon.HILDON_PORTRAIT_MODE_SUPPORT
- hildon.HILDON_PORTRAIT_MODE_REQUEST
-
- window_to_portrait = _hildon_window_to_portrait
- window_to_landscape = _hildon_window_to_landscape
-except AttributeError:
- window_to_portrait = _null_window_to_portrait
- window_to_landscape = _null_window_to_landscape
-
-
-def get_device_orientation():
- bus = dbus.SystemBus()
- try:
- rawMceRequest = bus.get_object("com.nokia.mce", "/com/nokia/mce/request")
- mceRequest = dbus.Interface(rawMceRequest, dbus_interface="com.nokia.mce.request")
- orientation, standState, faceState, xAxis, yAxis, zAxis = mceRequest.get_device_orientation()
- except dbus.exception.DBusException:
- # catching for documentation purposes that when a system doesn't
- # support this, this is what to expect
- raise
-
- if orientation == "":
- return gtk.ORIENTATION_HORIZONTAL
- elif orientation == "":
- return gtk.ORIENTATION_VERTICAL
- else:
- raise RuntimeError("Unknown orientation: %s" % orientation)
-
-
-def _hildon_hildonize_password_entry(textEntry):
- textEntry.set_property('hildon-input-mode', 7 | (1 << 29))
-
-
-def _null_hildonize_password_entry(textEntry):
- pass
-
-
-if IS_HILDON_SUPPORTED:
- hildonize_password_entry = _hildon_hildonize_password_entry
-else:
- hildonize_password_entry = _null_hildonize_password_entry
-
-
-def _hildon_hildonize_combo_entry(comboEntry):
- comboEntry.set_property('hildon-input-mode', 1 << 4)
-
-
-def _null_hildonize_combo_entry(textEntry):
- pass
-
-
-if IS_HILDON_SUPPORTED:
- hildonize_combo_entry = _hildon_hildonize_combo_entry
-else:
- hildonize_combo_entry = _null_hildonize_combo_entry
-
-
-def _fremantle_hildonize_scrollwindow(scrolledWindow):
- pannableWindow = hildon.PannableArea()
-
- child = scrolledWindow.get_child()
- scrolledWindow.remove(child)
- pannableWindow.add(child)
-
- parent = scrolledWindow.get_parent()
- parent.remove(scrolledWindow)
- parent.add(pannableWindow)
-
- return pannableWindow
-
-
-def _hildon_hildonize_scrollwindow(scrolledWindow):
- hildon.hildon_helper_set_thumb_scrollbar(scrolledWindow, True)
- return scrolledWindow
-
-
-def _null_hildonize_scrollwindow(scrolledWindow):
- return scrolledWindow
-
-
-try:
- hildon.PannableArea
- hildonize_scrollwindow = _fremantle_hildonize_scrollwindow
- hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
-except AttributeError:
- try:
- hildon.hildon_helper_set_thumb_scrollbar
- hildonize_scrollwindow = _hildon_hildonize_scrollwindow
- hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
- except AttributeError:
- hildonize_scrollwindow = _null_hildonize_scrollwindow
- hildonize_scrollwindow_with_viewport = _null_hildonize_scrollwindow
-
-
-def _hildon_request_number(parent, title, range, default):
- spinner = hildon.NumberEditor(*range)
- spinner.set_value(default)
-
- dialog = gtk.Dialog(
- title,
- parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
- )
- dialog.set_default_response(gtk.RESPONSE_CANCEL)
- dialog.get_child().add(spinner)
-
- try:
- dialog.show_all()
- response = dialog.run()
- finally:
- dialog.hide()
-
- if response == gtk.RESPONSE_OK:
- return spinner.get_value()
- elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
- raise RuntimeError("User cancelled request")
- else:
- raise RuntimeError("Unrecognized response %r", response)
-
-
-def _null_request_number(parent, title, range, default):
- adjustment = gtk.Adjustment(default, range[0], range[1], 1, 5, 0)
- spinner = gtk.SpinButton(adjustment, 0, 0)
- spinner.set_wrap(False)
-
- dialog = gtk.Dialog(
- title,
- parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
- )
- dialog.set_default_response(gtk.RESPONSE_CANCEL)
- dialog.get_child().add(spinner)
-
- try:
- dialog.show_all()
- response = dialog.run()
- finally:
- dialog.hide()
-
- if response == gtk.RESPONSE_OK:
- return spinner.get_value_as_int()
- elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
- raise RuntimeError("User cancelled request")
- else:
- raise RuntimeError("Unrecognized response %r", response)
-
-
-try:
- hildon.NumberEditor # TODO deprecated in fremantle
- request_number = _hildon_request_number
-except AttributeError:
- request_number = _null_request_number
-
-
-def _hildon_touch_selector(parent, title, items, defaultIndex):
- model = gtk.ListStore(gobject.TYPE_STRING)
- for item in items:
- model.append((item, ))
-
- selector = hildon.TouchSelector()
- selector.append_text_column(model, True)
- selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
- selector.set_active(0, defaultIndex)
-
- dialog = hildon.PickerDialog(parent)
- dialog.set_selector(selector)
-
- try:
- dialog.show_all()
- response = dialog.run()
- finally:
- dialog.hide()
-
- if response == gtk.RESPONSE_OK:
- return selector.get_active(0)
- elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
- raise RuntimeError("User cancelled request")
- else:
- raise RuntimeError("Unrecognized response %r", response)
-
-
-def _on_null_touch_selector_activated(treeView, path, column, dialog):
- dialog.response(gtk.RESPONSE_OK)
-
-
-def _null_touch_selector(parent, title, items, defaultIndex = -1):
- model = gtk.ListStore(gobject.TYPE_STRING)
- for item in items:
- model.append((item, ))
-
- cell = gtk.CellRendererText()
- set_cell_thumb_selectable(cell)
- column = gtk.TreeViewColumn(title)
- column .pack_start(cell, expand=True)
- column.add_attribute(cell, "text", 0)
-
- treeView = gtk.TreeView()
- treeView.set_model(model)
- treeView.append_column(column)
- selection = treeView.get_selection()
- selection.set_mode(gtk.SELECTION_SINGLE)
- if 0 < defaultIndex:
- selection.select_path((defaultIndex, ))
-
- scrolledWin = gtk.ScrolledWindow()
- scrolledWin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- scrolledWin.add(treeView)
- hildonize_scrollwindow(scrolledWin)
-
- dialog = gtk.Dialog(
- title,
- parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
- )
- dialog.set_default_response(gtk.RESPONSE_CANCEL)
- dialog.get_child().add(scrolledWin)
- parentSize = parent.get_size()
- dialog.resize(parentSize[0], max(parentSize[1]-100, 100))
- treeView.connect("row-activated", _on_null_touch_selector_activated, dialog)
-
- try:
- dialog.show_all()
- response = dialog.run()
- finally:
- dialog.hide()
-
- if response == gtk.RESPONSE_OK:
- model, itr = selection.get_selected()
- if itr is None:
- raise RuntimeError("No selection made")
- return model.get_path(itr)[0]
- elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
- raise RuntimeError("User cancelled request")
- else:
- raise RuntimeError("Unrecognized response %r", response)
-
-
-try:
- hildon.PickerDialog
- hildon.TouchSelector
- touch_selector = _hildon_touch_selector
-except AttributeError:
- touch_selector = _null_touch_selector
-
-
-def _hildon_touch_selector_entry(parent, title, items, defaultItem):
- # Got a segfault when using append_text_column with TouchSelectorEntry, so using this way
- selector = hildon.hildon_touch_selector_entry_new_text()
- defaultIndex = -1
- for i, item in enumerate(items):
- selector.append_text(item)
- if item == defaultItem:
- defaultIndex = i
-
- dialog = hildon.PickerDialog(parent)
- dialog.set_selector(selector)
-
- if 0 < defaultIndex:
- selector.set_active(0, defaultIndex)
- else:
- selector.get_entry().set_text(defaultItem)
-
- try:
- dialog.show_all()
- response = dialog.run()
- finally:
- dialog.hide()
-
- if response == gtk.RESPONSE_OK:
- selectedIndex = selector.get_active(0)
- return selector.get_entry().get_text()
- elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
- raise RuntimeError("User cancelled request")
- else:
- raise RuntimeError("Unrecognized response %r", response)
-
-
-def _on_null_touch_selector_entry_entry_activated(entry, dialog, customEntry, result):
- dialog.response(gtk.RESPONSE_OK)
- result.append(customEntry.get_text())
-
-
-def _on_null_touch_selector_entry_tree_activated(treeView, path, column, dialog, selection, result):
- dialog.response(gtk.RESPONSE_OK)
- model, itr = selection.get_selected()
- if itr is not None:
- result.append(model.get_value(itr, 0))
-
-
-def _null_touch_selector_entry(parent, title, items, defaultItem):
- model = gtk.ListStore(gobject.TYPE_STRING)
- defaultIndex = -1
- for i, item in enumerate(items):
- model.append((item, ))
- if item == defaultItem:
- defaultIndex = i
-
- cell = gtk.CellRendererText()
- set_cell_thumb_selectable(cell)
- column = gtk.TreeViewColumn(title)
- column .pack_start(cell, expand=True)
- column.add_attribute(cell, "text", 0)
-
- treeView = gtk.TreeView()
- treeView.set_model(model)
- treeView.append_column(column)
- selection = treeView.get_selection()
- selection.set_mode(gtk.SELECTION_SINGLE)
-
- scrolledWin = gtk.ScrolledWindow()
- scrolledWin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- scrolledWin.add(treeView)
- hildonize_scrollwindow(scrolledWin)
-
- customEntry = gtk.Entry()
-
- layout = gtk.VBox()
- layout.pack_start(customEntry, expand=False)
- layout.pack_start(scrolledWin)
-
- dialog = gtk.Dialog(
- title,
- parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
- )
- dialog.set_default_response(gtk.RESPONSE_CANCEL)
- dialog.get_child().add(layout)
- parentSize = parent.get_size()
- dialog.resize(parentSize[0], max(parentSize[1]-100, 100))
-
- if 0 < defaultIndex:
- selection.select_path((defaultIndex, ))
- else:
- customEntry.set_text(defaultItem)
- result = []
- customEntry.connect("activate", _on_null_touch_selector_entry_entry_activated, dialog, customEntry, result)
- treeView.connect("row-activated", _on_null_touch_selector_entry_tree_activated, dialog, selection, result)
-
- try:
- dialog.show_all()
- response = dialog.run()
- finally:
- dialog.hide()
-
- if response == gtk.RESPONSE_OK:
- model, itr = selection.get_selected()
- if len(result) != 1:
- raise RuntimeError("No selection made")
- else:
- return result[0]
- elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
- raise RuntimeError("User cancelled request")
- else:
- raise RuntimeError("Unrecognized response %r", response)
-
-
-try:
- hildon.PickerDialog
- hildon.TouchSelectorEntry
- touch_selector_entry = _hildon_touch_selector_entry
-except AttributeError:
- touch_selector_entry = _null_touch_selector_entry
-
-
-if __name__ == "__main__":
- app = get_app_class()()
-
- label = gtk.Label("Hello World from a Label!")
-
- win = gtk.Window()
- win.add(label)
- win = hildonize_window(app, win)
- if False:
- print touch_selector(win, "Test", ["A", "B", "C", "D"], 2)
- if True:
- print touch_selector_entry(win, "Test", ["A", "B", "C", "D"], "C")
- print touch_selector_entry(win, "Test", ["A", "B", "C", "D"], "Blah")
- if False:
- import pprint
- name, value = "", ""
- goodLocals = [
- (name, value) for (name, value) in locals().iteritems()
- if not name.startswith("_")
- ]
- pprint.pprint(goodLocals)
- if False:
- import time
- show_information_banner(win, "Hello World")
- time.sleep(5)
- if False:
- import time
- banner = show_busy_banner_start(win, "Hello World")
- time.sleep(5)
- show_busy_banner_end(banner)
+++ /dev/null
-#!/usr/bin/env python
-
-import dbus
-
-
-class LedHandler(object):
-
- def __init__(self):
- self._bus = dbus.SystemBus()
- self._rawMceRequest = self._bus.get_object("com.nokia.mce", "/com/nokia/mce/request")
- self._mceRequest = dbus.Interface(self._rawMceRequest, dbus_interface="com.nokia.mce.request")
-
- self._ledPattern = "PatternCommunicationChat"
-
- def on(self):
- self._mceRequest.req_led_pattern_activate(self._ledPattern)
-
- def off(self):
- self._mceRequest.req_led_pattern_deactivate(self._ledPattern)
-
-
-if __name__ == "__main__":
- leds = LedHandler()
- leds.off()
+++ /dev/null
-#!/usr/bin/python2.5
-
-"""
-DialCentral - 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
-"""
-
-import gobject
-import gtk
-
-
-class Dialpad(object):
-
- def __init__(self, widgetTree):
- self._numberdisplay = widgetTree.get_widget("numberdisplay")
- self._dialButton = widgetTree.get_widget("dial")
- self._smsButton = widgetTree.get_widget("sms")
-
- def enable(self):
- self._dialButton.set_sensitive(False)
- self._smsButton.set_sensitive(False)
-
- def disable(self):
- self._dialButton.set_sensitive(True)
- self._smsButton.set_sensitive(True)
-
- @staticmethod
- def name():
- return "Dialpad"
-
- def load_settings(self, config, sectionName):
- pass
-
- def save_settings(self, config, sectionName):
- """
- @note Thread Agnostic
- """
- pass
-
-
-class AccountInfo(object):
-
- def __init__(self, widgetTree):
- self._callbackList = gtk.ListStore(gobject.TYPE_STRING)
- self._accountViewNumberDisplay = widgetTree.get_widget("gcnumber_display")
- self._callbackSelectButton = widgetTree.get_widget("callbackSelectButton")
- self._clearCookiesButton = widgetTree.get_widget("clearcookies")
-
- self._notifyCheckbox = widgetTree.get_widget("notifyCheckbox")
- self._minutesEntryButton = widgetTree.get_widget("minutesEntryButton")
- self._missedCheckbox = widgetTree.get_widget("missedCheckbox")
- self._voicemailCheckbox = widgetTree.get_widget("voicemailCheckbox")
- self._smsCheckbox = widgetTree.get_widget("smsCheckbox")
-
- def enable(self):
- self._callbackSelectButton.set_sensitive(False)
- self._clearCookiesButton.set_sensitive(False)
-
- self._notifyCheckbox.set_sensitive(False)
- self._minutesEntryButton.set_sensitive(False)
- self._missedCheckbox.set_sensitive(False)
- self._voicemailCheckbox.set_sensitive(False)
- self._smsCheckbox.set_sensitive(False)
-
- self._accountViewNumberDisplay.set_label("")
-
- def disable(self):
- self._callbackSelectButton.set_sensitive(True)
- self._clearCookiesButton.set_sensitive(True)
-
- self._notifyCheckbox.set_sensitive(True)
- self._minutesEntryButton.set_sensitive(True)
- self._missedCheckbox.set_sensitive(True)
- self._voicemailCheckbox.set_sensitive(True)
- self._smsCheckbox.set_sensitive(True)
-
- @staticmethod
- def update(force = False):
- return False
-
- @staticmethod
- def clear():
- pass
-
- @staticmethod
- def name():
- return "Account Info"
-
- def load_settings(self, config, sectionName):
- pass
-
- def save_settings(self, config, sectionName):
- """
- @note Thread Agnostic
- """
- pass
-
-
-class RecentCallsView(object):
-
- def __init__(self, widgetTree):
- pass
-
- def enable(self):
- pass
-
- def disable(self):
- pass
-
- def update(self, force = False):
- return False
-
- @staticmethod
- def clear():
- pass
-
- @staticmethod
- def name():
- return "Recent Calls"
-
- def load_settings(self, config, sectionName):
- pass
-
- def save_settings(self, config, sectionName):
- """
- @note Thread Agnostic
- """
- pass
-
-
-class MessagesView(object):
-
- def __init__(self, widgetTree):
- pass
-
- def enable(self):
- pass
-
- def disable(self):
- pass
-
- def update(self, force = False):
- return False
-
- @staticmethod
- def clear():
- pass
-
- @staticmethod
- def name():
- return "Messages"
-
- def load_settings(self, config, sectionName):
- pass
-
- def save_settings(self, config, sectionName):
- """
- @note Thread Agnostic
- """
- pass
-
-
-class ContactsView(object):
-
- def __init__(self, widgetTree):
- self._bookSelectionButton = widgetTree.get_widget("addressbookSelectButton")
-
- def enable(self):
- self._bookSelectionButton.set_sensitive(False)
-
- def disable(self):
- self._bookSelectionButton.set_sensitive(True)
-
- def update(self, force = False):
- return False
-
- @staticmethod
- def clear():
- pass
-
- @staticmethod
- def name():
- return "Contacts"
-
- def load_settings(self, config, sectionName):
- pass
-
- def save_settings(self, config, sectionName):
- """
- @note Thread Agnostic
- """
- pass
+++ /dev/null
-[Desktop Entry]
-Encoding=UTF-8
-Version=1.0
-Type=Application
-Name=DialCentral
-Exec=/usr/bin/run-standalone.sh /usr/bin/dialcentral.py
-Icon=dialcentral
+++ /dev/null
-familyname,phone,addr1,addr2,addr3,addr4,name1,name2,name3,name4\r
-"Last, First","555-123-4567","1234 Foo St","Austin, Texas 78727","","","First <name@domain.com>"\r
+++ /dev/null
-Name,E-mail,Notes,Section 1 - Description,Section 1 - Email,Section 1 - IM,Section 1 - Phone,Section 1 - Mobile,Section 1 - Pager,Section 1 - Fax,Section 1 - Company,Section 1 - Title,Section 1 - Other,Section 1 - Address,Section 2 - Description,Section 2 - Email,Section 2 - IM,Section 2 - Phone,Section 2 - Mobile,Section 2 - Pager,Section 2 - Fax,Section 2 - Company,Section 2 - Title,Section 2 - Other,Section 2 - Address,Section 3 - Description,Section 3 - Email,Section 3 - IM,Section 3 - Phone,Section 3 - Mobile,Section 3 - Pager,Section 3 - Fax,Section 3 - Company,Section 3 - Title,Section 3 - Other,Section 3 - Address\r
-First Last,name@domain.com,"Categories: Others\r
-\r
-\r
-Categories: Others",Other,name2@domain.com,,,,,,,,,,Personal,name3@domain.com; name4@domain.com; name5@domain.com; name6@domain.com,,17471234567,5551234567,,,,,,\r
-First1 Last,,"Categories: Friends\r
-",Personal,,,,5557654321,,,,,,\r
+++ /dev/null
-Name,E-mail Address,Categories,Company,Job Title,Home Address,Home Phone,Mobile Phone,Business Phone,GrandCentral,Suffix,Title,Initials,Web Page,Notes\r
-First Last,,Family,,,1234567 Foo St Austn Tx 78727,5559983254,5554023626,5559988899,,,,,,\r
-First1 Last,,Others,,,,5556835460,,,,,,,,\r
+++ /dev/null
-[1 - Contacts]
-
-[2 - Account Info]
-callback =
-
-[1 - Recent Calls]
-
-[2 - Messages]
-
-[0 - Messages]
-
-[1 - Messages]
-
-[2 - Dialpad]
-
-[2 - Contacts]
-
-[0 - Recent Calls]
-
-[DialCentral]
-active = 0
-bin_blob_0 =
-bin_blob_1 =
-
-[1 - Account Info]
-callback =
-
-[1 - Dialpad]
-
-[0 - Dialpad]
-
-[0 - Account Info]
-
-[0 - Contacts]
-
-[2 - Recent Calls]
-
+++ /dev/null
-import gobject
-import gtk
-
-class FileChooserDialog(gtk.FileChooserDialog):
- """
- @bug The buttons currently don't do anything
- """
-
- def __init__(self, *args, **kwds):
- super(FileChooserDialog, self).__init__(*args, **kwds)
- self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
- self.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK)
-
-
-class Program(object):
-
- def add_window(self, window):
- pass
-
-
-class Window(gtk.Window, object):
-
- def __init__(self):
- super(Window, self).__init__(gtk.WINDOW_TOPLEVEL)
- self.set_default_size(700, 500)
-
- def set_menu(self, menu):
- self._hildonMenu = menu
-
-
-gobject.type_register(Window)
-
-
-def hildon_helper_set_thumb_scrollbar(widget, value):
- pass
+++ /dev/null
-#!/usr/bin/env python
-
-import os
-import urllib
-import urllib2
-import traceback
-import warnings
-
-import sys
-sys.path.append("../../src")
-
-import browser_emu
-import gc_backend
-
-# Create Browser
-browser = browser_emu.MozillaEmulator(1)
-cookieFile = os.path.join(".", ".gc_cookies.txt")
-browser.cookies.filename = cookieFile
-
-# Login
-username = sys.argv[1]
-password = sys.argv[2]
-
-loginPostData = urllib.urlencode({
- 'Email' : username,
- 'Passwd' : password,
- 'service': "grandcentral",
- "ltmpl": "mobile",
- "btmpl": "mobile",
- "PersistentCookie": "yes",
-})
-
-try:
- loginSuccessOrFailurePage = browser.download(gc_backend.GCDialer._loginURL, loginPostData)
-except urllib2.URLError, e:
- warnings.warn(traceback.format_exc())
- raise RuntimeError("%s is not accesible" % gc_backend.GCDialer._loginURL)
-
-forwardPage = browser.download(gc_backend.GCDialer._forwardselectURL)
-
-tokenGroup = gc_backend.GCDialer._accessTokenRe.search(forwardPage)
-if tokenGroup is None:
- print forwardPage
- raise RuntimeError("Could not extract authentication token from GrandCentral")
-token = tokenGroup.group(1)
-
-
-with open("cookies.txt", "w") as f:
- f.writelines(
- "%s: %s\n" % (c.name, c.value)
- for c in browser.cookies
- )
+++ /dev/null
-#!/usr/bin/env python
-
-import os
-import urllib
-import urllib2
-import traceback
-import warnings
-
-import sys
-sys.path.append("../../src")
-
-import browser_emu
-import gc_backend
-
-webpages = [
- ("forward", gc_backend.GCDialer._forwardselectURL),
- ("login", gc_backend.GCDialer._loginURL),
- ("setforward", gc_backend.GCDialer._setforwardURL),
- ("clicktocall", gc_backend.GCDialer._clicktocallURL),
- ("recent", gc_backend.GCDialer._inboxallURL),
- ("contacts", gc_backend.GCDialer._contactsURL),
-]
-
-
-# Create Browser
-browser = browser_emu.MozillaEmulator(1)
-cookieFile = os.path.join(".", ".gc_cookies.txt")
-browser.cookies.filename = cookieFile
-
-# Get Pages
-for name, url in webpages:
- try:
- page = browser.download(url)
- except StandardError, e:
- print e.message
- continue
- with open("not_loggedin_%s.txt" % name, "w") as f:
- f.write(page)
-
-# Login
-username = sys.argv[1]
-password = sys.argv[2]
-
-loginPostData = urllib.urlencode({
- 'username' : username,
- 'password' : password,
-})
-
-try:
- loginSuccessOrFailurePage = browser.download(gc_backend.GCDialer._loginURL, loginPostData)
-except urllib2.URLError, e:
- warnings.warn(traceback.format_exc())
- raise RuntimeError("%s is not accesible" % gc_backend.GCDialer._loginURL)
-
-forwardPage = browser.download(gc_backend.GCDialer._forwardselectURL)
-
-tokenGroup = gc_backend.GCDialer._accessTokenRe.search(forwardPage)
-if tokenGroup is None:
- print "="*60
- print forwardPage
- print "="*60
- raise RuntimeError("Could not extract authentication token from GrandCentral")
-token = tokenGroup.group(1)
-
-# Get Pages
-for name, url in webpages:
- try:
- page = browser.download(url)
- except StandardError, e:
- warnings.warn(traceback.format_exc())
- continue
- print "Writing to file"
- with open("loggedin_%s.txt" % name, "w") as f:
- f.write(page)
+++ /dev/null
-from __future__ import with_statement
-
-import os
-import warnings
-
-import test_utils
-
-import sys
-sys.path.append("../src")
-
-import file_backend
-
-
-def test_factory():
- warnings.simplefilter("always")
- try:
- csvPath = os.path.join(os.path.dirname(__file__), "basic_data")
- factory = file_backend.FilesystemAddressBookFactory(csvPath)
- assert factory.factory_name() == "File"
- abooks = list(factory.get_addressbooks())
- abooks.sort()
- assert len(abooks) == 4
- abookNames = [abook[2] for abook in abooks]
- assert abookNames == ["basic", "empty", "google", "grandcentral"], "%s" % abookNames
-
- for abook_factory, abookId, abookName in abooks:
- abook = abook_factory.open_addressbook(abookId)
- assert isinstance(abook, file_backend.CsvAddressBook)
- finally:
- warnings.resetwarnings()
-
-
-def test_nonexistent_csv():
- warnings.simplefilter("always")
- try:
- csvPath = os.path.join(os.path.dirname(__file__), "basic_data", "nonexistent.csv")
- abook = file_backend.CsvAddressBook(csvPath)
-
- assert abook.factory_name() == "csv"
-
- contacts = list(abook.get_contacts())
- assert len(contacts) == 0
- finally:
- warnings.resetwarnings()
-
-
-def test_empty_csv():
- warnings.simplefilter("always")
- try:
- csvPath = os.path.join(os.path.dirname(__file__), "basic_data", "empty.csv")
- abook = file_backend.CsvAddressBook(csvPath)
-
- assert abook.factory_name() == "csv"
-
- contacts = list(abook.get_contacts())
- assert len(contacts) == 0
- finally:
- warnings.resetwarnings()
-
-
-def test_basic_csv():
- warnings.simplefilter("always")
- try:
- csvPath = os.path.join(os.path.dirname(__file__), "basic_data", "basic.csv")
- abook = file_backend.CsvAddressBook(csvPath)
-
- assert abook.factory_name() == "csv"
-
- contacts = list(abook.get_contacts())
- contacts.sort()
- assert len(contacts) == 1
-
- contactId, contactName = contacts[0]
- assert contactName == "Last, First"
- assert abook.contact_source_short_name(contactId) == "csv"
-
- details = list(abook.get_contact_details(contactId))
- assert len(details) == 1
- details.sort()
- assert details == [("phone", "555-123-4567")], "%s" % details
- finally:
- warnings.resetwarnings()
-
-
-def test_google_csv():
- warnings.simplefilter("always")
- try:
- csvPath = os.path.join(os.path.dirname(__file__), "basic_data", "google.csv")
- abook = file_backend.CsvAddressBook(csvPath)
-
- assert abook.factory_name() == "csv"
-
- contacts = list(abook.get_contacts())
- contacts.sort()
- assert len(contacts) == 2
-
- contactId, contactName = contacts[0]
- assert contactName == "First Last"
- assert abook.contact_source_short_name(contactId) == "csv"
-
- details = list(abook.get_contact_details(contactId))
- assert len(details) == 2
- details.sort()
- assert details == [
- ("Section 2 - Mobile", "5551234567"),
- ("Section 2 - Phone", "17471234567"),
- ], "%s" % details
-
- contactId, contactName = contacts[1]
- assert contactName == "First1 Last"
- assert abook.contact_source_short_name(contactId) == "csv"
-
- details = list(abook.get_contact_details(contactId))
- assert len(details) == 1
- details.sort()
- assert details == [("Section 1 - Mobile", "5557654321")], "%s" % details
- finally:
- warnings.resetwarnings()
-
-
-def test_grandcentral_csv():
- warnings.simplefilter("always")
- try:
- csvPath = os.path.join(os.path.dirname(__file__), "basic_data", "grandcentral.csv")
- abook = file_backend.CsvAddressBook(csvPath)
-
- assert abook.factory_name() == "csv"
-
- contacts = list(abook.get_contacts())
- contacts.sort()
- assert len(contacts) == 2
-
- contactId, contactName = contacts[0]
- assert contactName == "First Last"
- assert abook.contact_source_short_name(contactId) == "csv"
-
- details = list(abook.get_contact_details(contactId))
- assert len(details) == 3
- details.sort()
- assert details == [
- ("Business Phone", "5559988899"),
- ("Home Phone", "5559983254"),
- ("Mobile Phone", "5554023626"),
- ], "%s" % details
-
- contactId, contactName = contacts[1]
- assert contactName == "First1 Last"
- assert abook.contact_source_short_name(contactId) == "csv"
-
- details = list(abook.get_contact_details(contactId))
- assert len(details) == 1
- details.sort()
- assert details == [("Home Phone", "5556835460")], "%s" % details
- finally:
- warnings.resetwarnings()
+++ /dev/null
-from __future__ import with_statement
-
-import os
-import warnings
-import cookielib
-
-import test_utils
-
-import sys
-sys.path.append("../src")
-
-import gc_backend
-
-
-def generate_mock(cookiesSucceed, username, password):
-
- class MockModule(object):
-
- class MozillaEmulator(object):
-
- def __init__(self, trycount = 1):
- self.cookies = cookielib.LWPCookieJar()
- self.trycount = trycount
-
- def download(self, url,
- postdata = None, extraheaders = None, forbid_redirect = False,
- trycount = None, only_head = False,
- ):
- return ""
-
- return MockModule
-
-
-def test_not_logged_in():
- correctUsername, correctPassword = "", ""
- MockBrowserModule = generate_mock(False, correctUsername, correctPassword)
- gc_backend.browser_emu, RealBrowser = MockBrowserModule, gc_backend.browser_emu
- try:
- backend = gc_backend.GCDialer()
- assert not backend.is_authed()
- assert not backend.login("bad_name", "bad_password")
- backend.logout()
- with test_utils.expected(RuntimeError):
- backend.dial("5551234567")
- with test_utils.expected(RuntimeError):
- backend.send_sms("5551234567", "Hello World")
- assert backend.get_account_number() == "", "%s" % backend.get_account_number()
- backend.set_sane_callback()
- assert backend.get_callback_number() == ""
- recent = list(backend.get_recent())
- messages = list(backend.get_messages())
- finally:
- gc_backend.browser_emu = RealBrowser
+++ /dev/null
-from __future__ import with_statement
-
-import os
-import time
-import warnings
-
-import test_utils
-
-import sys
-sys.path.append("../src")
-
-import dc_glade
-
-
-def startup(factory):
- handle = factory()
- with test_utils.expected(AssertionError("Attempting login before app is fully loaded")):
- handle.refresh_session()
-
- for i in xrange(10):
- if handle._initDone:
- print "Completed init on iteration %d" % i
- break
- time.sleep(1)
- assert handle._initDone
-
- with test_utils.expected(RuntimeError("Login Failed")):
- handle.refresh_session()
-
- handle._save_settings()
-
- del handle
-
-
-def atest_startup_with_no_data_dir_with_dummy_hildon():
- warnings.simplefilter("always")
- hildonPath = os.path.join(os.path.dirname(__file__), "dummy_hildon")
- sys.path.insert(0, hildonPath)
- import hildon
- dc_glade.hildon = hildon
- try:
- dc_glade.Dialcentral._data_path = os.path.join(os.path.dirname(__file__), "notexistent_data")
- dc_glade.Dialcentral._user_settings = "%s/settings.ini" % dc_glade.Dialcentral._data_path
-
- try:
- startup(dc_glade.Dialcentral)
- finally:
- try:
- os.remove(dc_glade.Dialcentral._user_settings)
- except:
- pass
- try:
- os.removedirs(dc_glade.Dialcentral._data_path)
- except:
- pass
- finally:
- dc_glade.hildon = None
- sys.path.remove(hildonPath)
- warnings.resetwarnings()
-
-
-def atest_startup_with_no_data_dir():
- warnings.simplefilter("always")
- dc_glade.Dialcentral._data_path = os.path.join(os.path.dirname(__file__), "notexistent_data")
- dc_glade.Dialcentral._user_settings = "%s/settings.ini" % dc_glade.Dialcentral._data_path
-
- try:
- startup(dc_glade.Dialcentral)
- finally:
- try:
- os.remove(dc_glade.Dialcentral._user_settings)
- except:
- pass
- try:
- os.removedirs(dc_glade.Dialcentral._data_path)
- except:
- pass
- warnings.resetwarnings()
-
-
-def atest_startup_with_empty_data_dir():
- warnings.simplefilter("always")
- dc_glade.Dialcentral._data_path = os.path.join(os.path.dirname(__file__), "empty_data")
- dc_glade.Dialcentral._user_settings = "%s/settings.ini" % dc_glade.Dialcentral._data_path
-
- try:
- startup(dc_glade.Dialcentral)
- finally:
- try:
- os.remove(dc_glade.Dialcentral._user_settings)
- except:
- pass
- try:
- os.removedirs(dc_glade.Dialcentral._data_path)
- except:
- pass
- warnings.resetwarnings()
-
-
-def atest_startup_with_basic_data_dir():
- warnings.simplefilter("always")
- try:
- dc_glade.Dialcentral._data_path = os.path.join(os.path.dirname(__file__), "basic_data")
- dc_glade.Dialcentral._user_settings = "%s/settings.ini" % dc_glade.Dialcentral._data_path
-
- startup(dc_glade.Dialcentral)
- finally:
- warnings.resetwarnings()