PDA

View Full Version : Faking layout of custom editor widget in item delegate



mvromer
10th May 2011, 21:41
I have this TreeView that has a custom item delegate whose class I've inherited from QStyledItemDelegate. The view is basically used as a parameter editor where one column displays the name of the parameter, and the other column shows the current value of the parameter and can also be used to edit and and enter in a new value for the parameter.

For the majority of the items, I simply use a QLineEdit as the item's editor in my custom delegate class. However, for other items that represent filesystem locations, I've created a custom widget that's simply a QLineEdit (displaying the path) and a QPushButton (a "Browse..." button that opens up a choose folder dialog) put together in a horizontal box layout.

As can be seen from the attached image, I can properly create and display the editor widget whenever I'm currently editing the parameter (e.g., the job_directory parameter). But now I want to override the QStyledItemDelegate::paint() method to render the controls for my custom widget without actually having to create and use an instance of my custom widget (since, from what I understand, that's the preferred way of rendering editors within a delegate).

My question is how do I properly calculate the location and size of each of my widget's subcontrols when I don't have the actual widget instances myself? Essentially I'd want to do whatever it is that the QHBoxLayout object is doing in my custom widget so that I can fake the layout of the subcontrols and render them using the QStyle painter, but I don't know how to do this (or if it's even possible). I've looked at the various QLayout-derived classes as well as the documentation and examples for QAbstractItemDelegate and friends, but I haven't had luck in finding out how to do proper layout of custom editors for painting purposes. If anyone has any examples or links to docs that I should look over that'll give me a better idea of how to accomplish this, I'd greatly appreciate it.

For reference, here's my custom widget class and parts of my item delegate class:



from PySide import QtCore
from PySide import QtGui

class FilePathEditor( QtGui.QWidget ):
def __init__( self, parent=none, window_flags=QtCore.QtWidget ):
super( FilePathEditor, self ).__init__( parent, window_flags )
self.path_line = QtGui.QLineEdit( self )
self.browse_button = QtGui.QPushButton( "Browse...", self )

layout = QtGui.QHBoxLayout()
layout.setContentsMargins( 0, 0, 0, 0 )
layout.setSpacing( 1 )
layout.addWidget( self.path_line )
layout.addWidget( self.browse_button )
self.setLayout( layout )

self.browse_button.clicked.connect( self.choose_path )

# ... additional methods removed for brevity....


class ParameterItemDelegate( QtGui.QStyledItemDelegate ):
def __init__( self, parent=None ):
super( ParameterItemDelegate, self ).__init__( parent )

def updateEditorGeometry( self, editor, option, index ):
editor.setGeometry( option.rect )

def paint( self, painter, option, index ):
# grab pointer to my internal data structure for each item stored in my tree model.
item = index.internalPointer()

if index.column() == VALUE_COLUMN and item.has_path_data():
# XXX: how to properly draw my custom editor widget?
else:
super( ParameterItemDelegate, self ).paint( painter, option, index )

# ... additional methods removed for brevity....

Lykurg
10th May 2011, 22:35
Hi, what you need is QStyle::drawControl() with QStyle::CE_PushButton. Further you need to calculate the rect parameter of the QStyleOption yourself. For that use QStyle::pixelMetric() with QStyle::PM_ButtonMargin, QStyle::PM_DefaultFrameWidth, QStyle::PM_LayoutLeftMargin, ...