import ConfigParser
import logging
+from PyQt4 import QtCore
import dbus
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)
+ try:
+ 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)
+ except ConfigParser.NoOptionError:
+ pass
+ except ConfigParser.NoSectionError:
+ pass
def apply_settings(self, enabled, recurrence):
if recurrence != self._recurrence or enabled != self.isEnabled:
assert deleteResult != -1, "Deleting of alarm event failed"
-class _NoneAlarmHandler(object):
+class _ApplicationAlarmHandler(object):
- _INVALID_COOKIE = -1
_REPEAT_FOREVER = -1
- _LAUNCHER = os.path.abspath(os.path.join(os.path.dirname(__file__), "alarm_notify.py"))
+ _MIN_TO_MS_FACTORY = 1000 * 60
+
+ def __init__(self):
+ self._timer = QtCore.QTimer()
+ self._timer.setSingleShot(False)
+ self._timer.setInterval(5 * self._MIN_TO_MS_FACTORY)
+
+ def load_settings(self, config, sectionName):
+ try:
+ self._timer.setInterval(config.getint(sectionName, "recurrence") * self._MIN_TO_MS_FACTORY)
+ except ConfigParser.NoOptionError:
+ pass
+ except ConfigParser.NoSectionError:
+ pass
+ self._timer.start()
+
+ def save_settings(self, config, sectionName):
+ config.set(sectionName, "recurrence", str(self.recurrence))
+
+ def apply_settings(self, enabled, recurrence):
+ self._timer.setInterval(recurrence * self._MIN_TO_MS_FACTORY)
+ if enabled:
+ self._timer.start()
+ else:
+ self._timer.stop()
+
+ @property
+ def notifySignal(self):
+ return self._timer.timeout
+
+ @property
+ def recurrence(self):
+ return int(self._timer.interval() / self._MIN_TO_MS_FACTORY)
+
+ @property
+ def isEnabled(self):
+ return self._timer.isActive()
+
+
+class _NoneAlarmHandler(object):
def __init__(self):
- self._alarmCookie = 0
+ self._enabled = False
self._recurrence = 5
- 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
except ConfigParser.NoSectionError:
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)
+ config.set(sectionName, "recurrence", str(self.recurrence))
def apply_settings(self, enabled, recurrence):
- self._alarmCookie = 0 if enabled else self._INVALID_COOKIE
- self._recurrence = recurrence
+ self._enabled = enabled
@property
def recurrence(self):
@property
def isEnabled(self):
- return self._alarmCookie != self._INVALID_COOKIE
+ return self._enabled
-AlarmHandler = {
+_BACKGROUND_ALARM_FACTORY = {
_FREMANTLE_ALARM: _FremantleAlarmHandler,
_DIABLO_ALARM: _DiabloAlarmHandler,
- _NO_ALARM: _NoneAlarmHandler,
+ _NO_ALARM: None,
}[ALARM_TYPE]
+class AlarmHandler(object):
+
+ ALARM_NONE = "No Alert"
+ ALARM_BACKGROUND = "Background Alert"
+ ALARM_APPLICATION = "Application Alert"
+ ALARM_TYPES = [ALARM_NONE, ALARM_BACKGROUND, ALARM_APPLICATION]
+
+ ALARM_FACTORY = {
+ ALARM_NONE: _NoneAlarmHandler,
+ ALARM_BACKGROUND: _BACKGROUND_ALARM_FACTORY,
+ ALARM_APPLICATION: _ApplicationAlarmHandler,
+ }
+
+ def __init__(self):
+ self._alarms = {self.ALARM_NONE: _NoneAlarmHandler()}
+ self._currentAlarmType = self.ALARM_NONE
+
+ def load_settings(self, config, sectionName):
+ try:
+ self._currentAlarmType = config.get(sectionName, "alarm")
+ except (ConfigParser.NoOptionError, ConfigParser.NoSectionError):
+ _moduleLogger.exception("Falling back to old style")
+ self._currentAlarmType = self.ALARM_BACKGROUND
+ if self._currentAlarmType not in self.ALARM_TYPES:
+ self._currentAlarmType = self.ALARM_NONE
+
+ self._init_alarm(self._currentAlarmType)
+ if self._currentAlarmType in self._alarms:
+ self._alarms[self._currentAlarmType].load_settings(config, sectionName)
+ if not self._alarms[self._currentAlarmType].isEnabled:
+ _moduleLogger.info("Config file lied, not actually enabled")
+ self._currentAlarmType = self.ALARM_NONE
+ else:
+ _moduleLogger.info("Background alerts not supported")
+ self._currentAlarmType = self.ALARM_NONE
+
+ def save_settings(self, config, sectionName):
+ config.set(sectionName, "alarm", self._currentAlarmType)
+ self._alarms[self._currentAlarmType].save_settings(config, sectionName)
+
+ def apply_settings(self, t, recurrence):
+ self._init_alarm(t)
+ newHandler = self._alarms[t]
+ oldHandler = self._alarms[self._currentAlarmType]
+ if newHandler != oldHandler:
+ oldHandler.apply_settings(False, 0)
+ newHandler.apply_settings(True, recurrence)
+ self._currentAlarmType = t
+
+ @property
+ def alarmType(self):
+ return self._currentAlarmType
+
+ @property
+ def backgroundNotificationsSupported(self):
+ return self.ALARM_FACTORY[self.ALARM_BACKGROUND] is not None
+
+ @property
+ def applicationNotifySignal(self):
+ self._init_alarm(self.ALARM_APPLICATION)
+ return self._alarms[self.ALARM_APPLICATION].notifySignal
+
+ @property
+ def recurrence(self):
+ return self._alarms[self._currentAlarmType].recurrence
+
+ @property
+ def isEnabled(self):
+ return self._currentAlarmType != self.ALARM_NONE
+
+ def _init_alarm(self, t):
+ if t not in self._alarms and self.ALARM_FACTORY[t] is not None:
+ self._alarms[t] = self.ALARM_FACTORY[t]()
+
+
def main():
logFormat = '(%(relativeCreated)5d) %(levelname)-5s %(threadName)s.%(name)s.%(funcName)s: %(message)s'
logging.basicConfig(level=logging.DEBUG, format=logFormat)
from PyQt4 import QtCore
import constants
+import alarm_handler
+import led_handler
from util import qtpie
from util import qwrappers
from util import qui_utils
_moduleLogger = logging.getLogger(__name__)
-class LedWrapper(object):
-
- def __init__(self):
- self._ledHandler = None
- self._init = False
-
- def off(self):
- self._lazy_init()
- if self._ledHandler is not None:
- self._ledHandler.off()
-
- def _lazy_init(self):
- if self._init:
- return
- self._init = True
- try:
- import led_handler
- self._ledHandler = led_handler.LedHandler()
- except Exception, e:
- _moduleLogger.exception('Unable to initialize LED Handling: "%s"' % str(e))
- self._ledHandler = None
-
-
class Dialcentral(qwrappers.ApplicationWrapper):
_DATA_PATHS = [
def __init__(self, app):
self._dataPath = None
self._aboutDialog = None
- self._ledHandler = LedWrapper()
self.notifyOnMissed = False
self.notifyOnVoicemail = False
self.notifyOnSms = False
- try:
- import alarm_handler
- if alarm_handler.AlarmHandler is not alarm_handler._NoneAlarmHandler:
- self._alarmHandler = alarm_handler.AlarmHandler()
- else:
- self._alarmHandler = None
- except (ImportError, OSError):
- self._alarmHandler = None
- except Exception:
- _moduleLogger.exception("Notification failure")
- self._alarmHandler = None
- if self._alarmHandler is None:
- _moduleLogger.info("No notification support")
+ self._ledHandler = led_handler.LedHandler()
+ self._alarmHandler = alarm_handler.AlarmHandler()
qwrappers.ApplicationWrapper.__init__(self, app, constants)
except Exception:
_moduleLogger.exception("Unknown loading error")
- if self._alarmHandler is not None:
- try:
- self._alarmHandler.load_settings(config, "alarm")
- self.notifyOnMissed = config.getboolean("2 - Account Info", "notifyOnMissed")
- self.notifyOnVoicemail = config.getboolean("2 - Account Info", "notifyOnVoicemail")
- self.notifyOnSms = config.getboolean("2 - Account Info", "notifyOnSms")
- except ConfigParser.NoOptionError, e:
- _moduleLogger.info(
- "Settings file %s is missing option %s" % (
- constants._user_settings_,
- e.option,
- ),
- )
- except ConfigParser.NoSectionError, e:
- _moduleLogger.info(
- "Settings file %s is missing section %s" % (
- constants._user_settings_,
- e.section,
- ),
- )
- except Exception:
- _moduleLogger.exception("Unknown loading error")
+ try:
+ self._alarmHandler.load_settings(config, "alarm")
+ self.notifyOnMissed = config.getboolean("2 - Account Info", "notifyOnMissed")
+ self.notifyOnVoicemail = config.getboolean("2 - Account Info", "notifyOnVoicemail")
+ self.notifyOnSms = config.getboolean("2 - Account Info", "notifyOnSms")
+ except ConfigParser.NoOptionError, e:
+ _moduleLogger.info(
+ "Settings file %s is missing option %s" % (
+ constants._user_settings_,
+ e.option,
+ ),
+ )
+ except ConfigParser.NoSectionError, e:
+ _moduleLogger.info(
+ "Settings file %s is missing section %s" % (
+ constants._user_settings_,
+ e.section,
+ ),
+ )
+ except Exception:
+ _moduleLogger.exception("Unknown loading error")
creds = (
base64.b64decode(blob)
blob = base64.b64encode(value)
config.set(constants.__pretty_app_name__, "bin_blob_%i" % i, blob)
- if self._alarmHandler is not None:
- config.add_section("alarm")
- self._alarmHandler.save_settings(config, "alarm")
+ config.add_section("alarm")
+ self._alarmHandler.save_settings(config, "alarm")
config.add_section("2 - Account Info")
config.set("2 - Account Info", "notifyOnMissed", repr(self.notifyOnMissed))
config.set("2 - Account Info", "notifyOnVoicemail", repr(self.notifyOnVoicemail))
self._session.loggedOut.connect(self._on_logout)
self._session.draft.recipientsChanged.connect(self._on_recipients_changed)
self._session.newMessages.connect(self._on_new_message_alert)
+ self._app.alarmHandler.applicationNotifySignal.connect(self._on_app_alert)
self._defaultCredentials = "", ""
self._curentCredentials = "", ""
self._currentTab = 0
if self._accountDialog is None:
import dialogs
self._accountDialog = dialogs.AccountDialog(self._app)
- if self._app.alarmHandler is None:
- self._accountDialog.setIfNotificationsSupported(False)
- if self._app.alarmHandler is not None:
- self._accountDialog.notifications = self._app.alarmHandler.isEnabled
- self._accountDialog.notificationTime = self._app.alarmHandler.recurrence
- self._accountDialog.notifyOnMissed = self._app.notifyOnMissed
- self._accountDialog.notifyOnVoicemail = self._app.notifyOnVoicemail
- self._accountDialog.notifyOnSms = self._app.notifyOnSms
+ self._accountDialog.setIfNotificationsSupported(self._app.alarmHandler.backgroundNotificationsSupported)
+ self._accountDialog.notifications = self._app.alarmHandler.alarmType
+ self._accountDialog.notificationTime = self._app.alarmHandler.recurrence
+ self._accountDialog.notifyOnMissed = self._app.notifyOnMissed
+ self._accountDialog.notifyOnVoicemail = self._app.notifyOnVoicemail
+ self._accountDialog.notifyOnSms = self._app.notifyOnSms
self._accountDialog.set_callbacks(
self._session.get_callback_numbers(), self._session.get_callback_number()
)
else:
callbackNumber = self._accountDialog.selectedCallback
self._session.set_callback_number(callbackNumber)
- if self._app.alarmHandler is not None:
- self._app.alarmHandler.apply_settings(self._accountDialog.notifications, self._accountDialog.notificationTime)
- self._app.notifyOnMissed = self._accountDialog.notifyOnMissed
- self._app.notifyOnVoicemail = self._accountDialog.notifyOnVoicemail
- self._app.notifyOnSms = self._accountDialog.notifyOnSms
- self._app.save_settings()
+ self._app.alarmHandler.apply_settings(self._accountDialog.notifications, self._accountDialog.notificationTime)
+ self._app.notifyOnMissed = self._accountDialog.notifyOnMissed
+ self._app.notifyOnVoicemail = self._accountDialog.notifyOnVoicemail
+ self._app.notifyOnSms = self._accountDialog.notifyOnSms
+ self._app.save_settings()
elif response == QtGui.QDialog.Rejected:
_moduleLogger.info("Cancelled")
else:
@misc_utils.log_exception(_moduleLogger)
def _on_new_message_alert(self):
with qui_utils.notify_error(self._errorLog):
- self._errorLog.push_message("New messages available")
+ if self._app.alarmHandler.alarmType == self._app.alarmHandler.ALARM_APPLICATION:
+ if self._currentTab == self.MESSAGES_TAB or not self._app.ledHandler.isReal:
+ self._errorLog.push_message("New messages available")
+ else:
+ self._app.ledHandler.on()
@QtCore.pyqtSlot(str)
@misc_utils.log_exception(_moduleLogger)
@QtCore.pyqtSlot()
@misc_utils.log_exception(_moduleLogger)
+ def _on_app_alert(self):
+ with qui_utils.notify_error(self._errorLog):
+ if self._session.state == self._session.LOGGEDIN_STATE:
+ self._session.update_messages(force=True)
+
+ @QtCore.pyqtSlot()
+ @misc_utils.log_exception(_moduleLogger)
def _on_recipients_changed(self):
with qui_utils.notify_error(self._errorLog):
if self._session.draft.get_num_contacts() == 0:
with qui_utils.notify_error(self._errorLog):
self._currentTab = index
self._initialize_tab(index)
+ if self._app.alarmHandler.alarmType == self._app.alarmHandler.ALARM_APPLICATION:
+ self._app.ledHandler.off()
@QtCore.pyqtSlot()
@QtCore.pyqtSlot(bool)
(12*60, "12 hours"),
]
+ ALARM_NONE = "No Alert"
+ ALARM_BACKGROUND = "Background Alert"
+ ALARM_APPLICATION = "Application Alert"
+
def __init__(self, app):
self._app = app
self._doClear = False
self._accountNumberLabel = QtGui.QLabel("NUMBER NOT SET")
- self._notificationButton = QtGui.QCheckBox("Notifications")
- self._notificationButton.stateChanged.connect(self._on_notification_change)
+ self._notificationSelecter = QtGui.QComboBox()
+ self._notificationSelecter.currentIndexChanged.connect(self._on_notification_change)
self._notificationTimeSelector = QtGui.QComboBox()
#self._notificationTimeSelector.setEditable(True)
self._notificationTimeSelector.setInsertPolicy(QtGui.QComboBox.InsertAtTop)
self._credLayout.addWidget(self._accountNumberLabel, 0, 1)
self._credLayout.addWidget(QtGui.QLabel("Callback"), 1, 0)
self._credLayout.addWidget(self._callbackSelector, 1, 1)
- self._credLayout.addWidget(self._notificationButton, 2, 0)
+ self._credLayout.addWidget(self._notificationSelecter, 2, 0)
self._credLayout.addWidget(self._notificationTimeSelector, 2, 1)
self._credLayout.addWidget(QtGui.QLabel(""), 3, 0)
self._credLayout.addWidget(self._missedCallsNotificationButton, 3, 1)
def setIfNotificationsSupported(self, isSupported):
if isSupported:
- self._notificationButton.setVisible(True)
- self._notificationTimeSelector.setVisible(True)
- self._missedCallsNotificationButton.setVisible(True)
- self._voicemailNotificationButton.setVisible(True)
- self._smsNotificationButton.setVisible(True)
+ self._notificationSelecter.clear()
+ self._notificationSelecter.addItems([self.ALARM_NONE, self.ALARM_APPLICATION, self.ALARM_BACKGROUND])
+ self._notificationTimeSelector.setEnabled(False)
+ self._missedCallsNotificationButton.setEnabled(False)
+ self._voicemailNotificationButton.setEnabled(False)
+ self._smsNotificationButton.setEnabled(False)
else:
- self._notificationButton.setVisible(False)
- self._notificationTimeSelector.setVisible(False)
- self._missedCallsNotificationButton.setVisible(False)
- self._voicemailNotificationButton.setVisible(False)
- self._smsNotificationButton.setVisible(False)
+ self._notificationSelecter.clear()
+ self._notificationSelecter.addItems([self.ALARM_NONE, self.ALARM_APPLICATION])
+ self._notificationTimeSelector.setEnabled(False)
+ self._missedCallsNotificationButton.setEnabled(False)
+ self._voicemailNotificationButton.setEnabled(False)
+ self._smsNotificationButton.setEnabled(False)
def set_account_number(self, num):
self._accountNumberLabel.setText(num)
+ def _set_notifications(self, enabled):
+ for i in xrange(self._notificationSelecter.count()):
+ if self._notificationSelecter.itemText(i) == enabled:
+ self._notificationSelecter.setCurrentIndex(i)
+ break
+ else:
+ self._notificationSelecter.setCurrentIndex(0)
+
notifications = property(
- lambda self: self._notificationButton.isChecked(),
- lambda self, enabled: self._notificationButton.setChecked(enabled),
+ lambda self: str(self._notificationSelecter.currentText()),
+ _set_notifications,
)
notifyOnMissed = property(
_moduleLogger.exception("Oh well")
def _update_notification_state(self):
- if self._notificationButton.isChecked():
+ currentText = str(self._notificationSelecter.currentText())
+ if currentText == self.ALARM_BACKGROUND:
self._notificationTimeSelector.setEnabled(True)
+
self._missedCallsNotificationButton.setEnabled(True)
self._voicemailNotificationButton.setEnabled(True)
self._smsNotificationButton.setEnabled(True)
+ elif currentText == self.ALARM_APPLICATION:
+ self._notificationTimeSelector.setEnabled(True)
+
+ self._missedCallsNotificationButton.setEnabled(False)
+ self._voicemailNotificationButton.setEnabled(False)
+ self._smsNotificationButton.setEnabled(False)
+
+ self._missedCallsNotificationButton.setChecked(False)
+ self._voicemailNotificationButton.setChecked(True)
+ self._smsNotificationButton.setChecked(True)
else:
+
self._notificationTimeSelector.setEnabled(False)
self._missedCallsNotificationButton.setEnabled(False)
self._voicemailNotificationButton.setEnabled(False)
self._smsNotificationButton.setEnabled(False)
+ self._missedCallsNotificationButton.setChecked(False)
+ self._voicemailNotificationButton.setChecked(False)
+ self._smsNotificationButton.setChecked(False)
+
@QtCore.pyqtSlot(int)
@misc_utils.log_exception(_moduleLogger)
- def _on_notification_change(self, state):
+ def _on_notification_change(self, index):
with qui_utils.notify_error(self._app.errorLog):
self._update_notification_state()
def refresh(self, force=True):
self._itemView.setFocus(QtCore.Qt.OtherFocusReason)
self._session.update_history(force)
- if self._app.notifyOnMissed:
+ if self._app.notifyOnMissed and self._app.alarmHandler.alarmType == self._app.alarmHandler.ALARM_BACKGROUND:
self._app.ledHandler.off()
def _populate_items(self):
def refresh(self, force=True):
self._itemView.setFocus(QtCore.Qt.OtherFocusReason)
self._session.update_messages(force)
- if self._app.notifyOnSms or self._app.notifyOnVoicemail:
+ if self._app.notifyOnSms or self._app.notifyOnVoicemail and self._app.alarmHandler.alarmType == self._app.alarmHandler.ALARM_BACKGROUND:
self._app.ledHandler.off()
def _populate_items(self):
import dbus
-class LedHandler(object):
+class _NokiaLedHandler(object):
def __init__(self):
self._bus = dbus.SystemBus()
self._mceRequest.req_led_pattern_deactivate(self._ledPattern)
+class _NoLedHandler(object):
+
+ def __init__(self):
+ pass
+
+ def on(self):
+ pass
+
+ def off(self):
+ pass
+
+
+class LedHandler(object):
+
+ def __init__(self):
+ self._actual = None
+ self._isReal = False
+
+ def on(self):
+ self._lazy_init()
+ self._actual.on()
+
+ def off(self):
+ self._lazy_init()
+ self._actual.on()
+
+ @property
+ def isReal(self):
+ self._lazy_init()
+ self._isReal
+
+ def _lazy_init(self):
+ if self._actual is not None:
+ return
+ try:
+ self._actual = _NokiaLedHandler()
+ self._isReal = True
+ except dbus.DBusException:
+ self._actual = _NoLedHandler()
+ self._isReal = False
+
+
if __name__ == "__main__":
- leds = LedHandler()
+ leds = _NokiaLedHandler()
leds.off()
def _alert_on_messages(self, messages):
cleanNewMessages = list(self._clean_messages(messages))
+ cleanNewMessages.sort(key=lambda m: m["contactId"])
if self._cleanMessages:
if self._cleanMessages != cleanNewMessages:
self.newMessages.emit()