473,385 Members | 1,622 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

models & editors in PyQt4

Hi,

I created simple property classes with editing option, but since i'm not
too much experienced in PyQt4 i'd like to ask if i handle ColorProperty
changing right. Any other Property has its own editor and their control
flow is imho ok. Hovewer i'm not sure about ColorProperty.

What i do is: in createEditor(self, parent, option, index) i call
QtGui.QColorDialog.getColor() and return None

What do you think? Is it Ok?

thanks,
skink

#--------------------------------------------
import sys
from PyQt4 import QtGui, QtCore

class PropertyDelegate(QtGui.QItemDelegate):
def __init__(self, model):
QtGui.QItemDelegate.__init__(self, None)
self.model = model
def createEditor(self, parent, option, index):
if index.column() == 0:
return None
item = self.model.getItem(index)
return item.createEditor(parent, option, index)
def setEditorData(self, editor, index):
item = self.model.getItem(index)
item.setEditorData(editor, index)
def setModelData(self, editor, model, index):
item = self.model.getItem(index)
item.setModelData(editor, model, index)
# def updateEditorGeometry(self, editor, option, index):
# editor.setGeometry(option.rect)
def paint(self, painter, option, index):
item = self.model.getItem(index)
if isinstance(item, ColorProperty) and index.column() == 1:
item.paint(painter, option, index)
return
QtGui.QItemDelegate.paint(self, painter, option, index)

class SimpleModelItem:
def __init__(self, parent=0):
self._index = []
self._children = []
self._parent = parent
if parent:
parent._children.append(self)
self._parent = parent
def parent(self):
return self._parent
def children(self):
return self._children
def addIndex(self, index):
self._index.append(index)
def childId(self, child):
return id(self._children[child])
def index(self, column=0):
return self._index[column]

class Property(SimpleModelItem):
def __init__(self, parent=0, name="", data=[]):
SimpleModelItem.__init__(self, parent)
self._data = data
self._name = name
def data(self, index):
return self._data[index.column()]
def name(self):
return self._name
def createEditor(self, parent, option, index):
return None
def setEditorData(self, editor, index):
return
def setModelData(self, editor, model, index):
return

class StringProperty(Property):
def __init__(self, parent, name, t):
Property.__init__(self, parent, name, [t, ""])
def createEditor(self, parent, option, index):
editor = QtGui.QLineEdit(parent)
return editor
def setEditorData(self, editor, index):
value = index.model().getObjectData(self.name())
editor.setText(value)
def setModelData(self, editor, model, index):
index.model().setObjectData(self.name(), editor.text())
def data(self, index):
if index.column() == 0:
return self._data[0]
else:
return str(index.model().getObjectData(self.name()))
class IntegerProperty(Property):
def __init__(self, parent, name, t):
Property.__init__(self, parent, name, [t, ""])
def createEditor(self, parent, option, index):
editor = QtGui.QSpinBox(parent)
editor.setMaximum(256*256)
return editor
def setEditorData(self, editor, index):
value = index.model().getObjectData(self.name())
editor.setValue(value)
def setModelData(self, editor, model, index):
index.model().setObjectData(self.name(), editor.value())
def data(self, index):
if index.column() == 0:
return self._data[0]
else:
return str(index.model().getObjectData(self.name()))

class SizeProperty(Property):
def __init__(self, parent, name, t):
Property.__init__(self, parent, name, [t, ""])
self.items = []
self.items.append(IntegerProperty(self, name+":x", "x"))
self.items.append(IntegerProperty(self, name+":y", "y"))
self.items.append(IntegerProperty(self, name+":w", "width"))
self.items.append(IntegerProperty(self, name+":h", "height"))

class ColorProperty(Property):
def __init__(self, parent, name, t):
Property.__init__(self, parent, name, [t, ""])
def createEditor(self, parent, option, index):
color = QtGui.QColorDialog.getColor()
if color.isValid():
index.model().setObjectData(self.name(), color)
return None
def paint(self, painter, option, index):
r = option.rect
if option.state & QtGui.QStyle.State_Selected:
painter.fillRect(r, option.palette.highlight())
color = index.model().getObjectData(self.name())
colorStr = color.name()
tr = painter.boundingRect(r, QtCore.Qt.AlignLeft, colorStr)
w = tr.width() + 4
painter.fillRect(r.x() + 1, r.y() + 1, r.width() - 3 - w,
r.height() - 3, QtGui.QBrush(color))
painter.setPen(QtCore.Qt.black)
painter.drawRect(r.x() + 1, r.y() + 1, r.width() - 3 - w,
r.height() - 3)
r.setLeft(r.x() + r.width() + 1 - w)
painter.drawText(r, QtCore.Qt.AlignLeft, colorStr)

