Adding progress notification
authorEd Page <eopage@byu.net>
Wed, 8 Dec 2010 02:37:40 +0000 (20:37 -0600)
committerEd Page <eopage@byu.net>
Wed, 8 Dec 2010 02:37:40 +0000 (20:37 -0600)
src/dialcentral_qt.py
src/dialogs.py
src/gv_views.py
src/session.py
src/util/qui_utils.py

index fd5f0c5..2d366c0 100755 (executable)
@@ -326,7 +326,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 +344,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)
@@ -586,76 +587,85 @@ 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):
+                       if self._defaultCredentials != self._curentCredentials:
+                               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)
        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()
 
        @QtCore.pyqtSlot()
        @QtCore.pyqtSlot(bool)
index 67950aa..31e91e6 100644 (file)
@@ -331,7 +331,8 @@ class SMSEntryWindow(object):
                self._update_recipients()
 
        def close(self):
-               self._dialog.reject()
+               self._window.destroy()
+               self._window = None
 
        def _update_letter_count(self):
                count = self._smsEntry.toPlainText().size()
@@ -516,7 +517,7 @@ class SMSEntryWindow(object):
                self._smsButton.setVisible(True)
                self._dialButton.setVisible(True)
 
-               self._errorLog.push_message(message)
+               self._errorLog.push_error(message)
 
        @QtCore.pyqtSlot()
        @misc_utils.log_exception(_moduleLogger)
index 250e5f0..23c07c8 100644 (file)
@@ -123,43 +123,48 @@ class Dialpad(object):
 
        @misc_utils.log_exception(_moduleLogger)
        def _on_keypress(self, key):
-               self._entry.insert(key)
+               with qui_utils.notify_error(self._errorLog):
+                       self._entry.insert(key)
 
        @misc_utils.log_exception(_moduleLogger)
        def _on_backspace(self, toggled = False):
-               self._entry.backspace()
+               with qui_utils.notify_error(self._errorLog):
+                       self._entry.backspace()
 
        @misc_utils.log_exception(_moduleLogger)
        def _on_clear_text(self, toggled = False):
-               self._entry.clear()
+               with qui_utils.notify_error(self._errorLog):
+                       self._entry.clear()
 
        @QtCore.pyqtSlot()
        @QtCore.pyqtSlot(bool)
        @misc_utils.log_exception(_moduleLogger)
        def _on_sms_clicked(self, checked = False):
-               number = misc_utils.make_ugly(str(self._entry.text()))
-               self._entry.clear()
+               with qui_utils.notify_error(self._errorLog):
+                       number = misc_utils.make_ugly(str(self._entry.text()))
+                       self._entry.clear()
 
-               contactId = number
-               title = misc_utils.make_pretty(number)
-               description = misc_utils.make_pretty(number)
-               numbersWithDescriptions = [(number, "")]
-               self._session.draft.add_contact(contactId, title, description, numbersWithDescriptions)
+                       contactId = number
+                       title = misc_utils.make_pretty(number)
+                       description = misc_utils.make_pretty(number)
+                       numbersWithDescriptions = [(number, "")]
+                       self._session.draft.add_contact(contactId, title, description, numbersWithDescriptions)
 
        @QtCore.pyqtSlot()
        @QtCore.pyqtSlot(bool)
        @misc_utils.log_exception(_moduleLogger)
        def _on_call_clicked(self, checked = False):
-               number = misc_utils.make_ugly(str(self._entry.text()))
-               self._entry.clear()
+               with qui_utils.notify_error(self._errorLog):
+                       number = misc_utils.make_ugly(str(self._entry.text()))
+                       self._entry.clear()
 
-               contactId = number
-               title = misc_utils.make_pretty(number)
-               description = misc_utils.make_pretty(number)
-               numbersWithDescriptions = [(number, "")]
-               self._session.draft.clear()
-               self._session.draft.add_contact(contactId, title, description, numbersWithDescriptions)
-               self._session.draft.call()
+                       contactId = number
+                       title = misc_utils.make_pretty(number)
+                       description = misc_utils.make_pretty(number)
+                       numbersWithDescriptions = [(number, "")]
+                       self._session.draft.clear()
+                       self._session.draft.add_contact(contactId, title, description, numbersWithDescriptions)
+                       self._session.draft.call()
 
 
 class TimeCategories(object):
