- 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._typemodel = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
- self._typeviewselection = None
-
- self._message = self._widgetTree.get_widget("phoneSelectionMessage")
- self._messageViewport = self._widgetTree.get_widget("phoneSelectionMessage_viewport")
- self._scrollWindow = self._widgetTree.get_widget("phoneSelectionMessage_scrolledwindow")
- 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, message = "", parent = None):
- self._action = self.ACTION_CANCEL
- self._typemodel.clear()
- self._typeview.set_model(self._typemodel)
-
- # Add the column to the treeview
- 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)
-
- self._typeviewselection = self._typeview.get_selection()
- self._typeviewselection.set_mode(gtk.SELECTION_SINGLE)
-
- for phoneType, phoneNumber in contactDetails:
- display = " - ".join((phoneNumber, phoneType))
- display = phoneType
- row = (phoneNumber, display)
- self._typemodel.append(row)
-
- self._typeviewselection.select_iter(self._typemodel.get_iter_first())
- if message:
- self._message.set_markup(message)
- self._message.show()
- else:
- self._message.set_markup("")
- self._message.hide()
-
- if parent is not None:
- self._dialog.set_transient_for(parent)
-
- try:
- self._dialog.show()
- adjustment = self._scrollWindow.get_vadjustment()
- dx = self._message.get_allocation().height - self._messageViewport.get_allocation().height
- dx = max(dx, 0)
- adjustment.value = dx
-
- 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, message, parent)
- if not smsMessage:
- phoneNumber = ""
- self._action = self.ACTION_CANCEL
- else:
- smsMessage = ""
-
- 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._message = self._widgetTree.get_widget("smsMessage")
- self._messageViewport = self._widgetTree.get_widget("smsMessage_viewport")
- self._scrollWindow = self._widgetTree.get_widget("smsMessage_scrolledwindow")
- self._smsEntry = self._widgetTree.get_widget("smsEntry")
- self._smsEntry.get_buffer().connect("changed", self._on_entry_changed)
-
- def run(self, number, message = "", parent = None):
- if message:
- self._message.set_markup(message)
- self._message.show()
- else:
- self._message.set_markup("")
- self._message.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()
- adjustment = self._scrollWindow.get_vadjustment()
- dx = self._message.get_allocation().height - self._messageViewport.get_allocation().height
- dx = max(dx, 0)
- adjustment.value = dx
-
- 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 = ""
-
- 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._errorDisplay = errorDisplay
- self._smsDialog = SmsEntryDialog(widgetTree)
-
- self._numberdisplay = widgetTree.get_widget("numberdisplay")
- self._dialButton = widgetTree.get_widget("dial")
- self._backButton = widgetTree.get_widget("back")
- self._phonenumber = ""
- self._prettynumber = ""
-
- callbackMapping = {
- "on_dial_clicked": self._on_dial_clicked,
- "on_sms_clicked": self._on_sms_clicked,
- "on_digit_clicked": self._on_digit_clicked,
- "on_clear_number": self._on_clear_number,
- }
- widgetTree.signal_autoconnect(callbackMapping)
-
- 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)