Source code for ccpn.ui.gui.widgets.Entry

"""Module Documentation here

"""
#=========================================================================================
# Licence, Reference and Credits
#=========================================================================================
__copyright__ = "Copyright (C) CCPN project (http://www.ccpn.ac.uk) 2014 - 2021"
__credits__ = ("Ed Brooksbank, Joanna Fox, Victoria A Higman, Luca Mureddu, Eliza Płoskoń",
               "Timothy J Ragan, Brian O Smith, Gary S Thompson & Geerten W Vuister")
__licence__ = ("CCPN licence. See http://www.ccpn.ac.uk/v3-software/downloads/license")
__reference__ = ("Skinner, S.P., Fogh, R.H., Boucher, W., Ragan, T.J., Mureddu, L.G., & Vuister, G.W.",
                 "CcpNmr AnalysisAssign: a flexible platform for integrated NMR analysis",
                 "J.Biomol.Nmr (2016), 66, 111-124, http://doi.org/10.1007/s10858-016-0060-y")
#=========================================================================================
# Last code modification
#=========================================================================================
__modifiedBy__ = "$modifiedBy: Ed Brooksbank $"
__dateModified__ = "$dateModified: 2021-07-30 20:44:26 +0100 (Fri, July 30, 2021) $"
__version__ = "$Revision: 3.0.4 $"
#=========================================================================================
# Created
#=========================================================================================
__author__ = "$Author: CCPN $"
__date__ = "$Date: 2017-04-07 10:28:41 +0000 (Fri, April 07, 2017) $"
#=========================================================================================
# Start of code
#=========================================================================================

from PyQt5 import QtGui, QtWidgets
from ccpn.ui.gui.widgets.Base import Base
from ccpn.ui.gui.widgets.Frame import Frame
from ccpn.ui.gui.widgets.Label import Label
from ccpn.ui.gui.widgets.Font import setWidgetFont, getFontHeight

# Width?
# Allow setting of max length based on data model?

import re


SPLIT_REG_EXP = re.compile(',?\s*')
SEPARATOR = ', '
MAXINT = 2 ** 31 - 1
INFINITY = float('Inf')


