HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Binding a value to a control

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
controlvaluebinding

Problem

I'm currently writing some code in PyQt4 that takes a value and a control and binds the value to the control. Once the user saves the form it will unbind all the values and save it back to a custom object (in this case QgsFeature).

At the moment, I have the bind and unbind code which uses if/elif statements to work out the control type and then use the correct methods to bind the value, like so:

```
def bindValueToControl(self, control, value):
"""
Binds a control to the supplied value.
Raises BindingError() if control is not supported.

control - QWidget based control that takes the new value
value - A QVariant holding the value
"""
if isinstance(control, QCalendarWidget):
control.setSelectedDate(QDate.fromString(value.toString(), Qt.ISODate))

elif isinstance(control, QListWidget):
items = control.findItems(value.toString(), Qt.MatchExactly)
try:
control.setCurrentItem(items[0])
control.currentItemChanged.emit(None, items[0])
except IndexError:
pass

elif isinstance(control, QLineEdit) or isinstance(control, QTextEdit):
control.setText(value.toString())

elif isinstance(control, QCheckBox) or isinstance(control, QGroupBox):
control.setChecked(value.toBool())

elif isinstance(control, QPlainTextEdit):
control.setPlainText(value.toString())

elif isinstance(control, QComboBox):
# Add items stored in the database
query = QSqlQuery()
query.prepare("SELECT value FROM ComboBoxItems WHERE control = :contorl")
query.bindValue(":control", control.objectName())
query.exec_()
while query.next():
newvalue = query.value(0).toString()
if not newvalue.isEmpty():
control.addItem(newvalue)

itemindex = control.findTe

Solution

To expand a little further on part of sky py's answer, you could try something like the following

class BaseControlHandler:
    def __init__( self, control ):
        self.control = control
    def bind( self, value ): 
        raise SuitableException()
    def unbind( self ):
        raise SuitableException()

class LineEditHandler( BaseControlHandler ):
    def __init__( self, control ):
        BaseControlHandler.__init__( self, control )
    def bind( self, value ):
        self.control.setText(value.toString())
    def unbind( self ):
        return self.control.text()

class CheckBoxHandler( BaseContolHandler ):
    # etc


You could then set up a dictionary mapping the control type to the appropriate handler:

handlers = { QtLineEdit: LineEditHandler, QtCheckBox: CheckBoxHandler, ... }


So your main block of if..elif.. becomes

for ctltype in handlers:
    if isinstance( control, ctltype ):
        ctl = handlers[ctltype]( control )
        ctl.bind( value ) # or unbind
        break


You'll unfortunately need to keep the handlers= line and the subclasses in step together.

Code Snippets

class BaseControlHandler:
    def __init__( self, control ):
        self.control = control
    def bind( self, value ): 
        raise SuitableException()
    def unbind( self ):
        raise SuitableException()

class LineEditHandler( BaseControlHandler ):
    def __init__( self, control ):
        BaseControlHandler.__init__( self, control )
    def bind( self, value ):
        self.control.setText(value.toString())
    def unbind( self ):
        return self.control.text()

class CheckBoxHandler( BaseContolHandler ):
    # etc
handlers = { QtLineEdit: LineEditHandler, QtCheckBox: CheckBoxHandler, ... }
for ctltype in handlers:
    if isinstance( control, ctltype ):
        ctl = handlers[ctltype]( control )
        ctl.bind( value ) # or unbind
        break

Context

StackExchange Code Review Q#16454, answer score: 3

Revisions (0)

No revisions yet.