@@ -337,47 +342,50 @@ class History(object):
        @QtCore.pyqtSlot(str)
        @misc_utils.log_exception(_moduleLogger)
        def _on_filter_changed(self, newItem):
-               self._selectedFilter = str(newItem)
-               self._populate_items()
+               with qui_utils.notify_error(self._errorLog):
+                       self._selectedFilter = str(newItem)
+                       self._populate_items()
 
        @QtCore.pyqtSlot()
        @misc_utils.log_exception(_moduleLogger)
        def _on_history_updated(self):
-               self._populate_items()
+               with qui_utils.notify_error(self._errorLog):
+                       self._populate_items()
 
        @QtCore.pyqtSlot(QtCore.QModelIndex)
        @misc_utils.log_exception(_moduleLogger)
        def _on_row_activated(self, index):
-               timeIndex = index.parent()
-               assert timeIndex.isValid()
-               timeRow = timeIndex.row()
-               row = index.row()
-               detailsItem = self._categoryManager.get_item(timeRow, row, self.DETAILS_IDX)
-               fromItem = self._categoryManager.get_item(timeRow, row, self.FROM_IDX)
-               contactDetails = detailsItem.data().toPyObject()
-
-               title = str(fromItem.text())
-               number = str(contactDetails[QtCore.QString("number")])
-               contactId = number # ids don't seem too unique so using numbers
-
-               descriptionRows = []
-               for t in xrange(self._itemStore.rowCount()):
-                       randomTimeItem = self._itemStore.item(t, 0)
-                       for i in xrange(randomTimeItem.rowCount()):
-                               iItem = randomTimeItem.child(i, 0)
-                               iContactDetails = iItem.data().toPyObject()
-                               iNumber = str(iContactDetails[QtCore.QString("number")])
-                               if number != iNumber:
-                                       continue
-                               relTime = misc_utils.abbrev_relative_date(iContactDetails[QtCore.QString("relTime")])
-                               action = str(iContactDetails[QtCore.QString("action")])
-                               number = str(iContactDetails[QtCore.QString("number")])
-                               prettyNumber = misc_utils.make_pretty(number)
-                               rowItems = relTime, action, prettyNumber
-                               descriptionRows.append("<tr><td>%s</td></tr>" % "</td><td>".join(rowItems))
-               description = "<table>%s</table>" % "".join(descriptionRows)
-               numbersWithDescriptions = [(str(contactDetails[QtCore.QString("number")]), "")]
-               self._session.draft.add_contact(contactId, title, description, numbersWithDescriptions)
+               with qui_utils.notify_error(self._errorLog):
+                       timeIndex = index.parent()
+                       assert timeIndex.isValid()
+                       timeRow = timeIndex.row()
+                       row = index.row()
+                       detailsItem = self._categoryManager.get_item(timeRow, row, self.DETAILS_IDX)
+                       fromItem = self._categoryManager.get_item(timeRow, row, self.FROM_IDX)
+                       contactDetails = detailsItem.data().toPyObject()
+
+                       title = str(fromItem.text())
+                       number = str(contactDetails[QtCore.QString("number")])
+                       contactId = number # ids don't seem too unique so using numbers
+
+                       descriptionRows = []
+                       for t in xrange(self._itemStore.rowCount()):
+                               randomTimeItem = self._itemStore.item(t, 0)
+                               for i in xrange(randomTimeItem.rowCount()):
+                                       iItem = randomTimeItem.child(i, 0)
+                                       iContactDetails = iItem.data().toPyObject()
+                                       iNumber = str(iContactDetails[QtCore.QString("number")])
+                                       if number != iNumber:
+                                               continue
+                                       relTime = misc_utils.abbrev_relative_date(iContactDetails[QtCore.QString("relTime")])
+                                       action = str(iContactDetails[QtCore.QString("action")])
+                                       number = str(iContactDetails[QtCore.QString("number")])
+                                       prettyNumber = misc_utils.make_pretty(number)
+                                       rowItems = relTime, action, prettyNumber
+                                       descriptionRows.append("<tr><td>%s</td></tr>" % "</td><td>".join(rowItems))
+                       description = "<table>%s</table>" % "".join(descriptionRows)
+                       numbersWithDescriptions = [(str(contactDetails[QtCore.QString("number")]), "")]
+                       self._session.draft.add_contact(contactId, title, description, numbersWithDescriptions)
 
 
 class Messages(object):
