From: Ed Page Date: Wed, 8 Dec 2010 02:37:40 +0000 (-0600) Subject: Adding progress notification X-Git-Url: http://git.maemo.org/git/?a=commitdiff_plain;h=5511579804f952c3403d6fb1c430254b79e5a791;hp=dc58d53b93280fd7bc08fff84c2f8e267ef3e4e7;p=gc-dialer Adding progress notification --- diff --git a/src/dialcentral_qt.py b/src/dialcentral_qt.py index fd5f0c5..2d366c0 100755 --- a/src/dialcentral_qt.py +++ b/src/dialcentral_qt.py @@ -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) diff --git a/src/dialogs.py b/src/dialogs.py index 67950aa..31e91e6 100644 --- a/src/dialogs.py +++ b/src/dialogs.py @@ -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) diff --git a/src/gv_views.py b/src/gv_views.py index 250e5f0..23c07c8 100644 --- a/src/gv_views.py +++ b/src/gv_views.py @@ -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("%s" % "".join(rowItems)) - description = "%s
" % "".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("%s" % "".join(rowItems)) + description = "%s
" % "".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): diff --git a/src/session.py b/src/session.py index 949b29a..1ce732c 100644 --- a/src/session.py +++ b/src/session.py @@ -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 diff --git a/src/util/qui_utils.py b/src/util/qui_utils.py index d15761b..7a9ac52 100644 --- a/src/util/qui_utils.py +++ b/src/util/qui_utils.py @@ -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):