[docs]class Entry(QtWidgets.QLineEdit, Base): def __init__(self, parent, text='', callback=None, maxLength=1000, listener=None, stripEndWhitespace=True, editable=True, backgroundText='<default>', **kwds): super().__init__(parent) Base._init(self, **kwds) self.setText(self.convertInput(text)) self.setMaxLength(maxLength) self._isAltered = False self._stripEndWhitespace = stripEndWhitespace self.callback = callback self.textChanged.connect(self._changed) self.returnPressed.connect(self._callback) self.editingFinished.connect(self._callback) if listener: if isinstance(listener, (set, list, tuple)): for signal in listener: signal.connect(self.set) else: listener.connect(self.set) self.setStyleSheet('padding: 3px 3px 3px 3px;') self.backgroundText = backgroundText if self.backgroundText: self.setPlaceholderText(str(self.backgroundText)) if not editable: self.setReadOnly(True) self.setEnabled(False) def _callback(self): if self.callback and self._isAltered: self.callback(self.get()) self._isAltered = False def _changed(self): self._isAltered = True
[docs] def convertText(self, text): # Overwritten in subclasses to make float, int etc if self._stripEndWhitespace: text = text.strip() return text or None
[docs] def convertInput(self, value): # Overwritten in subclasses to convert float, int return value or ''
[docs] def get(self): return self.convertText(self.text())
#gwv 20181101; some consistency getText = get
[docs] def set(self, value, doCallback=True): self.setText(self.convertInput(value)) if doCallback: self._callback()
def _split(self, text: str): return [x.strip() for x in text.split(',')]
[docs]class IntEntry(Entry): def __init__(self, parent, text=0, callback=None, minValue=-MAXINT, maxValue=MAXINT, **kwds): Entry.__init__(self, parent, text, callback, **kwds) valid = QtGui.QIntValidator(minValue, maxValue, self) self.setValidator(valid)
[docs] def convertText(self, text): if not text: return None else: return int(text)
[docs] def convertInput(self, value): if value is None: return '' else: return str(value)
[docs] def setRange(self, minValue=-MAXINT, maxValue=MAXINT): valid = QtGui.QIntValidator(minValue, maxValue, self) self.setValidator(valid)
[docs]class FloatEntry(Entry): decimals = 4 def __init__(self, parent, text=0.0, callback=None, minValue=-INFINITY, maxValue=INFINITY, decimals=4, **kwds): Entry.__init__(self, parent, text, callback, **kwds) self.decimals = decimals self.setText(self.convertInput(text)) valid = QtGui.QDoubleValidator(minValue, maxValue, decimals, self) self.setValidator(valid)
[docs] def convertText(self, text): if not text: return None else: return float(text)
[docs] def convertInput(self, value): if value is None: text = '' elif value == 0: text = '0.0' elif abs(value) > 999999 or abs(value) < 0.00001: textFormat = '%%.%de' % (self.decimals) text = textFormat % value else: textFormat = '%%.%df' % (self.decimals) text = textFormat % value return text
[docs] def setRange(self, minValue=-MAXINT, maxValue=MAXINT): valid = QtGui.QIntValidator(minValue, maxValue, self) self.setValidator(valid)
[docs]class RegExpEntry(Entry): def __init__(self, parent, text='', callback=None, **kwds): Entry.__init__(self, parent, text, callback, **kwds) self.setValidator(QtGui.QRegExpValidator)
[docs]class ArrayEntry(Entry): def __init__(self, parent, text='', callback=None, **kwds): Entry.__init__(self, parent, text, callback, **kwds)
[docs] def convertText(self, text): # return re.split(SPLIT_REG_EXP, text) or [] return self._split(text) or []
[docs] def convertInput(self, array): return SEPARATOR.join(array)
[docs]class IntArrayEntry(IntEntry): def __init__(self, parent, text='', callback=None, **kwds): IntEntry.__init__(self, parent, text, callback, **kwds)
[docs] def convertText(self, text): # array = re.split(SPLIT_REG_EXP, text) or [] array = self._split(text) or [] return [IntEntry.convertText(self, x) for x in array]
[docs] def convertInput(self, values): texts = [IntEntry.convertInput(self, x) for x in values] return SEPARATOR.join(texts)
[docs]class FloatArrayEntry(FloatEntry): def __init__(self, parent, text='', callback=None, **kwds): FloatEntry.__init__(self, parent, text, callback, **kwds)
[docs] def convertText(self, text): # array = re.split(SPLIT_REG_EXP, text) or [] array = self._split(text) or [] return [FloatEntry.convertText(self, x) for x in array]
[docs] def convertInput(self, values): texts = [FloatEntry.convertInput(self, x) for x in values] return SEPARATOR.join(texts)
[docs]class LabelledEntry(Frame): def __init__(self, parent, labelText, entryText='', callback=None, maxLength=32, tipText=None, **kwds): Frame.__init__(self, parent, tipText=tipText, **kwds) self.label = Label(self, labelText, tipText=tipText, grid=(0, 0)) self.entry = Entry(self, entryText, callback, maxLength, tipText=tipText, grid=(0, 1))
[docs] def getLabel(self): return self.label.get()
[docs] def setLabel(self, text): self.label.set(text)
[docs] def getEntry(self): return self.entry.get()
[docs] def setEntry(self, text): self.entry.set(text)
[docs]class LabelledIntEntry(LabelledEntry): def __init__(self, parent, labelText, entryText='', callback=None, minValue=-MAXINT, maxValue=MAXINT, tipText=None, **kwds): Frame.__init__(self, parent, tipText=tipText, **kwds) self.label = Label(self, labelText, tipText=tipText, grid=(0, 0)) self.entry = IntEntry(self, entryText, callback, minValue, maxValue, tipText=tipText, grid=(0, 1))
[docs]class LabelledFloatEntry(LabelledEntry): def __init__(self, parent, labelText, entryText='', callback=None, minValue=-MAXINT, maxValue=MAXINT, decimals=4, tipText=None, **kwds): Frame.__init__(self, parent, tipText=tipText, **kwds) self.label = Label(self, labelText, tipText=tipText, grid=(0, 0)) self.entry = FloatEntry(self, entryText, callback, minValue, maxValue, decimals, tipText=tipText, grid=(0, 1))
if __name__ == '__main__': # from memops.qtgui.Application import Application from ccpn.ui.gui.widgets.Application import Application app = Application('test', 'test1') window = QtWidgets.QWidget() frame = Frame(window, setLayout=True) def callback(value): print("Callback", value) Entry(frame, 'Start Text', callback, grid=(0, 0)) ArrayEntry(frame, ['A', 'C', 'D', 'C'], callback, grid=(1, 0)) IntEntry(frame, 123, callback, grid=(2, 0)) IntArrayEntry(frame, [4, 5, 6, 7], callback, grid=(3, 0)) FloatEntry(frame, 2.818, callback, grid=(4, 0)) e = FloatArrayEntry(frame, [1, 2, 4], callback, decimals=2, grid=(5, 0)) e.set([1e12, -0.7e-5, 9.75]) LabelledEntry(frame, 'Text:', 'Initial val', callback, setLayout=True, grid=(6, 0)) LabelledIntEntry(frame, 'Int:', 0, callback, setLayout=True, grid=(7, 0)) LabelledFloatEntry(frame, 'Float:', 0.7295, callback, decimals=8, setLayout=True, grid=(8, 0)) window.show() app.start()