@@ -549,42 +557,46 @@ class Messages(object):
        @QtCore.pyqtSlot(str)
        @misc_utils.log_exception(_moduleLogger)
        def _on_type_filter_changed(self, newItem):
-               self._selectedTypeFilter = str(newItem)
-               self._populate_items()
+               with qui_utils.notify_error(self._errorLog):
+                       self._selectedTypeFilter = str(newItem)
+                       self._populate_items()
 
        @QtCore.pyqtSlot(str)
        @misc_utils.log_exception(_moduleLogger)
        def _on_status_filter_changed(self, newItem):
-               self._selectedStatusFilter = str(newItem)
-               self._populate_items()
+               with qui_utils.notify_error(self._errorLog):
+                       self._selectedStatusFilter = str(newItem)
+                       self._populate_items()
 
        @QtCore.pyqtSlot()
        @misc_utils.log_exception(_moduleLogger)
        def _on_messages_updated(self):
-               self._populate_items()
+               with qui_utils.notify_error(self._errorLog):
+                       self._populate_items()
 
        @QtCore.pyqtSlot(QtCore.QModelIndex)
        @misc_utils.log_exception(_moduleLogger)
        def _on_row_activated(self, index):
-               timeIndex = index.parent()
-               assert timeIndex.isValid()
-               timeRow = timeIndex.row()
-               row = index.row()
-               item = self._categoryManager.get_item(timeRow, row, 0)
-               contactDetails = item.data().toPyObject()
-
-               name = str(contactDetails[QtCore.QString("name")])
-               number = str(contactDetails[QtCore.QString("number")])
-               if not name or name == number:
-                       name = str(contactDetails[QtCore.QString("location")])
-               if not name:
-                       name = "Unknown"
-
-               contactId = str(contactDetails[QtCore.QString("id")])
-               title = name
-               description = str(contactDetails[QtCore.QString("expandedMessages")])
-               numbersWithDescriptions = [(number, "")]
-               self._session.draft.add_contact(contactId, title, description, numbersWithDescriptions)
+               with qui_utils.notify_error(self._errorLog):
+                       timeIndex = index.parent()
+                       assert timeIndex.isValid()
+                       timeRow = timeIndex.row()
+                       row = index.row()
+                       item = self._categoryManager.get_item(timeRow, row, 0)
+                       contactDetails = item.data().toPyObject()
+
+                       name = str(contactDetails[QtCore.QString("name")])
+                       number = str(contactDetails[QtCore.QString("number")])
+                       if not name or name == number:
+                               name = str(contactDetails[QtCore.QString("location")])
+                       if not name:
+                               name = "Unknown"
+
+                       contactId = str(contactDetails[QtCore.QString("id")])
+                       title = name
+                       description = str(contactDetails[QtCore.QString("expandedMessages")])
+                       numbersWithDescriptions = [(number, "")]
+                       self._session.draft.add_contact(contactId, title, description, numbersWithDescriptions)
 
 
 class Contacts(object):
@@ -748,52 +760,55 @@ class Contacts(object):
        @QtCore.pyqtSlot(str)
        @misc_utils.log_exception(_moduleLogger)
        def _on_filter_changed(self, newItem):
-               self._activeList = str(newItem)
-               self.refresh(force=False)
-               self._populate_items()
+               with qui_utils.notify_error(self._errorLog):
+                       self._activeList = str(newItem)
+                       self.refresh(force=False)
+                       self._populate_items()
 
        @QtCore.pyqtSlot()
        @misc_utils.log_exception(_moduleLogger)
        def _on_contacts_updated(self):
-               self._populate_items()
+               with qui_utils.notify_error(self._errorLog):
+                       self._populate_items()
 
        @QtCore.pyqtSlot(QtCore.QModelIndex)
        @misc_utils.log_exception(_moduleLogger)
        def _on_row_activated(self, index):
