try:
import alarm_handler
- self._alarmHandler = alarm_handler.AlarmHandler()
+ if alarm_handler.AlarmHandler is not alarm_handler._NoneAlarmHandler:
+ self._alarmHandler = alarm_handler.AlarmHandler()
+ else:
+ self._alarmHandler = None
except (ImportError, OSError):
alarm_handler = None
except Exception:
with gtk_toolbox.gtk_lock():
self._errorDisplay.push_exception()
alarm_handler = None
+ if alarm_handler is None:
_moduleLogger.warning("No notification support")
if hildonize.IS_HILDON_SUPPORTED:
try:
<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"/>
+ <accelerator key="b" signal="clicked"/>
+ <accelerator key="a" signal="clicked"/>
+ <accelerator key="2" signal="clicked"/>
<child>
<widget class="GtkLabel" id="label10">
<property name="visible">True</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"/>
+ <accelerator key="e" signal="clicked"/>
+ <accelerator key="d" signal="clicked"/>
+ <accelerator key="3" signal="clicked"/>
<child>
<widget class="GtkLabel" id="label11">
<property name="visible">True</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"/>
+ <accelerator key="h" signal="clicked"/>
+ <accelerator key="g" signal="clicked"/>
+ <accelerator key="4" signal="clicked"/>
<child>
<widget class="GtkLabel" id="label13">
<property name="visible">True</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"/>
+ <accelerator key="k" signal="clicked"/>
+ <accelerator key="j" signal="clicked"/>
+ <accelerator key="5" signal="clicked"/>
<child>
<widget class="GtkLabel" id="label14">
<property name="visible">True</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"/>
+ <accelerator key="n" signal="clicked"/>
+ <accelerator key="m" signal="clicked"/>
+ <accelerator key="6" signal="clicked"/>
<child>
<widget class="GtkLabel" id="label15">
<property name="visible">True</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"/>
+ <accelerator key="r" signal="clicked"/>
+ <accelerator key="q" signal="clicked"/>
+ <accelerator key="p" signal="clicked"/>
+ <accelerator key="7" signal="clicked"/>
<child>
<widget class="GtkLabel" id="label16">
<property name="visible">True</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"/>
+ <accelerator key="u" signal="clicked"/>
+ <accelerator key="t" signal="clicked"/>
+ <accelerator key="8" signal="clicked"/>
<child>
<widget class="GtkLabel" id="label17">
<property name="visible">True</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"/>
+ <accelerator key="y" signal="clicked"/>
+ <accelerator key="x" signal="clicked"/>
+ <accelerator key="w" signal="clicked"/>
+ <accelerator key="9" signal="clicked"/>
<child>
<widget class="GtkLabel" id="label18">
<property name="visible">True</property>
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
+ <widget class="GtkHBox" id="hbox4">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkButton" id="messageTypeButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </widget>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkButton" id="messageStatusButton">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
<widget class="GtkScrolledWindow" id="message_scrolledwindow">
<property name="visible">True</property>
<property name="can_focus">True</property>
</child>
</widget>
<packing>
- <property name="position">0</property>
+ <property name="position">1</property>
</packing>
</child>
</widget>
_voicemailURL = "https://www.google.com/voice/inbox/recent/voicemail/"
_smsURL = "https://www.google.com/voice/inbox/recent/sms/"
+ @staticmethod
+ def _merge_messages(parsedMessages, json):
+ for message in parsedMessages:
+ id = message["id"]
+ jsonItem = json["messages"][id]
+ message["isRead"] = jsonItem["isRead"]
+ message["isSpam"] = jsonItem["isSpam"]
+ message["isTrash"] = jsonItem["isTrash"]
+ yield message
+
def get_messages(self):
try:
voicemailPage = self._browser.download(self._voicemailURL)
_moduleLogger.exception("Translating error: %s" % str(e))
raise NetworkError("%s is not accesible" % self._voicemailURL)
voicemailHtml = self._grab_html(voicemailPage)
+ voicemailJson = self._grab_json(voicemailPage)
parsedVoicemail = self._parse_voicemail(voicemailHtml)
- decoratedVoicemails = self._decorate_voicemail(parsedVoicemail)
+ voicemails = self._merge_messages(parsedVoicemail, voicemailJson)
+ decoratedVoicemails = self._decorate_voicemail(voicemails)
try:
smsPage = self._browser.download(self._smsURL)
_moduleLogger.exception("Translating error: %s" % str(e))
raise NetworkError("%s is not accesible" % self._smsURL)
smsHtml = self._grab_html(smsPage)
+ smsJson = self._grab_json(smsPage)
parsedSms = self._parse_sms(smsHtml)
- decoratedSms = self._decorate_sms(parsedSms)
+ smss = self._merge_messages(parsedSms, smsJson)
+ decoratedSms = self._decorate_sms(smss)
allMessages = itertools.chain(decoratedVoicemails, decoratedSms)
return allMessages
"number": number,
"location": location,
"messageParts": messageParts,
+ "type": "Voicemail",
}
def _decorate_voicemail(self, parsedVoicemails):
"number": number,
"location": "",
"messageParts": messageParts,
+ "type": "Texts",
}
def _decorate_sms(self, parsedTexts):
MESSAGES_IDX = 4
FROM_ID_IDX = 5
+ NO_MESSAGES = "None"
+ VOICEMAIL_MESSAGES = "Voicemail"
+ TEXT_MESSAGES = "Texts"
+ ALL_MESSAGES = "All Messages"
+ MESSAGE_TYPES = [NO_MESSAGES, VOICEMAIL_MESSAGES, TEXT_MESSAGES, ALL_MESSAGES]
+
+ UNREAD_STATUS = "Unread"
+ UNARCHIVED_STATUS = "Unarchived"
+ ALL_STATUS = "Any"
+ MESSAGE_STATUSES = [UNREAD_STATUS, UNARCHIVED_STATUS, ALL_STATUS]
+
def __init__(self, widgetTree, backend, errorDisplay):
self._errorDisplay = errorDisplay
self._backend = backend
self._window = gtk_toolbox.find_parent_window(self._messageview)
self._phoneTypeSelector = SmsEntryDialog(widgetTree)
+ self._messageTypeButton = widgetTree.get_widget("messageTypeButton")
+ self._onMessageTypeClickedId = 0
+ self._messageType = self.ALL_MESSAGES
+ self._messageStatusButton = widgetTree.get_widget("messageStatusButton")
+ self._onMessageStatusClickedId = 0
+ self._messageStatus = self.ALL_STATUS
+
self._updateSink = gtk_toolbox.threaded_stage(
gtk_toolbox.comap(
self._idly_populate_messageview,
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)
+ self._messageTypeButton.set_label(self._messageType)
+ self._messageStatusButton.set_label(self._messageStatus)
+
+ self._onMessageviewRowActivatedId = self._messageview.connect(
+ "row-activated", self._on_messageview_row_activated
+ )
+ self._onMessageTypeClickedId = self._messageTypeButton.connect(
+ "clicked", self._on_message_type_clicked
+ )
+ self._onMessageStatusClickedId = self._messageStatusButton.connect(
+ "clicked", self._on_message_status_clicked
+ )
def disable(self):
self._messageview.disconnect(self._onMessageviewRowActivatedId)
+ self._messageTypeButton.disconnect(self._onMessageTypeClickedId)
+ self._messageStatusButton.disconnect(self._onMessageStatusClickedId)
self.clear()
def name():
return "Messages"
- def load_settings(self, config, section):
- pass
+ def load_settings(self, config, sectionName):
+ try:
+ self._messageStatus = config.get(sectionName, "status")
+ self._messageType = config.get(sectionName, "type")
+ except ConfigParser.NoOptionError:
+ pass
- def save_settings(self, config, section):
+ def save_settings(self, config, sectionName):
"""
@note Thread Agnostic
"""
- pass
+ config.set(sectionName, "status", self._messageStatus)
+ config.set(sectionName, "type", self._messageType)
_MIN_MESSAGES_SHOWN = 4
+ @classmethod
+ def _filter_messages(cls, message, type, status):
+ if type == cls.ALL_MESSAGES:
+ isType = True
+ else:
+ messageType = message["type"]
+ isType = messageType == type
+
+ if status == cls.ALL_STATUS:
+ isStatus = True
+ else:
+ isUnarchived = not message["isTrash"]
+ isUnread = not message["isRead"]
+ if status == cls.UNREAD_STATUS:
+ isStatus = isUnarchived and isUnread
+ elif status == cls.UNARCHIVED_STATUS:
+ isStatus = isUnarchived
+ else:
+ assert "Status %s is bad for %r" % (status, message)
+
+ return isType and isStatus
+
def _idly_populate_messageview(self):
with gtk_toolbox.gtk_lock():
banner = hildonize.show_busy_banner_start(self._window, "Loading Messages")
self._messagemodel.clear()
self._isPopulated = True
- try:
- messageItems = self._backend.get_messages()
- except Exception, e:
- self._errorDisplay.push_exception_with_lock()
- self._isPopulated = False
+ if self._messageType == self.NO_MESSAGES:
messageItems = []
+ else:
+ try:
+ messageItems = self._backend.get_messages()
+ except Exception, e:
+ self._errorDisplay.push_exception_with_lock()
+ self._isPopulated = False
+ messageItems = []
messageItems = (
gv_backend.decorate_message(message)
for message in gv_backend.sort_messages(messageItems)
+ if self._filter_messages(message, self._messageType, self._messageStatus)
)
for contactId, header, number, relativeDate, messages in messageItems:
except Exception, e:
self._errorDisplay.push_exception()
+ def _on_message_type_clicked(self, *args, **kwds):
+ try:
+ selectedIndex = self.MESSAGE_TYPES.index(self._messageType)
+
+ try:
+ newSelectedIndex = hildonize.touch_selector(
+ self._window,
+ "Message Type",
+ self.MESSAGE_TYPES,
+ selectedIndex,
+ )
+ except RuntimeError:
+ return
+
+ if selectedIndex != newSelectedIndex:
+ self._messageType = self.MESSAGE_TYPES[newSelectedIndex]
+ self._messageTypeButton.set_label(self._messageType)
+ self.update(True)
+ except Exception, e:
+ self._errorDisplay.push_exception()
+
+ def _on_message_status_clicked(self, *args, **kwds):
+ try:
+ selectedIndex = self.MESSAGE_STATUSES.index(self._messageStatus)
+
+ try:
+ newSelectedIndex = hildonize.touch_selector(
+ self._window,
+ "Message Status",
+ self.MESSAGE_STATUSES,
+ selectedIndex,
+ )
+ except RuntimeError:
+ return
+
+ if selectedIndex != newSelectedIndex:
+ self._messageStatus = self.MESSAGE_STATUSES[newSelectedIndex]
+ self._messageStatusButton.set_label(self._messageStatus)
+ self.update(True)
+ except Exception, e:
+ self._errorDisplay.push_exception()
+
class ContactsView(object):
class MessagesView(object):
def __init__(self, widgetTree):
- pass
+ self._messageTypeButton = widgetTree.get_widget("messageTypeButton")
+ self._messageStatusButton = widgetTree.get_widget("messageStatusButton")
def enable(self):
- pass
+ self._messageTypeButton.set_sensitive(False)
+ self._messageStatusButton.set_sensitive(False)
def disable(self):
- pass
+ self._messageTypeButton.set_sensitive(True)
+ self._messageStatusButton.set_sensitive(True)
def update(self, force = False):
return False
__changelog__ = """
1.0.8
* Sped up login time by delay loading contact list
+* Ability to narrow down messages either by type or status
* UI Tweak: Cut down the number of times the login dialog is needlessly displayed
1.0.7