from PyQt4 import QtCore
import constants
-import maeqt
+from util import qui_utils
from util import misc as misc_utils
import unit_data
self._favoritesWindow = None
self._inputUnitValue = QtGui.QLineEdit()
- maeqt.mark_numbers_preferred(self._inputUnitValue)
+ qui_utils.mark_numbers_preferred(self._inputUnitValue)
self._inputUnitValue.textEdited.connect(self._on_value_edited)
self._inputUnitSymbol = QtGui.QLabel()
self._outputUnitValue = QtGui.QLineEdit()
- maeqt.mark_numbers_preferred(self._outputUnitValue)
+ qui_utils.mark_numbers_preferred(self._outputUnitValue)
self._outputUnitValue.textEdited.connect(self._on_output_value_edited)
self._outputUnitSymbol = QtGui.QLabel()
self._window = QtGui.QMainWindow(parent)
self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
- maeqt.set_autorient(self._window, True)
- maeqt.set_stackable(self._window, True)
+ qui_utils.set_stackable(self._window, True)
self._window.setWindowTitle("%s - Quick Convert" % (constants.__pretty_app_name__, ))
self._window.setWindowIcon(QtGui.QIcon(app.appIconPath))
self._window.setCentralWidget(centralWidget)
self._window = QtGui.QMainWindow(parent)
self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
- maeqt.set_autorient(self._window, True)
- maeqt.set_stackable(self._window, True)
+ qui_utils.set_stackable(self._window, True)
self._window.setWindowTitle("%s - Categories" % constants.__pretty_app_name__)
self._window.setWindowIcon(QtGui.QIcon(self._app.appIconPath))
self._window.setCentralWidget(centralWidget)
self._selectedUnitName = QtGui.QLabel()
self._selectedUnitValue = QtGui.QLineEdit()
self._selectedUnitValue.textEdited.connect(self._on_value_edited)
- maeqt.mark_numbers_preferred(self._selectedUnitValue)
+ qui_utils.mark_numbers_preferred(self._selectedUnitValue)
self._selectedUnitSymbol = QtGui.QLabel()
self._updateDelayTimer = QtCore.QTimer()
self._updateDelayTimer.setInterval(100)
self._window = QtGui.QMainWindow(parent)
self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
- maeqt.set_autorient(self._window, True)
- maeqt.set_stackable(self._window, True)
+ qui_utils.set_stackable(self._window, True)
self._window.setWindowTitle("%s - %s" % (constants.__pretty_app_name__, category))
self._window.setWindowIcon(QtGui.QIcon(app.appIconPath))
self._window.setCentralWidget(centralWidget)
+++ /dev/null
-from PyQt4 import QtCore
-from PyQt4 import QtGui
-
-
-def _null_set_stackable(window, isStackable):
- pass
-
-
-def _maemo_set_stackable(window, isStackable):
- window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable)
-
-
-try:
- QtCore.Qt.WA_Maemo5StackedWindow
- set_stackable = _maemo_set_stackable
-except AttributeError:
- set_stackable = _null_set_stackable
-
-
-def _null_set_autorient(window, isStackable):
- pass
-
-
-def _maemo_set_autorient(window, isStackable):
- window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable)
-
-
-try:
- QtCore.Qt.WA_Maemo5AutoOrientation
- set_autorient = _maemo_set_autorient
-except AttributeError:
- set_autorient = _null_set_autorient
-
-
-def _null_set_landscape(window, isStackable):
- pass
-
-
-def _maemo_set_landscape(window, isStackable):
- window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable)
-
-
-try:
- QtCore.Qt.WA_Maemo5LandscapeOrientation
- set_landscape = _maemo_set_landscape
-except AttributeError:
- set_landscape = _null_set_landscape
-
-
-def _null_set_portrait(window, isStackable):
- pass
-
-
-def _maemo_set_portrait(window, isStackable):
- window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable)
-
-
-try:
- QtCore.Qt.WA_Maemo5PortraitOrientation
- set_portrait = _maemo_set_portrait
-except AttributeError:
- set_portrait = _null_set_portrait
-
-
-def _null_show_progress_indicator(window, isStackable):
- pass
-
-
-def _maemo_show_progress_indicator(window, isStackable):
- window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable)
-
-
-try:
- QtCore.Qt.WA_Maemo5ShowProgressIndicator
- show_progress_indicator = _maemo_show_progress_indicator
-except AttributeError:
- show_progress_indicator = _null_show_progress_indicator
-
-
-def _null_mark_numbers_preferred(widget):
- pass
-
-
-def _newqt_mark_numbers_preferred(widget):
- widget.setInputMethodHints(QtCore.Qt.ImhPreferNumbers)
-
-
-try:
- QtCore.Qt.ImhPreferNumbers
- mark_numbers_preferred = _newqt_mark_numbers_preferred
-except AttributeError:
- mark_numbers_preferred = _null_mark_numbers_preferred
-
-
-def screen_orientation():
- geom = QtGui.QApplication.desktop().screenGeometry()
- if geom.width() <= geom.height():
- return QtCore.Qt.Vertical
- else:
- return QtCore.Qt.Horizontal
-
-
-def _null_get_theme_icon(iconNames, fallback = None):
- icon = fallback if fallback is not None else QtGui.QIcon()
- return icon
-
-
-def _newqt_get_theme_icon(iconNames, fallback = None):
- for iconName in iconNames:
- if QtGui.QIcon.hasThemeIcon(iconName):
- icon = QtGui.QIcon.fromTheme(iconName)
- break
- else:
- icon = fallback if fallback is not None else QtGui.QIcon()
- return icon
-
-
-try:
- QtGui.QIcon.fromTheme
- get_theme_icon = _newqt_get_theme_icon
-except AttributeError:
- get_theme_icon = _null_get_theme_icon
import time
import functools
import contextlib
+import logging
+
+import misc
+
+
+_moduleLogger = logging.getLogger(__name__)
+
+
+class AsyncLinearExecution(object):
+
+ def __init__(self, pool, func):
+ self._pool = pool
+ self._func = func
+ self._run = None
+
+ def start(self, *args, **kwds):
+ assert self._run is None, "Task already started"
+ self._run = self._func(*args, **kwds)
+ trampoline, args, kwds = self._run.send(None) # priming the function
+ self._pool.add_task(
+ trampoline,
+ args,
+ kwds,
+ self.on_success,
+ self.on_error,
+ )
+
+ @misc.log_exception(_moduleLogger)
+ def on_success(self, result):
+ _moduleLogger.debug("Processing success for: %r", self._func)
+ try:
+ trampoline, args, kwds = self._run.send(result)
+ except StopIteration, e:
+ pass
+ else:
+ self._pool.add_task(
+ trampoline,
+ args,
+ kwds,
+ self.on_success,
+ self.on_error,
+ )
+
+ @misc.log_exception(_moduleLogger)
+ def on_error(self, error):
+ _moduleLogger.debug("Processing error for: %r", self._func)
+ try:
+ trampoline, args, kwds = self._run.throw(error)
+ except StopIteration, e:
+ pass
+ else:
+ self._pool.add_task(
+ trampoline,
+ args,
+ kwds,
+ self.on_success,
+ self.on_error,
+ )
+
+ def __repr__(self):
+ return "<async %s at 0x%x>" % (self._func.__name__, id(self))
+
+ def __hash__(self):
+ return hash(self._func)
+
+ def __eq__(self, other):
+ return self._func == other._func
+
+ def __ne__(self, other):
+ return self._func != other._func
def synchronized(lock):
result = func(*args, **kwds)
isError = False
except Exception, e:
- _moduleLogger.exception("Error, passing it back to the main thread")
+ _moduleLogger.error("Error, passing it back to the main thread")
result = e
isError = True
self.__workQueue.task_done()
_moduleLogger.debug("Shutting down worker thread")
-class AsyncLinearExecution(object):
-
- def __init__(self, pool, func):
- self._pool = pool
- self._func = func
- self._run = None
-
- def start(self, *args, **kwds):
- assert self._run is None
- self._run = self._func(*args, **kwds)
- trampoline, args, kwds = self._run.send(None) # priming the function
- self._pool.add_task(
- trampoline,
- args,
- kwds,
- self.on_success,
- self.on_error,
- )
-
- @misc.log_exception(_moduleLogger)
- def on_success(self, result):
- #_moduleLogger.debug("Processing success for: %r", self._func)
- try:
- trampoline, args, kwds = self._run.send(result)
- except StopIteration, e:
- pass
- else:
- self._pool.add_task(
- trampoline,
- args,
- kwds,
- self.on_success,
- self.on_error,
- )
-
- @misc.log_exception(_moduleLogger)
- def on_error(self, error):
- #_moduleLogger.debug("Processing error for: %r", self._func)
- try:
- trampoline, args, kwds = self._run.throw(error)
- except StopIteration, e:
- pass
- else:
- self._pool.add_task(
- trampoline,
- args,
- kwds,
- self.on_success,
- self.on_error,
- )
-
-
class AutoSignal(object):
def __init__(self, toplevel):
import string
+class AnyData(object):
+
+ pass
+
+
_indentationLevel = [0]
uglynumber = re.sub('[^0-9+]', '', prettynumber)
if uglynumber.startswith("+"):
pass
- elif uglynumber.startswith("1") and len(uglynumber) == 11:
+ elif uglynumber.startswith("1"):
uglynumber = "+"+uglynumber
- elif len(uglynumber) == 10:
+ elif 10 <= len(uglynumber):
+ assert uglynumber[0] not in ("+", "1"), "Number format confusing"
uglynumber = "+1"+uglynumber
else:
pass
- #validateRe = re.compile("^\+?[0-9]{10,}$")
- #assert validateRe.match(uglynumber) is not None
-
return uglynumber
return _VALIDATE_RE.match(number) is not None
+def make_ugly(prettynumber):
+ """
+ function to take a phone number and strip out all non-numeric
+ characters
+
+ >>> make_ugly("+012-(345)-678-90")
+ '+01234567890'
+ """
+ return normalize_number(prettynumber)
+
+
+def _make_pretty_with_areacode(phonenumber):
+ prettynumber = "(%s)" % (phonenumber[0:3], )
+ if 3 < len(phonenumber):
+ prettynumber += " %s" % (phonenumber[3:6], )
+ if 6 < len(phonenumber):
+ prettynumber += "-%s" % (phonenumber[6:], )
+ return prettynumber
+
+
+def _make_pretty_local(phonenumber):
+ prettynumber = "%s" % (phonenumber[0:3], )
+ if 3 < len(phonenumber):
+ prettynumber += "-%s" % (phonenumber[3:], )
+ return prettynumber
+
+
+def _make_pretty_international(phonenumber):
+ prettynumber = phonenumber
+ if phonenumber.startswith("1"):
+ prettynumber = "1 "
+ prettynumber += _make_pretty_with_areacode(phonenumber[1:])
+ return prettynumber
+
+
+def make_pretty(phonenumber):
+ """
+ Function to take a phone number and return the pretty version
+ pretty numbers:
+ if phonenumber begins with 0:
+ ...-(...)-...-....
+ if phonenumber begins with 1: ( for gizmo callback numbers )
+ 1 (...)-...-....
+ if phonenumber is 13 digits:
+ (...)-...-....
+ if phonenumber is 10 digits:
+ ...-....
+ >>> make_pretty("12")
+ '12'
+ >>> make_pretty("1234567")
+ '123-4567'
+ >>> make_pretty("2345678901")
+ '+1 (234) 567-8901'
+ >>> make_pretty("12345678901")
+ '+1 (234) 567-8901'
+ >>> make_pretty("01234567890")
+ '+012 (345) 678-90'
+ >>> make_pretty("+01234567890")
+ '+012 (345) 678-90'
+ >>> make_pretty("+12")
+ '+1 (2)'
+ >>> make_pretty("+123")
+ '+1 (23)'
+ >>> make_pretty("+1234")
+ '+1 (234)'
+ """
+ if phonenumber is None or phonenumber == "":
+ return ""
+
+ phonenumber = normalize_number(phonenumber)
+
+ if phonenumber == "":
+ return ""
+ elif phonenumber[0] == "+":
+ prettynumber = _make_pretty_international(phonenumber[1:])
+ if not prettynumber.startswith("+"):
+ prettynumber = "+"+prettynumber
+ elif 8 < len(phonenumber) and phonenumber[0] in ("1", ):
+ prettynumber = _make_pretty_international(phonenumber)
+ elif 7 < len(phonenumber):
+ prettynumber = _make_pretty_with_areacode(phonenumber)
+ elif 3 < len(phonenumber):
+ prettynumber = _make_pretty_local(phonenumber)
+ else:
+ prettynumber = phonenumber
+ return prettynumber.strip()
+
+
+def similar_ugly_numbers(lhs, rhs):
+ return (
+ lhs == rhs or
+ lhs[1:] == rhs and lhs.startswith("1") or
+ lhs[2:] == rhs and lhs.startswith("+1") or
+ lhs == rhs[1:] and rhs.startswith("1") or
+ lhs == rhs[2:] and rhs.startswith("+1")
+ )
+
+
+def abbrev_relative_date(date):
+ """
+ >>> abbrev_relative_date("42 hours ago")
+ '42 h'
+ >>> abbrev_relative_date("2 days ago")
+ '2 d'
+ >>> abbrev_relative_date("4 weeks ago")
+ '4 w'
+ """
+ parts = date.split(" ")
+ return "%s %s" % (parts[0], parts[1][0])
+
+
def parse_version(versionText):
"""
>>> parse_version("0.5.2")
--- /dev/null
+import logging
+
+from PyQt4 import QtCore
+
+import misc
+
+
+_moduleLogger = logging.getLogger(__name__)
+
+
+class QThread44(QtCore.QThread):
+ """
+ This is to imitate QThread in Qt 4.4+ for when running on older version
+ See http://labs.trolltech.com/blogs/2010/06/17/youre-doing-it-wrong
+ (On Lucid I have Qt 4.7 and this is still an issue)
+ """
+
+ def __init__(self, parent = None):
+ QtCore.QThread.__init__(self, parent)
+
+ def run(self):
+ self.exec_()
+
+
+class _ParentThread(QtCore.QObject):
+
+ def __init__(self, pool):
+ QtCore.QObject.__init__(self)
+ self._pool = pool
+
+ @QtCore.pyqtSlot(object)
+ @misc.log_exception(_moduleLogger)
+ def _on_task_complete(self, taskResult):
+ on_success, on_error, isError, result = taskResult
+ if not self._pool._isRunning:
+ if isError:
+ _moduleLogger.error("Masking: %s" % (result, ))
+ isError = True
+ result = StopIteration("Cancelling all callbacks")
+ callback = on_success if not isError else on_error
+ try:
+ callback(result)
+ except Exception:
+ _moduleLogger.exception("Callback errored")
+
+
+class _WorkerThread(QtCore.QObject):
+
+ taskComplete = QtCore.pyqtSignal(object)
+
+ def __init__(self, pool):
+ QtCore.QObject.__init__(self)
+ self._pool = pool
+
+ @QtCore.pyqtSlot(object)
+ @misc.log_exception(_moduleLogger)
+ def _on_task_added(self, task):
+ if not self._pool._isRunning:
+ _moduleLogger.error("Dropping task")
+
+ func, args, kwds, on_success, on_error = task
+
+ try:
+ result = func(*args, **kwds)
+ isError = False
+ except Exception, e:
+ _moduleLogger.error("Error, passing it back to the main thread")
+ result = e
+ isError = True
+
+ taskResult = on_success, on_error, isError, result
+ self.taskComplete.emit(taskResult)
+
+ @QtCore.pyqtSlot()
+ @misc.log_exception(_moduleLogger)
+ def _on_stop_requested(self):
+ self._pool._thread.quit()
+
+
+class AsyncPool(QtCore.QObject):
+
+ _addTask = QtCore.pyqtSignal(object)
+ _stopPool = QtCore.pyqtSignal()
+
+ def __init__(self):
+ QtCore.QObject.__init__(self)
+ self._thread = QThread44()
+ self._isRunning = True
+ self._parent = _ParentThread(self)
+ self._worker = _WorkerThread(self)
+ self._worker.moveToThread(self._thread)
+
+ self._addTask.connect(self._worker._on_task_added)
+ self._worker.taskComplete.connect(self._parent._on_task_complete)
+ self._stopPool.connect(self._worker._on_stop_requested)
+
+ def start(self):
+ self._thread.start()
+
+ def stop(self):
+ self._isRunning = False
+ self._stopPool.emit()
+
+ def add_task(self, func, args, kwds, on_success, on_error):
+ assert self._isRunning, "Task queue not started"
+ task = func, args, kwds, on_success, on_error
+ self._addTask.emit(task)
from PyQt4 import QtGui
from PyQt4 import QtCore
-try:
- from util import misc as misc_utils
-except ImportError:
- class misc_utils(object):
-
- @staticmethod
- def log_exception(logger):
-
- def wrapper(func):
- return func
- return wrapper
+import misc as misc_utils
_moduleLogger = logging.getLogger(__name__)
_TWOPI = 2 * math.pi
-class EIGHT_SLICE_PIE(object):
-
- SLICE_CENTER = -1
- SLICE_NORTH = 0
- SLICE_NORTH_WEST = 1
- SLICE_WEST = 2
- SLICE_SOUTH_WEST = 3
- SLICE_SOUTH = 4
- SLICE_SOUTH_EAST = 5
- SLICE_EAST = 6
- SLICE_NORTH_EAST = 7
-
- MAX_ANGULAR_SLICES = 8
-
- SLICE_DIRECTIONS = [
- SLICE_CENTER,
- SLICE_NORTH,
- SLICE_NORTH_WEST,
- SLICE_WEST,
- SLICE_SOUTH_WEST,
- SLICE_SOUTH,
- SLICE_SOUTH_EAST,
- SLICE_EAST,
- SLICE_NORTH_EAST,
- ]
-
- SLICE_DIRECTION_NAMES = [
- "CENTER",
- "NORTH",
- "NORTH_WEST",
- "WEST",
- "SOUTH_WEST",
- "SOUTH",
- "SOUTH_EAST",
- "EAST",
- "NORTH_EAST",
- ]
-
-
def _radius_at(center, pos):
delta = pos - center
xDelta = delta.x()
SHAPE_SQUARE = "square"
DEFAULT_SHAPE = SHAPE_SQUARE
- def __init__(self, filing):
+ BACKGROUND_FILL = "fill"
+ BACKGROUND_NOFILL = "no fill"
+
+ def __init__(self, filing, background = BACKGROUND_FILL):
self._filing = filing
self._cachedOuterRadius = self._filing.outerRadius()
canvasSize = self._cachedOuterRadius * 2 + 1
self._canvas = QtGui.QPixmap(canvasSize, canvasSize)
self._mask = None
+ self._backgroundState = background
self.palette = None
def pieSize(self):
painter = QtGui.QPainter(self._canvas)
painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
- adjustmentRect = self._canvas.rect().adjusted(0, 0, -1, -1)
+ self.paintPainter(selectionIndex, painter)
+
+ return self._canvas
+
+ def paintPainter(self, selectionIndex, painter):
+ adjustmentRect = painter.viewport().adjusted(0, 0, -1, -1)
numChildren = len(self._filing)
if numChildren == 0:
- if selectionIndex == PieFiling.SELECTION_CENTER and self._filing.center().isEnabled():
- painter.setBrush(self.palette.highlight())
- else:
- painter.setBrush(self.palette.window())
- painter.setPen(self.palette.mid().color())
-
- painter.drawRect(self._canvas.rect())
- self._paint_center_foreground(painter, selectionIndex)
+ self._paint_center_background(painter, adjustmentRect, selectionIndex)
+ self._paint_center_foreground(painter, adjustmentRect, selectionIndex)
return self._canvas
- elif numChildren == 1:
- if selectionIndex == 0 and self._filing[0].isEnabled():
- painter.setBrush(self.palette.highlight())
- else:
- painter.setBrush(self.palette.window())
-
- painter.fillRect(self._canvas.rect(), painter.brush())
else:
for i in xrange(len(self._filing)):
self._paint_slice_background(painter, adjustmentRect, i, selectionIndex)
self._paint_center_background(painter, adjustmentRect, selectionIndex)
- self._paint_center_foreground(painter, selectionIndex)
+ self._paint_center_foreground(painter, adjustmentRect, selectionIndex)
for i in xrange(len(self._filing)):
- self._paint_slice_foreground(painter, i, selectionIndex)
-
- return self._canvas
+ self._paint_slice_foreground(painter, adjustmentRect, i, selectionIndex)
def _generate_mask(self, mask):
"""
else:
raise NotImplementedError(self.DEFAULT_SHAPE)
- if i == selectionIndex and self._filing[i].isEnabled():
- painter.setBrush(self.palette.highlight())
+ if self._backgroundState == self.BACKGROUND_NOFILL:
+ painter.setBrush(QtGui.QBrush(QtCore.Qt.transparent))
+ painter.setPen(self.palette.highlight().color())
else:
- painter.setBrush(self.palette.window())
- painter.setPen(self.palette.mid().color())
+ if i == selectionIndex and self._filing[i].isEnabled():
+ painter.setBrush(self.palette.highlight())
+ painter.setPen(self.palette.highlight().color())
+ else:
+ painter.setBrush(self.palette.window())
+ painter.setPen(self.palette.window().color())
a = self._filing._index_to_angle(i, True)
b = self._filing._index_to_angle(i + 1, True)
sizeInDeg = (size * 360 * 16) / _TWOPI
painter.drawPie(adjustmentRect, int(startAngleInDeg), int(sizeInDeg))
- def _paint_slice_foreground(self, painter, i, selectionIndex):
+ def _paint_slice_foreground(self, painter, adjustmentRect, i, selectionIndex):
child = self._filing[i]
a = self._filing._index_to_angle(i, True)
sliceX = averageRadius * math.cos(middleAngle)
sliceY = - averageRadius * math.sin(middleAngle)
- piePos = self._canvas.rect().center()
+ piePos = adjustmentRect.center()
pieX = piePos.x()
pieY = piePos.y()
self._paint_label(
painter.drawText(leftX, topY, text)
def _paint_center_background(self, painter, adjustmentRect, selectionIndex):
- dark = self.palette.mid().color()
- light = self.palette.light().color()
- if selectionIndex == PieFiling.SELECTION_CENTER and self._filing.center().isEnabled():
- background = self.palette.highlight().color()
- else:
- background = self.palette.window().color()
-
- innerRadius = self._cachedInnerRadius
- adjustmentCenterPos = adjustmentRect.center()
- innerRect = QtCore.QRect(
- adjustmentCenterPos.x() - innerRadius,
- adjustmentCenterPos.y() - innerRadius,
- innerRadius * 2 + 1,
- innerRadius * 2 + 1,
- )
+ if self._backgroundState == self.BACKGROUND_NOFILL:
+ return
+ if len(self._filing) == 0:
+ if self._backgroundState == self.BACKGROUND_NOFILL:
+ painter.setBrush(QtGui.QBrush(QtCore.Qt.transparent))
+ else:
+ if selectionIndex == PieFiling.SELECTION_CENTER and self._filing.center().isEnabled():
+ painter.setBrush(self.palette.highlight())
+ else:
+ painter.setBrush(self.palette.window())
+ painter.setPen(self.palette.mid().color())
- painter.setPen(QtCore.Qt.NoPen)
- painter.setBrush(background)
- painter.drawPie(innerRect, 0, 360 * 16)
+ painter.drawRect(adjustmentRect)
+ else:
+ dark = self.palette.mid().color()
+ light = self.palette.light().color()
+ if self._backgroundState == self.BACKGROUND_NOFILL:
+ background = QtGui.QBrush(QtCore.Qt.transparent)
+ else:
+ if selectionIndex == PieFiling.SELECTION_CENTER and self._filing.center().isEnabled():
+ background = self.palette.highlight().color()
+ else:
+ background = self.palette.window().color()
+
+ innerRadius = self._cachedInnerRadius
+ adjustmentCenterPos = adjustmentRect.center()
+ innerRect = QtCore.QRect(
+ adjustmentCenterPos.x() - innerRadius,
+ adjustmentCenterPos.y() - innerRadius,
+ innerRadius * 2 + 1,
+ innerRadius * 2 + 1,
+ )
- painter.setPen(QtGui.QPen(dark, 1))
- painter.setBrush(QtCore.Qt.NoBrush)
- painter.drawEllipse(innerRect)
+ painter.setPen(QtCore.Qt.NoPen)
+ painter.setBrush(background)
+ painter.drawPie(innerRect, 0, 360 * 16)
- if self.DEFAULT_SHAPE == self.SHAPE_SQUARE:
- pass
- elif self.DEFAULT_SHAPE == self.SHAPE_CIRCLE:
- painter.setPen(QtGui.QPen(dark, 1))
- painter.setBrush(QtCore.Qt.NoBrush)
- painter.drawEllipse(adjustmentRect)
- else:
- raise NotImplementedError(self.DEFAULT_SHAPE)
+ if self.DEFAULT_SHAPE == self.SHAPE_SQUARE:
+ pass
+ elif self.DEFAULT_SHAPE == self.SHAPE_CIRCLE:
+ painter.setPen(QtGui.QPen(dark, 1))
+ painter.setBrush(QtCore.Qt.NoBrush)
+ painter.drawEllipse(adjustmentRect)
+ else:
+ raise NotImplementedError(self.DEFAULT_SHAPE)
- def _paint_center_foreground(self, painter, selectionIndex):
- centerPos = self._canvas.rect().center()
+ def _paint_center_foreground(self, painter, adjustmentRect, selectionIndex):
+ centerPos = adjustmentRect.center()
pieX = centerPos.x()
pieY = centerPos.y()
@misc_utils.log_exception(_moduleLogger)
def paintEvent(self, paintEvent):
canvas = self._artist.paint(self._selectionIndex)
+ offset = (self.size() - canvas.size()) / 2
screen = QtGui.QPainter(self)
- screen.drawPixmap(QtCore.QPoint(0, 0), canvas)
+ screen.drawPixmap(QtCore.QPoint(offset.width(), offset.height()), canvas)
QtGui.QWidget.paintEvent(self, paintEvent)
BUTTON_RADIUS = 24
DELAY = 250
- def __init__(self, buttonSlice, parent = None):
+ def __init__(self, buttonSlice, parent = None, buttonSlices = None):
# @bug Artifacts on Maemo 5 due to window 3D effects, find way to disable them for just these?
# @bug The pie's are being pushed back on screen on Maemo, leading to coordinate issues
QtGui.QWidget.__init__(self, parent)
self._buttonFiling = PieFiling()
self._buttonFiling.set_center(buttonSlice)
+ if buttonSlices is not None:
+ for slice in buttonSlices:
+ self._buttonFiling.insertItem(slice)
self._buttonFiling.setOuterRadius(self.BUTTON_RADIUS)
- self._buttonArtist = PieArtist(self._buttonFiling)
+ self._buttonArtist = PieArtist(self._buttonFiling, PieArtist.BACKGROUND_NOFILL)
self._poppedUp = False
+ self._pressed = False
self._delayPopupTimer = QtCore.QTimer()
self._delayPopupTimer.setInterval(self.DELAY)
self._mousePosition = None
self.setFocusPolicy(QtCore.Qt.StrongFocus)
+ self.setSizePolicy(
+ QtGui.QSizePolicy(
+ QtGui.QSizePolicy.MinimumExpanding,
+ QtGui.QSizePolicy.MinimumExpanding,
+ )
+ )
def insertItem(self, item, index = -1):
self._filing.insertItem(item, index)
def setButtonRadius(self, radius):
self._buttonFiling.setOuterRadius(radius)
+ self._buttonFiling.setInnerRadius(radius / 2)
self._buttonArtist.show(self.palette())
def minimumSizeHint(self):
self.highlighted.emit(self._selectionIndex)
self._display.selectAt(self._selectionIndex)
+ self._pressed = True
+ self.update()
self._popupLocation = mouseEvent.globalPos()
self._delayPopupTimer.start()
@misc_utils.log_exception(_moduleLogger)
def _on_delayed_popup(self):
- assert self._popupLocation is not None
+ assert self._popupLocation is not None, "Widget location abuse"
self._popup_child(self._popupLocation)
@misc_utils.log_exception(_moduleLogger)
self._mousePosition = None
self._activate_at(self._selectionIndex)
+ self._pressed = False
+ self.update()
self._hide_child()
@misc_utils.log_exception(_moduleLogger)
def paintEvent(self, paintEvent):
self.setButtonRadius(min(self.rect().width(), self.rect().height()) / 2 - 1)
if self._poppedUp:
- canvas = self._buttonArtist.paint(PieFiling.SELECTION_CENTER)
+ selectionIndex = PieFiling.SELECTION_CENTER
else:
- canvas = self._buttonArtist.paint(PieFiling.SELECTION_NONE)
+ selectionIndex = PieFiling.SELECTION_NONE
- screen = QtGui.QPainter(self)
- screen.drawPixmap(QtCore.QPoint(0, 0), canvas)
+ screen = QtGui.QStylePainter(self)
+ screen.setRenderHint(QtGui.QPainter.Antialiasing, True)
+ option = QtGui.QStyleOptionButton()
+ option.initFrom(self)
+ option.state = QtGui.QStyle.State_Sunken if self._pressed else QtGui.QStyle.State_Raised
+
+ screen.drawControl(QtGui.QStyle.CE_PushButton, option)
+ self._buttonArtist.paintPainter(selectionIndex, screen)
QtGui.QWidget.paintEvent(self, paintEvent)
import warnings
from PyQt4 import QtGui
-from PyQt4 import QtCore
import qtpie
class PieKeyboard(object):
- SLICE_CENTER = qtpie.EIGHT_SLICE_PIE.SLICE_CENTER
- SLICE_NORTH = qtpie.EIGHT_SLICE_PIE.SLICE_NORTH
- SLICE_NORTH_WEST = qtpie.EIGHT_SLICE_PIE.SLICE_NORTH_WEST
- SLICE_WEST = qtpie.EIGHT_SLICE_PIE.SLICE_WEST
- SLICE_SOUTH_WEST = qtpie.EIGHT_SLICE_PIE.SLICE_SOUTH_WEST
- SLICE_SOUTH = qtpie.EIGHT_SLICE_PIE.SLICE_SOUTH
- SLICE_SOUTH_EAST = qtpie.EIGHT_SLICE_PIE.SLICE_SOUTH_EAST
- SLICE_EAST = qtpie.EIGHT_SLICE_PIE.SLICE_EAST
- SLICE_NORTH_EAST = qtpie.EIGHT_SLICE_PIE.SLICE_NORTH_EAST
-
- MAX_ANGULAR_SLICES = qtpie.EIGHT_SLICE_PIE.MAX_ANGULAR_SLICES
-
- SLICE_DIRECTIONS = qtpie.EIGHT_SLICE_PIE.SLICE_DIRECTIONS
-
- SLICE_DIRECTION_NAMES = qtpie.EIGHT_SLICE_PIE.SLICE_DIRECTION_NAMES
+ SLICE_CENTER = -1
+ SLICE_NORTH = 0
+ SLICE_NORTH_WEST = 1
+ SLICE_WEST = 2
+ SLICE_SOUTH_WEST = 3
+ SLICE_SOUTH = 4
+ SLICE_SOUTH_EAST = 5
+ SLICE_EAST = 6
+ SLICE_NORTH_EAST = 7
+
+ MAX_ANGULAR_SLICES = 8
+
+ SLICE_DIRECTIONS = [
+ SLICE_CENTER,
+ SLICE_NORTH,
+ SLICE_NORTH_WEST,
+ SLICE_WEST,
+ SLICE_SOUTH_WEST,
+ SLICE_SOUTH,
+ SLICE_SOUTH_EAST,
+ SLICE_EAST,
+ SLICE_NORTH_EAST,
+ ]
+
+ SLICE_DIRECTION_NAMES = [
+ "CENTER",
+ "NORTH",
+ "NORTH_WEST",
+ "WEST",
+ "SOUTH_WEST",
+ "SOUTH",
+ "SOUTH_EAST",
+ "EAST",
+ "NORTH_EAST",
+ ]
def __init__(self):
self._layout = QtGui.QGridLayout()
def add_pie(self, row, column, pieButton):
assert len(pieButton) == 8
- self._layout.addWidget(pieButton, row, column, QtCore.Qt.AlignCenter)
+ self._layout.addWidget(pieButton, row, column)
self.__cells[(row, column)] = pieButton
def get_pie(self, row, column):
--- /dev/null
+import sys
+import contextlib
+import datetime
+import logging
+
+from PyQt4 import QtCore
+from PyQt4 import QtGui
+
+import misc
+
+
+_moduleLogger = logging.getLogger(__name__)
+
+
+@contextlib.contextmanager
+def notify_error(log):
+ try:
+ yield
+ except:
+ log.push_exception()
+
+
+@contextlib.contextmanager
+def notify_busy(log, message):
+ log.push_busy(message)
+ try:
+ yield
+ finally:
+ log.pop(message)
+
+
+class ErrorMessage(object):
+
+ LEVEL_ERROR = 0
+ LEVEL_BUSY = 1
+ LEVEL_INFO = 2
+
+ def __init__(self, message, level):
+ self._message = message
+ self._level = level
+ self._time = datetime.datetime.now()
+
+ @property
+ def level(self):
+ return self._level
+
+ @property
+ def message(self):
+ return self._message
+
+ def __repr__(self):
+ return "%s.%s(%r, %r)" % (__name__, self.__class__.__name__, self._message, self._level)
+
+
+class QErrorLog(QtCore.QObject):
+
+ messagePushed = QtCore.pyqtSignal()
+ messagePopped = QtCore.pyqtSignal()
+
+ def __init__(self):
+ QtCore.QObject.__init__(self)
+ self._messages = []
+
+ def push_busy(self, message):
+ _moduleLogger.info("Entering state: %s" % message)
+ self._push_message(message, ErrorMessage.LEVEL_BUSY)
+
+ def push_message(self, message):
+ 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_error(userMessage)
+
+ def pop(self, message = None):
+ if message is None:
+ del self._messages[0]
+ else:
+ _moduleLogger.info("Exiting state: %s" % message)
+ 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))
+ # Sort is defined as stable, so this should be fine
+ self._messages.sort(key=lambda x: x.level)
+ self.messagePushed.emit()
+
+ def __len__(self):
+ return len(self._messages)
+
+
+class ErrorDisplay(object):
+
+ _SENTINEL_ICON = QtGui.QIcon()
+
+ def __init__(self, errorLog):
+ self._errorLog = errorLog
+ self._errorLog.messagePushed.connect(self._on_message_pushed)
+ self._errorLog.messagePopped.connect(self._on_message_popped)
+
+ self._icons = {
+ ErrorMessage.LEVEL_BUSY:
+ get_theme_icon(
+ #("process-working", "view-refresh", "general_refresh", "gtk-refresh")
+ ("view-refresh", "general_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.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
+
+ self._message = QtGui.QLabel()
+ self._message.setText("Boo")
+ self._message.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter)
+ self._message.setWordWrap(True)
+
+ closeIcon = get_theme_icon(("window-close", "general_close", "gtk-close"), self._SENTINEL_ICON)
+ if closeIcon is not self._SENTINEL_ICON:
+ self._closeLabel = QtGui.QPushButton(closeIcon, "")
+ else:
+ self._closeLabel = QtGui.QPushButton("X")
+ self._closeLabel.clicked.connect(self._on_close)
+
+ self._controlLayout = QtGui.QHBoxLayout()
+ 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._widget = QtGui.QWidget()
+ self._widget.setLayout(self._controlLayout)
+ self._widget.hide()
+
+ @property
+ def toplevel(self):
+ return self._widget
+
+ def _show_error(self):
+ error = self._errorLog.peek_message()
+ self._message.setText(error.message)
+ self._severityLabel.setPixmap(self._icons[error.level])
+ self._widget.show()
+
+ @QtCore.pyqtSlot()
+ @QtCore.pyqtSlot(bool)
+ @misc.log_exception(_moduleLogger)
+ def _on_close(self, checked = False):
+ self._errorLog.pop()
+
+ @QtCore.pyqtSlot()
+ @misc.log_exception(_moduleLogger)
+ def _on_message_pushed(self):
+ self._show_error()
+
+ @QtCore.pyqtSlot()
+ @misc.log_exception(_moduleLogger)
+ def _on_message_popped(self):
+ if len(self._errorLog) == 0:
+ self._message.setText("")
+ self._widget.hide()
+ else:
+ self._show_error()
+
+
+class QHtmlDelegate(QtGui.QStyledItemDelegate):
+
+ UNDEFINED_SIZE = -1
+
+ def __init__(self, *args, **kwd):
+ QtGui.QStyledItemDelegate.__init__(*((self, ) + args), **kwd)
+ self._width = self.UNDEFINED_SIZE
+
+ def paint(self, painter, option, index):
+ newOption = QtGui.QStyleOptionViewItemV4(option)
+ self.initStyleOption(newOption, index)
+ if newOption.widget is not None:
+ style = newOption.widget.style()
+ else:
+ style = QtGui.QApplication.style()
+
+ doc = QtGui.QTextDocument()
+ doc.setHtml(newOption.text)
+ doc.setTextWidth(newOption.rect.width())
+
+ newOption.text = ""
+ style.drawControl(QtGui.QStyle.CE_ItemViewItem, newOption, painter)
+
+ ctx = QtGui.QAbstractTextDocumentLayout.PaintContext()
+ if newOption.state & QtGui.QStyle.State_Selected:
+ ctx.palette.setColor(
+ QtGui.QPalette.Text,
+ newOption.palette.color(
+ QtGui.QPalette.Active,
+ QtGui.QPalette.HighlightedText
+ )
+ )
+ else:
+ ctx.palette.setColor(
+ QtGui.QPalette.Text,
+ newOption.palette.color(
+ QtGui.QPalette.Active,
+ QtGui.QPalette.Text
+ )
+ )
+
+ textRect = style.subElementRect(QtGui.QStyle.SE_ItemViewItemText, newOption)
+ painter.save()
+ painter.translate(textRect.topLeft())
+ painter.setClipRect(textRect.translated(-textRect.topLeft()))
+ doc.documentLayout().draw(painter, ctx)
+ painter.restore()
+
+ def setWidth(self, width):
+ # @bug we need to be emitting sizeHintChanged but it requires an index
+ self._width = width
+
+ def sizeHint(self, option, index):
+ newOption = QtGui.QStyleOptionViewItemV4(option)
+ self.initStyleOption(newOption, index)
+
+ doc = QtGui.QTextDocument()
+ doc.setHtml(newOption.text)
+ if self._width != self.UNDEFINED_SIZE:
+ width = self._width
+ else:
+ width = newOption.rect.width()
+ doc.setTextWidth(width)
+ size = QtCore.QSize(doc.idealWidth(), doc.size().height())
+ return size
+
+
+def _null_set_stackable(window, isStackable):
+ pass
+
+
+def _maemo_set_stackable(window, isStackable):
+ window.setAttribute(QtCore.Qt.WA_Maemo5StackedWindow, isStackable)
+
+
+try:
+ QtCore.Qt.WA_Maemo5StackedWindow
+ set_stackable = _maemo_set_stackable
+except AttributeError:
+ set_stackable = _null_set_stackable
+
+
+def _null_set_autorient(window, isStackable):
+ pass
+
+
+def _maemo_set_autorient(window, isStackable):
+ window.setAttribute(QtCore.Qt.WA_Maemo5AutoOrientation, isStackable)
+
+
+try:
+ QtCore.Qt.WA_Maemo5AutoOrientation
+ set_autorient = _maemo_set_autorient
+except AttributeError:
+ set_autorient = _null_set_autorient
+
+
+def screen_orientation():
+ geom = QtGui.QApplication.desktop().screenGeometry()
+ if geom.width() <= geom.height():
+ return QtCore.Qt.Vertical
+ else:
+ return QtCore.Qt.Horizontal
+
+
+def _null_set_window_orientation(window, orientation):
+ pass
+
+
+def _maemo_set_window_orientation(window, orientation):
+ if orientation == QtCore.Qt.Vertical:
+ oldHint = QtCore.Qt.WA_Maemo5LandscapeOrientation
+ newHint = QtCore.Qt.WA_Maemo5PortraitOrientation
+ elif orientation == QtCore.Qt.Horizontal:
+ oldHint = QtCore.Qt.WA_Maemo5PortraitOrientation
+ newHint = QtCore.Qt.WA_Maemo5LandscapeOrientation
+ window.setAttribute(oldHint, False)
+ window.setAttribute(newHint, True)
+
+
+try:
+ QtCore.Qt.WA_Maemo5LandscapeOrientation
+ QtCore.Qt.WA_Maemo5PortraitOrientation
+ set_window_orientation = _maemo_set_window_orientation
+except AttributeError:
+ set_window_orientation = _null_set_window_orientation
+
+
+def _null_show_progress_indicator(window, isStackable):
+ pass
+
+
+def _maemo_show_progress_indicator(window, isStackable):
+ window.setAttribute(QtCore.Qt.WA_Maemo5ShowProgressIndicator, isStackable)
+
+
+try:
+ QtCore.Qt.WA_Maemo5ShowProgressIndicator
+ show_progress_indicator = _maemo_show_progress_indicator
+except AttributeError:
+ show_progress_indicator = _null_show_progress_indicator
+
+
+def _null_mark_numbers_preferred(widget):
+ pass
+
+
+def _newqt_mark_numbers_preferred(widget):
+ widget.setInputMethodHints(QtCore.Qt.ImhPreferNumbers)
+
+
+try:
+ QtCore.Qt.ImhPreferNumbers
+ mark_numbers_preferred = _newqt_mark_numbers_preferred
+except AttributeError:
+ mark_numbers_preferred = _null_mark_numbers_preferred
+
+
+def _null_get_theme_icon(iconNames, fallback = None):
+ icon = fallback if fallback is not None else QtGui.QIcon()
+ return icon
+
+
+def _newqt_get_theme_icon(iconNames, fallback = None):
+ for iconName in iconNames:
+ if QtGui.QIcon.hasThemeIcon(iconName):
+ icon = QtGui.QIcon.fromTheme(iconName)
+ break
+ else:
+ icon = fallback if fallback is not None else QtGui.QIcon()
+ return icon
+
+
+try:
+ QtGui.QIcon.fromTheme
+ get_theme_icon = _newqt_get_theme_icon
+except AttributeError:
+ get_theme_icon = _null_get_theme_icon
+
--- /dev/null
+#!/usr/bin/env python
+
+from __future__ import with_statement
+from __future__ import division
+
+import logging
+
+from PyQt4 import QtGui
+from PyQt4 import QtCore
+
+from util import qui_utils
+from util import misc as misc_utils
+
+
+_moduleLogger = logging.getLogger(__name__)
+
+
+class ApplicationWrapper(object):
+
+ def __init__(self, qapp, constants):
+ self._constants = constants
+ self._qapp = qapp
+ self._clipboard = QtGui.QApplication.clipboard()
+
+ self._errorLog = qui_utils.QErrorLog()
+ self._mainWindow = None
+
+ self._fullscreenAction = QtGui.QAction(None)
+ self._fullscreenAction.setText("Fullscreen")
+ self._fullscreenAction.setCheckable(True)
+ 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"))
+ self._logAction.triggered.connect(self._on_log)
+
+ self._quitAction = QtGui.QAction(None)
+ self._quitAction.setText("Quit")
+ self._quitAction.setShortcut(QtGui.QKeySequence("CTRL+q"))
+ self._quitAction.triggered.connect(self._on_quit)
+
+ self._aboutAction = QtGui.QAction(None)
+ self._aboutAction.setText("About")
+ self._aboutAction.triggered.connect(self._on_about)
+
+ self._qapp.lastWindowClosed.connect(self._on_app_quit)
+ self._mainWindow = self._new_main_window()
+ self._mainWindow.window.destroyed.connect(self._on_child_close)
+
+ self.load_settings()
+
+ self._mainWindow.show()
+ self._idleDelay = QtCore.QTimer()
+ self._idleDelay.setSingleShot(True)
+ self._idleDelay.setInterval(0)
+ self._idleDelay.timeout.connect(lambda: self._mainWindow.start())
+ self._idleDelay.start()
+
+ def load_settings(self):
+ raise NotImplementedError("Booh")
+
+ def save_settings(self):
+ raise NotImplementedError("Booh")
+
+ def _new_main_window(self):
+ raise NotImplementedError("Booh")
+
+ @property
+ def qapp(self):
+ return self._qapp
+
+ @property
+ def constants(self):
+ return self._constants
+
+ @property
+ def errorLog(self):
+ return self._errorLog
+
+ @property
+ def fullscreenAction(self):
+ return self._fullscreenAction
+
+ @property
+ def orientationAction(self):
+ return self._orientationAction
+
+ @property
+ def logAction(self):
+ return self._logAction
+
+ @property
+ def aboutAction(self):
+ return self._aboutAction
+
+ @property
+ def quitAction(self):
+ return self._quitAction
+
+ def _close_windows(self):
+ if self._mainWindow is not None:
+ self.save_settings()
+ self._mainWindow.window.destroyed.disconnect(self._on_child_close)
+ self._mainWindow.close()
+ self._mainWindow = None
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_app_quit(self, checked = False):
+ if self._mainWindow is not None:
+ self.save_settings()
+ self._mainWindow.destroy()
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_child_close(self, obj = None):
+ if self._mainWindow is not None:
+ self.save_settings()
+ self._mainWindow = None
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_toggle_fullscreen(self, checked = False):
+ with qui_utils.notify_error(self._errorLog):
+ self._mainWindow.set_fullscreen(checked)
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_toggle_orientation(self, checked = False):
+ with qui_utils.notify_error(self._errorLog):
+ self._mainWindow.set_orientation(checked)
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_about(self, checked = True):
+ raise NotImplementedError("Booh")
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_log(self, checked = False):
+ with qui_utils.notify_error(self._errorLog):
+ with open(self._constants._user_logpath_, "r") as f:
+ logLines = f.xreadlines()
+ log = "".join(logLines)
+ self._clipboard.setText(log)
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_quit(self, checked = False):
+ with qui_utils.notify_error(self._errorLog):
+ self._close_windows()
+
+
+class WindowWrapper(object):
+
+ def __init__(self, parent, app):
+ self._app = app
+
+ self._errorDisplay = qui_utils.ErrorDisplay(self._app.errorLog)
+
+ self._layout = QtGui.QBoxLayout(QtGui.QBoxLayout.LeftToRight)
+ self._layout.setContentsMargins(0, 0, 0, 0)
+
+ self._superLayout = QtGui.QVBoxLayout()
+ self._superLayout.addWidget(self._errorDisplay.toplevel)
+ self._superLayout.setContentsMargins(0, 0, 0, 0)
+ self._superLayout.addLayout(self._layout)
+
+ centralWidget = QtGui.QWidget()
+ centralWidget.setLayout(self._superLayout)
+ centralWidget.setContentsMargins(0, 0, 0, 0)
+
+ self._window = QtGui.QMainWindow(parent)
+ self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
+ qui_utils.set_stackable(self._window, True)
+ self._window.setCentralWidget(centralWidget)
+
+ self._closeWindowAction = QtGui.QAction(None)
+ self._closeWindowAction.setText("Close")
+ self._closeWindowAction.setShortcut(QtGui.QKeySequence("CTRL+w"))
+ self._closeWindowAction.triggered.connect(self._on_close_window)
+
+ self._window.addAction(self._closeWindowAction)
+ self._window.addAction(self._app.quitAction)
+ self._window.addAction(self._app.fullscreenAction)
+ self._window.addAction(self._app.orientationAction)
+ self._window.addAction(self._app.logAction)
+
+ @property
+ def window(self):
+ return self._window
+
+ def walk_children(self):
+ return ()
+
+ def start(self):
+ pass
+
+ def close(self):
+ for child in self.walk_children():
+ child.window.destroyed.disconnect(self._on_child_close)
+ child.close()
+ self._window.close()
+
+ def destroy(self):
+ pass
+
+ def show(self):
+ self.set_fullscreen(self._app.fullscreenAction.isChecked())
+ self._window.show()
+ for child in self.walk_children():
+ child.show()
+
+ def hide(self):
+ for child in self.walk_children():
+ child.hide()
+ self._window.hide()
+
+ def set_fullscreen(self, isFullscreen):
+ if isFullscreen:
+ self._window.showFullScreen()
+ else:
+ self._window.showNormal()
+ for child in self.walk_children():
+ child.set_fullscreen(isFullscreen)
+
+ def set_orientation(self, isPortrait):
+ if isPortrait:
+ qui_utils.set_window_orientation(self.window, QtCore.Qt.Vertical)
+ else:
+ qui_utils.set_window_orientation(self.window, QtCore.Qt.Horizontal)
+ for child in self.walk_children():
+ child.set_orientation(isPortrait)
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_child_close(self):
+ raise NotImplementedError("Booh")
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_close_window(self, checked = True):
+ with qui_utils.notify_error(self._errorLog):
+ self.close()
+
+
+class AutoFreezeWindowFeature(object):
+
+ def __init__(self, app, window):
+ self._app = app
+ self._window = window
+ self._app.qapp.focusChanged.connect(self._on_focus_changed)
+ if self._app.qapp.focusWidget() is not None:
+ self._window.setUpdatesEnabled(True)
+ else:
+ self._window.setUpdatesEnabled(False)
+
+ def close(self):
+ self._app.qapp.focusChanged.disconnect(self._on_focus_changed)
+ self._window.setUpdatesEnabled(True)
+
+ @misc_utils.log_exception(_moduleLogger)
+ def _on_focus_changed(self, oldWindow, newWindow):
+ with qui_utils.notify_error(self._app.errorLog):
+ if oldWindow is None and newWindow is not None:
+ self._window.setUpdatesEnabled(True)
+ elif oldWindow is not None and newWindow is None:
+ self._window.setUpdatesEnabled(False)
self._report_error("closed too early")
def _report_success(self):
- assert not self._didReport
+ assert not self._didReport, "Double reporting a missed call"
self._didReport = True
self._onTimeout.cancel()
self.__on_success(self)
def _report_error(self, reason):
- assert not self._didReport
+ assert not self._didReport, "Double reporting a missed call"
self._didReport = True
self._onTimeout.cancel()
self.__on_error(self, reason)
from PyQt4 import QtCore
import constants
-import maeqt
+from util import qui_utils
from util import misc as misc_utils
import unit_data
self._window = QtGui.QMainWindow(parent)
self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
- maeqt.set_autorient(self._window, True)
- maeqt.set_stackable(self._window, True)
+ qui_utils.set_stackable(self._window, True)
self._window.setWindowTitle("%s - Favorites" % constants.__pretty_app_name__)
self._window.setWindowIcon(QtGui.QIcon(self._app.appIconPath))
self._window.setCentralWidget(centralWidget)
self._window = QtGui.QMainWindow(parent)
self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
- maeqt.set_autorient(self._window, True)
- maeqt.set_stackable(self._window, True)
+ qui_utils.set_stackable(self._window, True)
self._window.setWindowTitle("%s - Quick Jump" % constants.__pretty_app_name__)
self._window.setWindowIcon(QtGui.QIcon(self._app.appIconPath))
self._window.setCentralWidget(centralWidget)
self._window = QtGui.QMainWindow(parent)
self._window.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
- maeqt.set_autorient(self._window, True)
- maeqt.set_stackable(self._window, True)
+ qui_utils.set_stackable(self._window, True)
self._window.setWindowTitle("%s - Recent" % constants.__pretty_app_name__)
self._window.setWindowIcon(QtGui.QIcon(self._app.appIconPath))
self._window.setCentralWidget(centralWidget)