-               letterIndex = index.parent()
-               assert letterIndex.isValid()
-               letterRow = letterIndex.row()
-               letter = list(self._prefixes())[letterRow]
-               letterItem = self._alphaItem[letter]
-               rowIndex = index.row()
-               item = letterItem.child(rowIndex, 0)
-               contactDetails = item.data().toPyObject()
-
-               name = str(contactDetails[QtCore.QString("name")])
-               if not name:
-                       name = str(contactDetails[QtCore.QString("location")])
-               if not name:
-                       name = "Unknown"
-
-               contactId = str(contactDetails[QtCore.QString("contactId")])
-               numbers = contactDetails[QtCore.QString("numbers")]
-               numbers = [
-                       dict(
-                               (str(k), str(v))
-                               for (k, v) in number.iteritems()
-                       )
-                       for number in numbers
-               ]
-               numbersWithDescriptions = [
-                       (
-                               number["phoneNumber"],
-                               self._choose_phonetype(number),
-                       )
-                       for number in numbers
-               ]
-               title = name
-               description = name
-               self._session.draft.add_contact(contactId, title, description, numbersWithDescriptions)
+               with qui_utils.notify_error(self._errorLog):
+                       letterIndex = index.parent()
+                       assert letterIndex.isValid()
+                       letterRow = letterIndex.row()
+                       letter = list(self._prefixes())[letterRow]
+                       letterItem = self._alphaItem[letter]
+                       rowIndex = index.row()
+                       item = letterItem.child(rowIndex, 0)
+                       contactDetails = item.data().toPyObject()
+
+                       name = str(contactDetails[QtCore.QString("name")])
+                       if not name:
+                               name = str(contactDetails[QtCore.QString("location")])
+                       if not name:
+                               name = "Unknown"
+
+                       contactId = str(contactDetails[QtCore.QString("contactId")])
+                       numbers = contactDetails[QtCore.QString("numbers")]
+                       numbers = [
+                               dict(
+                                       (str(k), str(v))
+                                       for (k, v) in number.iteritems()
+                               )
+                               for number in numbers
+                       ]
+                       numbersWithDescriptions = [
+                               (
+                                       number["phoneNumber"],
+                                       self._choose_phonetype(number),
+                               )
+                               for number in numbers
+                       ]
+                       title = name
+                       description = name
+                       self._session.draft.add_contact(contactId, title, description, numbersWithDescriptions)
 
        @staticmethod
        def _choose_phonetype(numberDetails):
index 949b29a..1ce732c 100644 (file)
@@ -3,6 +3,7 @@ from __future__ import with_statement
 import os
 import time
 import datetime
+import contextlib
 import logging
 
 try:
@@ -23,6 +24,15 @@ import constants
 _moduleLogger = logging.getLogger(__name__)
 
 
+@contextlib.contextmanager
+def notify_busy(log, message):
+       log.push_busy(message)
+       try:
+               yield
+       finally:
+               log.pop(message)
+
+
 class _DraftContact(object):
 
        def __init__(self, title, description, numbersWithDescriptions):
@@ -44,8 +54,9 @@ class Draft(QtCore.QObject):
 
        recipientsChanged = QtCore.pyqtSignal()
 
-       def __init__(self, pool, backend):
+       def __init__(self, pool, backend, errorLog):
                QtCore.QObject.__init__(self)
+               self._errorLog = errorLog
                self._contacts = {}
                self._pool = pool
                self._backend = backend
@@ -114,11 +125,12 @@ class Draft(QtCore.QObject):
        def _send(self, numbers, text):
                self.sendingMessage.emit()
                try:
-                       yield (
-                               self._backend[0].send_sms,
-                               (numbers, text),
-                               {},
-                       )
+                       with notify_busy(self._errorLog, "Sending Text"):
+                               yield (
+                                       self._backend[0].send_sms,
+                                       (numbers, text),
+                                       {},
+                               )
                        self.sentMessage.emit()
                        self.clear()
                except Exception, e:
@@ -127,11 +139,12 @@ class Draft(QtCore.QObject):
        def _call(self, number):
                self.calling.emit()
                try:
-                       yield (
-                               self._backend[0].call,
-                               (number, ),
-                               {},
-                       )
+                       with notify_busy(self._errorLog, "Calling"):
+                               yield (
+                                       self._backend[0].call,
+                                       (number, ),
+                                       {},
+                               )
                        self.called.emit()
                        self.clear()
                except Exception, e:
@@ -140,11 +153,12 @@ class Draft(QtCore.QObject):
        def _cancel(self):
                self.cancelling.emit()
                try:
-                       yield (
-                               self._backend[0].cancel,
-                               (),
-                               {},
-                       )
+                       with notify_busy(self._errorLog, "Cancelling"):
+                               yield (
+                                       self._backend[0].cancel,
+                                       (),
+                                       {},
+                               )
                        self.cancelled.emit()
                except Exception, e:
                        self.error.emit(str(e))
@@ -175,15 +189,16 @@ class Session(QtCore.QObject):
        _LOGGEDOUT_TIME = -1
        _LOGGINGIN_TIME = 0
 
-       def __init__(self, cachePath = None):
+       def __init__(self, errorLog, cachePath = None):
                QtCore.QObject.__init__(self)
+               self._errorLog = errorLog
                self._pool = qore_utils.AsyncPool()
                self._backend = []
                self._loggedInTime = self._LOGGEDOUT_TIME
                self._loginOps = []
                self._cachePath = cachePath
                self._username = None
-               self._draft = Draft(self._pool, self._backend)
+               self._draft = Draft(self._pool, self._backend, self._errorLog)
 
                self._contacts = {}
                self._contactUpdateTime = datetime.datetime(1971, 1, 1)
@@ -292,11 +307,12 @@ class Session(QtCore.QObject):
                assert self.state == self.LOGGEDIN_STATE
                oldDnd = self._dnd
                try:
-                       yield (
-                               self._backend[0].set_dnd,
-                               (dnd, ),
-                               {},
-                       )
+                       with notify_busy(self._errorLog, "Setting DND Status"):
+                               yield (
+                                       self._backend[0].set_dnd,
+                                       (dnd, ),
+                                       {},
+                               )
                except Exception, e:
                        self.error.emit(str(e))
                        return
@@ -327,11 +343,12 @@ class Session(QtCore.QObject):
                assert self.state == self.LOGGEDIN_STATE
                oldCallback = self._callback
                try:
-                       yield (
-                               self._backend[0].set_callback_number,
-                               (callback, ),
-                               {},
-                       )
+                       with notify_busy(self._errorLog, "Setting Callback"):
+                               yield (
+                                       self._backend[0].set_callback_number,
+                                       (callback, ),
+                                       {},
+                               )
                except Exception, e:
                        self.error.emit(str(e))
                        return
@@ -340,58 +357,59 @@ class Session(QtCore.QObject):
                        self.callbackNumberChanged.emit(self._callback)
 
        def _login(self, username, password):