class EnumProperty(Property):
def __init__(self, parent, name, t, te):
Property.__init__(self, parent, name, [t, ""])
self.te = te
def createEditor(self, parent, option, index):
editor = QtGui.QComboBox(parent)
i = 0
for item in self.te:
editor.addItem(item, QtCore.QVariant(i))
i += 1
return editor
def setEditorData(self, editor, index):
index = index.model().getObjectData(self.name())
editor.setCurrentIndex(index)
def setModelData(self, editor, model, index):
index.model().setObjectData(self.name(), editor.currentIndex())
def data(self, index):
if index.column() == 0:
return self._data[0]
else:
index = index.model().getObjectData(self.name())
return self.te[index]

class BooleanProperty(EnumProperty):
def __init__(self, parent, name, t):
EnumProperty.__init__(self, parent, name, t, ["False", "True"])

#-----------------------------------------------------------------------
class SimpleModel(QtCore.QAbstractItemModel):
def __init__(self, root, parent=None):
QtCore.QAbstractItemModel.__init__(self, parent)
self.ids = {}

self.root = root
self.root.addIndex(QtCore.QModelIndex())
self.ids[id(self.root)] = self.root

self.walk(root)
def walk(self, parent):
row = 0
for child in parent.children():
_id = id(child)
self.ids[_id] = child
child.addIndex(self.createIndex(row, 0, _id))
child.addIndex(self.createIndex(row, 1, _id))
self.walk(child)
row += 1
def getItem(self, index):
if not index.isValid():
return self.root
else:
return self.ids[index.internalId()]

#-----------------------------------------------------------------------
def setObject(self, obj):
self.obj = obj
self.reset()
def getObjectData(self, name):
#print "getObjectData", name, self.obj[name]
return self.obj[name]
def setObjectData(self, name, value):
#print "setObjectData", name, value
self.obj[name] = value

#-----------------------------------------------------------------------
def index(self, row, column, parent):
parentItem = self.getItem(parent)
childItem = self.ids[parentItem.childId(row)]
return childItem.index(column)
def parent(self, index):
childItem = self.getItem(index)
parentItem = childItem.parent()
return parentItem.index()
def rowCount(self, parent):
parentItem = self.getItem(parent)
return len(parentItem.children())
def columnCount(self, parent):
return 2
def data(self, index, role):
if not index.isValid() or role != QtCore.Qt.DisplayRole:
return QtCore.QVariant()
item = self.getItem(index)
return QtCore.QVariant(item.data(index))
def flags(self, index):
if not index.isValid():
return QtCore.Qt.ItemIsEnabled
else:
return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
| QtCore.Qt.ItemIsEditable
def headerData(self, section, orientation, role):
if orientation == QtCore.Qt.Horizontal and role ==
QtCore.Qt.DisplayRole:
if section == 0:
return QtCore.QVariant("Name")
else:
return QtCore.QVariant("Value")
return QtCore.QVariant()

objAData = {
"width": 6, "size:x": 10, "size:y": 15, "size:w": 20, "size:h": 25,
"frameType": 0, "visible": 1, "color": QtGui.QColor(QtCore.Qt.red),
"name": "foobar A"
}
objBData = {
"width": 66, "size:x": 100, "size:y": 150, "size:w": 200, "size:h":
250,
"frameType": 1, "visible": 0, "color": QtGui.QColor(QtCore.Qt.green),
"name": "foobar B"
}
objCData = {
"width": 666, "size:x": 1000, "size:y": 1500, "size:w": 2000,
"size:h": 2500,
"frameType": 2, "visible": 1, "color": QtGui.QColor(QtCore.Qt.blue),
"name": "foobar C"
}

root = Property()
newItem = StringProperty(root, "name", "Name")
newItem = IntegerProperty(root, "width", "Item Width")
newItem = ColorProperty(root, "color", "Background Color")
newItem = SizeProperty(root, "size", "Item Size")
newItem = EnumProperty(root, "frameType", "Frame Type", ["Solid",
"Dashed", "None"])
newItem = BooleanProperty(root, "visible", "Visibility")

class Widget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
mainLayout = QtGui.QVBoxLayout()

self.treeView = QtGui.QTreeView()

self.treeView.setEditTriggers(QtGui.QAbstractItemV iew.SelectedClicked)
self.model = SimpleModel(root)
self.delegate = PropertyDelegate(self.model)
self.treeView.setItemDelegate(self.delegate)
self.model.setObject(objAData)
self.treeView.setModel(self.model)
mainLayout.addWidget(self.treeView)
b1 = QtGui.QPushButton("Object A")
self.connect(b1, QtCore.SIGNAL("clicked()"), self.objAClicked)
mainLayout.addWidget(b1)
b2 = QtGui.QPushButton("Object B")
self.connect(b2, QtCore.SIGNAL("clicked()"), self.objBClicked)
mainLayout.addWidget(b2)
b3 = QtGui.QPushButton("Object C")
self.connect(b3, QtCore.SIGNAL("clicked()"), self.objCClicked)
mainLayout.addWidget(b3)
self.setLayout(mainLayout)
def objAClicked(self):
self.model.setObject(objAData)
def objBClicked(self):
self.model.setObject(objBData)
def objCClicked(self):
self.model.setObject(objCData)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
widget = Widget()
widget.show()
sys.exit(app.exec_())
#--------------------------------------------
Aug 30 '06 #1
3 3179
Skink wrote:
I created simple property classes with editing option, but since i'm not
too much experienced in PyQt4 i'd like to ask if i handle ColorProperty
changing right. Any other Property has its own editor and their control
flow is imho ok. Hovewer i'm not sure about ColorProperty.

