#!/usr/bin/env python #**************************************************************************** # tmpcontrol.py, provides extended editors that signal focus loss # # Copyright (C) 2004, Douglas W. Bell # # This is free software; you can redistribute it and/or modify it under the # terms of the GNU General Public License, Version 2. This program is # distributed in the hope that it will be useful, but WITTHOUT ANY WARRANTY. #***************************************************************************** from qt import Qt, PYSIGNAL, SIGNAL, SLOT, QEvent, QFontMetrics, \ QLineEdit, QSpinBox, QString class TmpEdit(QLineEdit): """Gives temporary line editor, signals focus loss & return key""" def __init__(self, text, parent=None, name=None): QLineEdit.__init__(self, text, parent, name) self.active = 1 self.origText = text def focusOutEvent(self, event): """Signals to end editing if focus shifts""" QLineEdit.focusOutEvent(self, event) if self.active: self.active = 0 # one signal only self.emit(PYSIGNAL('editDone'), ()) def keyPressEvent(self, event): """Signals return key press""" if event.key() in (Qt.Key_Return, Qt.Key_Enter, Qt.Key_Escape): if self.active: if event.key() == Qt.Key_Escape: self.setText(self.origText) self.active = 0 # one signal only self.emit(PYSIGNAL('editDone'), ()) elif event.key() == Qt.Key_Up or event.key() == Qt.Key_Down: pass # avoid sending arrows to parent view else: QLineEdit.keyPressEvent(self, event) def mousePressEvent(self, event): """Ignores right-click""" if event.button() == Qt.LeftButton: QLineEdit.mousePressEvent(self, event) def event(self, event): """Avoid accel key or right-click crash""" if event.type() == QEvent.KeyRelease and event.key() == Qt.Key_Alt: return 1 if event.type() in (QEvent.MouseButtonPress, \ QEvent.MouseButtonRelease) and \ event.button() != Qt.LeftButton: return 1 return QLineEdit.event(self, event) class SpinBoxEx(QSpinBox): """Steps & wraps to factor, lead zeros, signals wrap, focus loss & enter""" def __init__(self, min, max, step=1, zeros=0, parent=None, name=None): QSpinBox.__init__(self, min, max, step, parent, name) self.active = 1 self.zeros = zeros self.origValue = None self.origWidth = QSpinBox.sizeHint(self).width() # self.connect(self.editor(), SIGNAL('textChanged(const QString &)'), \ # self.interpretText) def stepUp(self): """Override to step to even factors""" num = self.value() + self.lineStep() - self.value() % self.lineStep() if self.value() < 0 and self.value() % self.lineStep() != 0: num -= self.lineStep() if num > self.maxValue(): if self.wrapping(): num = self.minValue() if num % self.lineStep() != 0: # min is not step multiple num += self.lineStep() - num % self.lineStep() if minValue < 0: num -= self.lineStep() self.emit(PYSIGNAL('wrapped'), (1,)) else: num = self.maxValue() self.setValue(num) self.emit(PYSIGNAL('spinChange'), (1, num)) def stepDown(self): """Override to step to even factors""" num = self.value() - self.lineStep() if num % self.lineStep() != 0: num += self.lineStep() - self.value() % self.lineStep() if self.value() < 0: num -= self.lineStep() if num < self.minValue(): if self.wrapping(): num = self.maxValue() - self.maxValue() % self.lineStep() if self.maxValue() < 0 and \ self.maxValue() % self.lineStep() != 0: num -= self.lineStep() self.emit(PYSIGNAL('wrapped'), (0,)) else: num = self.minValue() self.setValue(num) self.emit(PYSIGNAL('spinChange'), (0, num)) def setValue(self, value): """Override to avoid bug with map not being called""" QSpinBox.setValue(self, value) self.updateDisplay() def updateValue(self): """Force an update without enter or focus change by calling a protected function""" self.interpretText() def mapValueToText(self, value): """Override to add leading zeros""" return QString(('%%0%dd' % self.zeros) % value) def sizeHint(self): """Return smaller size than default""" size = QSpinBox.sizeHint(self) if self.suffix().isEmpty(): size.setWidth(self.origWidth - QFontMetrics(self.font()).maxWidth()) return size def eventFilter(self, obj, event): """Signals to end editing if focus shifts, line edit is focus proxy""" QSpinBox.eventFilter(self, obj, event) # was and obj == self.editor(), didn't work if event.type() == QEvent.FocusOut and self.active: self.active = 0 # one signal only self.emit(PYSIGNAL('editDone'), ()) return 1 # stops event return 0 # continues event def keyPressEvent(self, event): """Signals return key press""" if event.key() in (Qt.Key_Return, Qt.Key_Enter): if self.active: self.active = 0 # one signal only self.emit(PYSIGNAL('editDone'), ()) elif event.key() == Qt.Key_Up: self.stepUp() # avoid sending arrows to parent view elif event.key() == Qt.Key_Down: self.stepDown() elif event.key() == Qt.Key_Escape: if self.active and self.origValue != None: self.active = 0 # one signal only self.setValue(self.origValue) self.emit(PYSIGNAL('editDone'), ()) else: QSpinBox.keyPressEvent(self, event) else: QSpinBox.keyPressEvent(self, event)