-               self._loggedInTime = self._LOGGINGIN_TIME
-               self.stateChange.emit(self.LOGGINGIN_STATE)
-               finalState = self.LOGGEDOUT_STATE
-               try:
-                       isLoggedIn = False
-
-                       if not isLoggedIn and self._backend[0].is_quick_login_possible():
-                               isLoggedIn = yield (
-                                       self._backend[0].is_authed,
-                                       (),
-                                       {},
-                               )
-                               if isLoggedIn:
-                                       _moduleLogger.info("Logged in through cookies")
-                               else:
-                                       # Force a clearing of the cookies
-                                       yield (
-                                               self._backend[0].logout,
+               with notify_busy(self._errorLog, "Logging In"):
+                       self._loggedInTime = self._LOGGINGIN_TIME
+                       self.stateChange.emit(self.LOGGINGIN_STATE)
+                       finalState = self.LOGGEDOUT_STATE
+                       try:
+                               isLoggedIn = False
+
+                               if not isLoggedIn and self._backend[0].is_quick_login_possible():
+                                       isLoggedIn = yield (
+                                               self._backend[0].is_authed,
                                                (),
                                                {},
                                        )
+                                       if isLoggedIn:
+                                               _moduleLogger.info("Logged in through cookies")
+                                       else:
+                                               # Force a clearing of the cookies
+                                               yield (
+                                                       self._backend[0].logout,
+                                                       (),
+                                                       {},
+                                               )
+
+                               if not isLoggedIn:
+                                       isLoggedIn = yield (
+                                               self._backend[0].login,
+                                               (username, password),
+                                               {},
+                                       )
+                                       if isLoggedIn:
+                                               _moduleLogger.info("Logged in through credentials")
 
-                       if not isLoggedIn:
-                               isLoggedIn = yield (
-                                       self._backend[0].login,
-                                       (username, password),
-                                       {},
-                               )
                                if isLoggedIn:
-                                       _moduleLogger.info("Logged in through credentials")
-
-                       if isLoggedIn:
-                               self._loggedInTime = int(time.time())
-                               oldUsername = self._username
-                               self._username = username
-                               finalState = self.LOGGEDIN_STATE
-                               self.loggedIn.emit()
-                               if oldUsername != self._username:
-                                       needOps = not self._load()
-                               else:
-                                       needOps = True
-                               if needOps:
-                                       loginOps = self._loginOps[:]
-                               else:
-                                       loginOps = []
-                               del self._loginOps[:]
-                               for asyncOp in loginOps:
-                                       asyncOp.start()
-               except Exception, e:
-                       self.error.emit(str(e))
-               finally:
-                       self.stateChange.emit(finalState)
+                                       self._loggedInTime = int(time.time())
+                                       oldUsername = self._username
+                                       self._username = username
+                                       finalState = self.LOGGEDIN_STATE
+                                       self.loggedIn.emit()
+                                       if oldUsername != self._username:
+                                               needOps = not self._load()
+                                       else:
+                                               needOps = True
+                                       if needOps:
+                                               loginOps = self._loginOps[:]
+                                       else:
+                                               loginOps = []
+                                       del self._loginOps[:]
+                                       for asyncOp in loginOps:
+                                               asyncOp.start()
+                       except Exception, e:
+                               self.error.emit(str(e))
+                       finally:
+                               self.stateChange.emit(finalState)
 
        def _load(self):
                updateContacts = len(self._contacts) != 0
@@ -521,11 +539,12 @@ class Session(QtCore.QObject):
 
        def _update_contacts(self):
                try:
-                       self._contacts = yield (
-                               self._backend[0].get_contacts,
-                               (),
-                               {},
-                       )
+                       with notify_busy(self._errorLog, "Updating Contacts"):
+                               self._contacts = yield (
+                                       self._backend[0].get_contacts,
+                                       (),
+                                       {},
+                               )
                except Exception, e:
                        self.error.emit(str(e))
                        return
@@ -534,11 +553,12 @@ class Session(QtCore.QObject):
 
        def _update_messages(self):
                try:
-                       self._messages = yield (
-                               self._backend[0].get_messages,
-                               (),
-                               {},
-                       )
+                       with notify_busy(self._errorLog, "Updating Messages"):
+                               self._messages = yield (
+                                       self._backend[0].get_messages,
+                                       (),
+                                       {},
+                               )
                except Exception, e:
                        self.error.emit(str(e))
                        return
@@ -547,11 +567,12 @@ class Session(QtCore.QObject):
 
        def _update_history(self):
                try:
-                       self._history = yield (
-                               self._backend[0].get_recent,
-                               (),
-                               {},
-                       )
+                       with notify_busy(self._errorLog, "Updating History"):
+                               self._history = yield (
+                                       self._backend[0].get_recent,
+                                       (),
+                                       {},
+                               )
                except Exception, e:
                        self.error.emit(str(e))
                        return
index d15761b..7a9ac52 100644 (file)
@@ -1,4 +1,5 @@
 import sys
+import contextlib
 import logging
 
 from PyQt4 import QtCore
@@ -10,6 +11,33 @@ import misc
 _moduleLogger = logging.getLogger(__name__)
 
 
+@contextlib.contextmanager
+def notify_error(log):
+       try:
+               yield
+       except:
+               log.push_exception()
+
+
+class ErrorMessage(object):
+
+       LEVEL_BUSY = "busy"
+       LEVEL_INFO = "info"
+       LEVEL_ERROR = "error"
+
+       def __init__(self, message, level):
+               self._message = message
+               self._level = level
+
+       @property
+       def level(self):
+               return self._level
+
+       @property
+       def message(self):
+               return self._message
+
+
 class QErrorLog(QtCore.QObject):
 
        messagePushed = QtCore.pyqtSignal()
@@ -19,22 +47,41 @@ class QErrorLog(QtCore.QObject):
                QtCore.QObject.__init__(self)
                self._messages = []
 
+       def push_busy(self, message):
+               self._push_message(message, ErrorMessage.LEVEL_BUSY)
+
        def push_message(self, message):
-               self._messages.append(message)
-               self.messagePushed.emit()
+               self._push_message(message, ErrorMessage.LEVEL_INFO)
+
+       def push_error(self, message):
+               self._push_message(message, ErrorMessage.LEVEL_ERROR)
 
        def push_exception(self):
                userMessage = str(sys.exc_info()[1])
                _moduleLogger.exception(userMessage)
-               self.push_message(userMessage)
+               self.push_error(userMessage)
 
-       def pop_message(self):
-               del self._messages[0]
+       def pop(self, message = None):
+               if message is None:
+                       del self._messages[0]
+               else:
+                       messageIndex = [
+                               i
+                               for (i, error) in enumerate(self._messages)
+                               if error.message == message
+                       ]
+                       # Might be removed out of order
+                       if messageIndex:
+                               del self._messages[messageIndex[0]]
                self.messagePopped.emit()
 
        def peek_message(self):
                return self._messages[0]
 
+       def _push_message(self, message, level):
+               self._messages.append(ErrorMessage(message, level))
+               self.messagePushed.emit()
+
        def __len__(self):
                return len(self._messages)
 
@@ -46,22 +93,36 @@ class ErrorDisplay(object):
                self._errorLog.messagePushed.connect(self._on_message_pushed)
                self._errorLog.messagePopped.connect(self._on_message_popped)
 
-               errorIcon = get_theme_icon(("dialog-error", "app_install_error", "gtk-dialog-error"))
-               self._severityIcon = errorIcon.pixmap(32, 32)
+               self._icons = {
+                       ErrorMessage.LEVEL_BUSY:
+                               get_theme_icon(
+                                       #("process-working", "gtk-refresh")
+                                       ("gtk-refresh", )
+                               ).pixmap(32, 32),
+                       ErrorMessage.LEVEL_INFO:
+                               get_theme_icon(
+                                       ("dialog-information", "general_notes", "gtk-info")
+                               ).pixmap(32, 32),
+                       ErrorMessage.LEVEL_ERROR:
+                               get_theme_icon(
+                                       ("dialog-error", "app_install_error", "gtk-dialog-error")
+                               ).pixmap(32, 32),
+               }
                self._severityLabel = QtGui.QLabel()
-               self._severityLabel.setPixmap(self._severityIcon)
+               self._severityLabel.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
 
                self._message = QtGui.QLabel()
                self._message.setText("Boo")
+               self._message.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
 
                closeIcon = get_theme_icon(("window-close", "general_close", "gtk-close"))
                self._closeLabel = QtGui.QPushButton(closeIcon, "")
                self._closeLabel.clicked.connect(self._on_close)
 
                self._controlLayout = QtGui.QHBoxLayout()
-               self._controlLayout.addWidget(self._severityLabel)
-               self._controlLayout.addWidget(self._message)
-               self._controlLayout.addWidget(self._closeLabel)
+               self._controlLayout.addWidget(self._severityLabel, 1, QtCore.Qt.AlignCenter)
+               self._controlLayout.addWidget(self._message, 1000)
+               self._controlLayout.addWidget(self._closeLabel, 1, QtCore.Qt.AlignCenter)
 
                self._topLevelLayout = QtGui.QHBoxLayout()
                self._topLevelLayout.addLayout(self._controlLayout)
@@ -77,13 +138,15 @@ class ErrorDisplay(object):
        @QtCore.pyqtSlot(bool)
        @misc.log_exception(_moduleLogger)
        def _on_close(self, checked = False):
-               self._errorLog.pop_message()
+               self._errorLog.pop()
 
        @QtCore.pyqtSlot()
        @misc.log_exception(_moduleLogger)
        def _on_message_pushed(self):
                if 1 <= len(self._errorLog) and self._widget.isHidden():
-                       self._message.setText(self._errorLog.peek_message())
+                       error = self._errorLog.peek_message()
+                       self._message.setText(error.message)
+                       self._severityLabel.setPixmap(self._icons[error.level])
                        self._widget.show()
 
        @QtCore.pyqtSlot()
@@ -93,7 +156,9 @@ class ErrorDisplay(object):
                        self._message.setText("")
                        self._widget.hide()
                else:
-                       self._message.setText(self._errorLog.peek_message())
+                       error = self._errorLog.peek_message()
+                       self._message.setText(error.message)
+                       self._severityLabel.setPixmap(self._icons[error.level])
 
 
 class QHtmlDelegate(QtGui.QStyledItemDelegate):