What i do is: in createEditor(self, parent, option, index) i call
QtGui.QColorDialog.getColor() and return None

What do you think? Is it Ok?
It should be OK - it shouldn't crash, anyway. It depends on the view
doing the right thing when it finds that it hasn't received an editor
widget.

You could create an empty placeholder widget in the createEditor()
method, call QColorDialog.getColor() with the existing color from the
model in setEditorData(), record the color returned by the dialog in
some internal instance variable, and finally set the data in the model
when setModelData() is called:

class ColorProperty(Property):
...
def createEditor(self, parent, option, index):
return QtGui.QWidget(parent)
def setEditorData(self, editor, index):
self.color = QtGui.QColorDialog.getColor(
index.model().getObjectData(self.name()))
def setModelData(self, editor, model, index):
if self.color.isValid():
index.model().setObjectData(self.name(), self.color)
...

I find it strange that you have to triple-click to edit any of the
items in your example. Do you see the same behaviour?

David

Aug 30 '06 #2
David Boddie wrote:
>
It should be OK - it shouldn't crash, anyway. It depends on the view
doing the right thing when it finds that it hasn't received an editor
widget.

You could create an empty placeholder widget in the createEditor()
method, call QColorDialog.getColor() with the existing color from the
model in setEditorData(), record the color returned by the dialog in
some internal instance variable, and finally set the data in the model
when setModelData() is called:

class ColorProperty(Property):
...
def createEditor(self, parent, option, index):
return QtGui.QWidget(parent)
def setEditorData(self, editor, index):
self.color = QtGui.QColorDialog.getColor(
index.model().getObjectData(self.name()))
def setModelData(self, editor, model, index):
if self.color.isValid():
index.model().setObjectData(self.name(), self.color)
thanks for tip, i'll check it how it works.
...

I find it strange that you have to triple-click to edit any of the
items in your example. Do you see the same behaviour?
oh, this is default Qt behavoiur: first click selects row, second select
editor (for ColorProperty, IntProperty & StringProperty you can now
change the value) but third click is required only for properties w/
QCombobox editor (EnumProperty & BooleanProperty) ...

skink
>
David
Aug 30 '06 #3
Skink wrote:
David Boddie wrote:
I find it strange that you have to triple-click to edit any of the
items in your example. Do you see the same behaviour?
oh, this is default Qt behavoiur: first click selects row, second select
editor (for ColorProperty, IntProperty & StringProperty you can now
change the value) but third click is required only for properties w/
QCombobox editor (EnumProperty & BooleanProperty) ...
It seemed that, even if the row was already selected, it took more than
a double click to start editing. I'll have to take another look at it.

David

Aug 30 '06 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Perttu Pulkkinen | last post by:
Hi all freaks! I have been thinking hard, what would be good solution for a straight-forward content management. I want to forget polls and forms etc.. and concentrate first only on different...
4
by: Adam Knight | last post by:
Hi all, I am using a dreamweaver template for a web app i am working on. Each time i update the template my page directives at the top of the associated pages gets removed. Anyone had...
1
by: shane.external | last post by:
I'm having trouble using Py2exe with a PyQT-based python project. Or possibly I'm having a problem with PyQT and Py2exe makes it apparent. Whichever it is, I run into trouble with importing QtCore...
2
by: Harshad | last post by:
Hi, I'm writing a program using Python 2.4 and PyQt4. The aim is to implement drag and drop from filesystem and display a list of files dragged on to the listWidget. This function will later...
3
by: Tina I | last post by:
I'm trying to 'convert' my self from Qt3 to Qt4 (it rocks!) and one thing seem strange: With Qt3 I usually did "from qt import *", but this does not seem to work with Qt4. I have to use "from...
25
by: Daniel Jonsson | last post by:
So, I've reached the point where my building pipeline tools actually needs to be used by other people in my company. By this reason I actually need to think about the usability, and I've come to...
2
by: AngelOfDarkness | last post by:
Hi guys, unfortunately I am pretty new to Python and Qt and all that. Well, I managed to successfully program a little stuff for my work (computational neuroscientist... no comment please), using...
5
by: Mel | last post by:
I am currently porting an SQL centered Visual Basic application to run on Linux, Python, and Qt4. Currently I am stumped on changing row colors in the QTableView widget. My test code is based on...
2
by: jiang.haiyun | last post by:
Hi, I am having some serious problems with PyQT4, when i run pyqt script, I always get 'Segmentation fault'. the script is simple: ====================== %less qttest.py from PyQt4 import...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.