X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=src%2Fdialcentral_qt.py;h=da2a7a9791465fd20d41c548a61129a52ea6e055;hb=3d7c7cdca856a8f21dcbdc8461275b26b6fd23ac;hp=fd5f0c576861cd1fccee9fb21b20f4e1e4cdaef6;hpb=dc58d53b93280fd7bc08fff84c2f8e267ef3e4e7;p=gc-dialer diff --git a/src/dialcentral_qt.py b/src/dialcentral_qt.py index fd5f0c5..da2a7a9 100755 --- a/src/dialcentral_qt.py +++ b/src/dialcentral_qt.py @@ -21,7 +21,30 @@ import session _moduleLogger = logging.getLogger(__name__) -IS_MAEMO = True + + +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(object): @@ -38,6 +61,10 @@ class Dialcentral(object): self._hiddenUnits = {} self._clipboard = QtGui.QApplication.clipboard() self._dataPath = None + self._ledHandler = LedWrapper() + self.notifyOnMissed = False + self.notifyOnVoicemail = False + self.notifyOnSms = False self._mainWindow = None @@ -47,6 +74,12 @@ class Dialcentral(object): self._fullscreenAction.setShortcut(QtGui.QKeySequence("CTRL+Enter")) self._fullscreenAction.toggled.connect(self._on_toggle_fullscreen) + self._orientationAction = QtGui.QAction(None) + self._orientationAction.setText("Orientation") + self._orientationAction.setCheckable(True) + self._orientationAction.setShortcut(QtGui.QKeySequence("CTRL+o")) + self._orientationAction.toggled.connect(self._on_toggle_orientation) + self._logAction = QtGui.QAction(None) self._logAction.setText("Log") self._logAction.setShortcut(QtGui.QKeySequence("CTRL+l")) @@ -61,6 +94,20 @@ class Dialcentral(object): self._mainWindow = MainWindow(None, self) self._mainWindow.window.destroyed.connect(self._on_child_close) + 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.load_settings() self._mainWindow.show() @@ -88,14 +135,16 @@ class Dialcentral(object): blobs = "", "" isFullscreen = False + isPortrait = qui_utils.screen_orientation() == QtCore.Qt.Vertical tabIndex = 0 try: - blobs = ( + blobs = [ config.get(constants.__pretty_app_name__, "bin_blob_%i" % i) for i in xrange(len(self._mainWindow.get_default_credentials())) - ) + ] isFullscreen = config.getboolean(constants.__pretty_app_name__, "fullscreen") tabIndex = config.getint(constants.__pretty_app_name__, "tab") + isPortrait = config.getboolean(constants.__pretty_app_name__, "portrait") except ConfigParser.NoOptionError, e: _moduleLogger.info( "Settings file %s is missing option %s" % ( @@ -110,10 +159,31 @@ class Dialcentral(object): e.section, ), ) - return except Exception: _moduleLogger.exception("Unknown loading error") - return + + 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") creds = ( base64.b64decode(blob) @@ -121,6 +191,7 @@ class Dialcentral(object): ) self._mainWindow.set_default_credentials(*creds) self._fullscreenAction.setChecked(isFullscreen) + self._orientationAction.setChecked(isPortrait) self._mainWindow.set_current_tab(tabIndex) self._mainWindow.load_settings(config) @@ -131,10 +202,19 @@ class Dialcentral(object): config.add_section(constants.__pretty_app_name__) config.set(constants.__pretty_app_name__, "tab", str(self._mainWindow.get_current_tab())) config.set(constants.__pretty_app_name__, "fullscreen", str(self._fullscreenAction.isChecked())) + config.set(constants.__pretty_app_name__, "portrait", str(self._orientationAction.isChecked())) for i, value in enumerate(self._mainWindow.get_default_credentials()): 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("2 - Account Info") + config.set("2 - Account Info", "notifyOnMissed", repr(self.notifyOnMissed)) + config.set("2 - Account Info", "notifyOnVoicemail", repr(self.notifyOnVoicemail)) + config.set("2 - Account Info", "notifyOnSms", repr(self.notifyOnSms)) + self._mainWindow.save_settings(config) with open(constants._user_settings_, "wb") as configFile: @@ -161,6 +241,10 @@ class Dialcentral(object): return self._fullscreenAction @property + def orientationAction(self): + return self._orientationAction + + @property def logAction(self): return self._logAction @@ -168,6 +252,20 @@ class Dialcentral(object): def quitAction(self): return self._quitAction + @property + def alarmHandler(self): + return self._alarmHandler + + @property + def ledHandler(self): + return self._ledHandler + + def _walk_children(self): + if self._mainWindow is not None: + return (self._mainWindow, ) + else: + return () + def _close_windows(self): if self._mainWindow is not None: self.save_settings() @@ -200,6 +298,13 @@ class Dialcentral(object): @QtCore.pyqtSlot() @QtCore.pyqtSlot(bool) @misc_utils.log_exception(_moduleLogger) + def _on_toggle_orientation(self, checked = False): + for window in self._walk_children(): + window.set_orientation(checked) + + @QtCore.pyqtSlot() + @QtCore.pyqtSlot(bool) + @misc_utils.log_exception(_moduleLogger) def _on_log(self, checked = False): with open(constants._user_logpath_, "r") as f: logLines = f.xreadlines() @@ -326,7 +431,11 @@ class MainWindow(object): def __init__(self, parent, app): self._app = app - self._session = session.Session(constants._data_path_) + + self._errorLog = qui_utils.QErrorLog() + self._errorDisplay = qui_utils.ErrorDisplay(self._errorLog) + + self._session = session.Session(self._errorLog, constants._data_path_) self._session.error.connect(self._on_session_error) self._session.loggedIn.connect(self._on_login) self._session.loggedOut.connect(self._on_logout) @@ -340,9 +449,6 @@ class MainWindow(object): self._accountDialog = None self._aboutDialog = None - self._errorLog = qui_utils.QErrorLog() - self._errorDisplay = qui_utils.ErrorDisplay(self._errorLog) - self._tabsContents = [ DelayedWidget(self._app, self._TAB_SETTINGS_NAMES[i]) for i in xrange(self.MAX_TABS) @@ -355,18 +461,25 @@ class MainWindow(object): self._tabWidget.setTabPosition(QtGui.QTabWidget.South) else: self._tabWidget.setTabPosition(QtGui.QTabWidget.West) + defaultTabIconSize = self._tabWidget.iconSize() + defaultTabIconWidth, defaultTabIconHeight = defaultTabIconSize.width(), defaultTabIconSize.height() for tabIndex, (tabTitle, tabIcon) in enumerate( zip(self._TAB_TITLES, self._TAB_ICONS) ): - if IS_MAEMO: - icon = self._app.get_icon(tabIcon) - if icon is None: - self._tabWidget.addTab(self._tabsContents[tabIndex].toplevel, tabTitle) - else: - self._tabWidget.addTab(self._tabsContents[tabIndex].toplevel, icon, "") + icon = self._app.get_icon(tabIcon) + if constants.IS_MAEMO and icon is not None: + tabTitle = "" + + if icon is None: + self._tabWidget.addTab(self._tabsContents[tabIndex].toplevel, tabTitle) else: - icon = self._app.get_icon(tabIcon) + iconSize = icon.availableSizes()[0] + defaultTabIconWidth = max(defaultTabIconWidth, iconSize.width()) + defaultTabIconHeight = max(defaultTabIconHeight, iconSize.height()) self._tabWidget.addTab(self._tabsContents[tabIndex].toplevel, icon, tabTitle) + defaultTabIconWidth = max(defaultTabIconWidth, 32) + defaultTabIconHeight = max(defaultTabIconHeight, 32) + self._tabWidget.setIconSize(QtCore.QSize(defaultTabIconWidth, defaultTabIconHeight)) self._tabWidget.currentChanged.connect(self._on_tab_changed) self._tabWidget.setContentsMargins(0, 0, 0, 0) @@ -381,7 +494,6 @@ class MainWindow(object): self._window = QtGui.QMainWindow(parent) self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, True) - qui_utils.set_autorient(self._window, True) qui_utils.set_stackable(self._window, True) self._window.setWindowTitle("%s" % constants.__pretty_app_name__) self._window.setCentralWidget(centralWidget) @@ -412,7 +524,7 @@ class MainWindow(object): self._closeWindowAction.setShortcut(QtGui.QKeySequence("CTRL+w")) self._closeWindowAction.triggered.connect(self._on_close_window) - if IS_MAEMO: + if constants.IS_MAEMO: fileMenu = self._window.menuBar().addMenu("&File") fileMenu.addAction(self._loginTabAction) fileMenu.addAction(self._refreshTabAction) @@ -425,6 +537,7 @@ class MainWindow(object): self._window.addAction(self._closeWindowAction) self._window.addAction(self._app.quitAction) self._window.addAction(self._app.fullscreenAction) + self._window.addAction(self._app.orientationAction) else: fileMenu = self._window.menuBar().addMenu("&File") fileMenu.addAction(self._loginTabAction) @@ -440,10 +553,13 @@ class MainWindow(object): toolsMenu.addAction(self._importTabAction) toolsMenu.addAction(self._aboutAction) + self._window.addAction(self._app.orientationAction) + self._window.addAction(self._app.logAction) self._initialize_tab(self._tabWidget.currentIndex()) self.set_fullscreen(self._app.fullscreenAction.isChecked()) + self.set_orientation(self._app.orientationAction.isChecked()) @property def window(self): @@ -456,17 +572,10 @@ class MainWindow(object): return self._defaultCredentials def walk_children(self): - return (diag for diag in ( - self._credentialsDialog, - self._smsEntryDialog, - self._accountDialog, - self._aboutDialog, - ) - if diag is not None - ) + return () def start(self): - assert self._session.state == self._session.LOGGEDOUT_STATE + assert self._session.state == self._session.LOGGEDOUT_STATE, "Initialization messed up" if self._defaultCredentials != ("", ""): username, password = self._defaultCredentials[0], self._defaultCredentials[1] self._curentCredentials = username, password @@ -476,7 +585,16 @@ class MainWindow(object): def close(self): for child in self.walk_children(): + child.window.destroyed.disconnect(self._on_child_close) child.close() + for diag in ( + self._credentialsDialog, + self._smsEntryDialog, + self._accountDialog, + self._aboutDialog, + ): + if diag is not None: + diag.close() self._window.close() def destroy(self): @@ -546,8 +664,18 @@ class MainWindow(object): for child in self.walk_children(): child.set_fullscreen(isFullscreen) + def set_orientation(self, isPortrait): + if isPortrait: + self._tabWidget.setTabPosition(QtGui.QTabWidget.South) + qui_utils.set_window_orientation(self.window, QtCore.Qt.Vertical) + else: + self._tabWidget.setTabPosition(QtGui.QTabWidget.West) + qui_utils.set_window_orientation(self.window, QtCore.Qt.Horizontal) + for child in self.walk_children(): + child.set_orientation(isPortrait) + def _initialize_tab(self, index): - assert index < self.MAX_TABS + assert index < self.MAX_TABS, "Invalid tab" if not self._tabsContents[index].has_child(): tab = self._TAB_CLASS[index](self._app, self._session, self._errorLog) self._tabsContents[index].set_child(tab) @@ -567,17 +695,30 @@ class MainWindow(object): 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.set_callbacks( self._session.get_callback_numbers(), self._session.get_callback_number() ) self._accountDialog.accountNumber = self._session.get_account_number() - response = self._accountDialog.run() + response = self._accountDialog.run(self.window) if response == QtGui.QDialog.Accepted: if self._accountDialog.doClear: self._session.logout_and_clear() 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 elif response == QtGui.QDialog.Rejected: _moduleLogger.info("Cancelled") else: @@ -586,76 +727,90 @@ class MainWindow(object): @QtCore.pyqtSlot(str) @misc_utils.log_exception(_moduleLogger) def _on_session_error(self, message): - self._errorLog.push_message(message) + with qui_utils.notify_error(self._errorLog): + self._errorLog.push_error(message) @QtCore.pyqtSlot() @misc_utils.log_exception(_moduleLogger) def _on_login(self): - if self._defaultCredentials != self._curentCredentials: - self._show_account_dialog() - self._defaultCredentials = self._curentCredentials - for tab in self._tabsContents: - tab.enable() + with qui_utils.notify_error(self._errorLog): + changedAccounts = self._defaultCredentials != self._curentCredentials + noCallback = not self._session.get_callback_number() + if changedAccounts or noCallback: + self._show_account_dialog() + + self._defaultCredentials = self._curentCredentials + + for tab in self._tabsContents: + tab.enable() @QtCore.pyqtSlot() @misc_utils.log_exception(_moduleLogger) def _on_logout(self): - for tab in self._tabsContents: - tab.disable() + with qui_utils.notify_error(self._errorLog): + for tab in self._tabsContents: + tab.disable() @QtCore.pyqtSlot() @misc_utils.log_exception(_moduleLogger) def _on_recipients_changed(self): - if self._session.draft.get_num_contacts() == 0: - return + with qui_utils.notify_error(self._errorLog): + if self._session.draft.get_num_contacts() == 0: + return - if self._smsEntryDialog is None: - import dialogs - self._smsEntryDialog = dialogs.SMSEntryWindow(self.window, self._app, self._session, self._errorLog) - pass + if self._smsEntryDialog is None: + import dialogs + self._smsEntryDialog = dialogs.SMSEntryWindow(self.window, self._app, self._session, self._errorLog) @QtCore.pyqtSlot() @QtCore.pyqtSlot(bool) @misc_utils.log_exception(_moduleLogger) def _on_login_requested(self, checked = True): - self._prompt_for_login() + with qui_utils.notify_error(self._errorLog): + self._prompt_for_login() @QtCore.pyqtSlot(int) @misc_utils.log_exception(_moduleLogger) def _on_tab_changed(self, index): - self._currentTab = index - self._initialize_tab(index) + with qui_utils.notify_error(self._errorLog): + self._currentTab = index + self._initialize_tab(index) @QtCore.pyqtSlot() @QtCore.pyqtSlot(bool) @misc_utils.log_exception(_moduleLogger) def _on_refresh(self, checked = True): - self._tabsContents[self._currentTab].refresh(force=True) + with qui_utils.notify_error(self._errorLog): + self._tabsContents[self._currentTab].refresh(force=True) @QtCore.pyqtSlot() @QtCore.pyqtSlot(bool) @misc_utils.log_exception(_moduleLogger) def _on_import(self, checked = True): - csvName = QtGui.QFileDialog.getOpenFileName(self._window, caption="Import", filter="CSV Files (*.csv)") - if not csvName: - return - import shutil - shutil.copy2(csvName, self._app.fsContactsPath) - self._tabsContents[self.CONTACTS_TAB].update_addressbooks() + with qui_utils.notify_error(self._errorLog): + csvName = QtGui.QFileDialog.getOpenFileName(self._window, caption="Import", filter="CSV Files (*.csv)") + if not csvName: + return + import shutil + shutil.copy2(csvName, self._app.fsContactsPath) + self._tabsContents[self.CONTACTS_TAB].update_addressbooks() @QtCore.pyqtSlot() @QtCore.pyqtSlot(bool) @misc_utils.log_exception(_moduleLogger) def _on_account(self, checked = True): - self._show_account_dialog() + with qui_utils.notify_error(self._errorLog): + self._show_account_dialog() @QtCore.pyqtSlot() @QtCore.pyqtSlot(bool) + @misc_utils.log_exception(_moduleLogger) def _on_about(self, checked = True): - if self._aboutDialog is None: - import dialogs - self._aboutDialog = dialogs.AboutDialog(self._app) - response = self._aboutDialog.run() + with qui_utils.notify_error(self._errorLog): + if self._aboutDialog is None: + import dialogs + self._aboutDialog = dialogs.AboutDialog(self._app) + response = self._aboutDialog.run(self.window) @QtCore.pyqtSlot() @QtCore.pyqtSlot(bool)