Hi all,
I think I need some MVC help once again:
I am using a custom item delegate that uses the bottom 20 pixels of a
cell in a table view for a QComboBox (the rest will be static content).
I can create the editor in the right spot etc, but I can't figure out
how to close it again when the user clicks into the upper part of the cell.
I tried all sorts of events and signals in the view, the delegate and
the editor itself but to no avail.
This is the state of things:
The initial table:
The table with the open editor after clicking into the bottom 20 pixels
of a cell:
The table after I click away from the editor but into the same cell, in
which case I'd like to close it and show the initial state as seen
above, but I just can't figure out how to.
Attached is the working code to produce the above images.
Any help would be greatly appreciated!
Cheers,
frank
--
ohufxLogo 50x50 <http://www.ohufx.com>
*vfx compositing <http://ohufx.com/compositing.html> | *workflow
customisation and consulting <http://ohufx.com/customising.html>* *
*<http://ohufx.com/compositing.html>*
<http://www.nukepedia.com/nubridge>
Your gateway to over 1,000 free tools... right inside of Nuke
<http://www.nukepedia.com/nubridge>
# simple table to compare versions of the same shot acros different sequences
from PySide2 import QtWidgets
from PySide2 import QtGui
from PySide2 import QtCore
class VersionChoser(QtWidgets.QComboBox):
def __init__(self, parent=None):
super(VersionChoser, self).__init__(parent)
self.setFocusPolicy(QtCore.Qt.StrongFocus)
class VersionTableModel(QtCore.QAbstractTableModel):
def __init__(self, parent=None):
super(VersionTableModel, self).__init__(parent)
def rowCount(self, index=None):
return 4
def columnCount(self, index=None):
return 6
def data(self, index, role):
if role == QtCore.Qt.DisplayRole:
try:
return "{}/{}".format(index.row(), index.column())
except TypeError:
return None
def flags(self, index):
flags = super(VersionTableModel, self).flags(index)
flags |= QtCore.Qt.ItemIsEditable
return flags
class VersionTableView(QtWidgets.QTableView):
def __init__(self, parent=None):
super(VersionTableView, self).__init__(parent)
self.setFrameStyle(QtWidgets.QFrame.NoFrame)
self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
def setModel(self, model):
super(VersionTableView, self).setModel(model)
self.resizeColumnsToContents()
self.resizeRowsToContents()
def minimumSizeHint(self):
return QtCore.QSize(self.width(), self.rowHeight(0) + self.horizontalHeader().height())
def mousePressEvent(self, event):
# edit cells when the right area is clicked
super(VersionTableView, self).mousePressEvent(event)
if not event.button() == QtCore.Qt.LeftButton:
return
index = self.indexAt(event.pos())
editorHeight = self.itemDelegate().editorHeight
editor_tl = self.mapToGlobal(self.visualRect(index).bottomLeft() + QtCore.QPoint(self.verticalHeader().width(), 2))
editor_br = self.mapToGlobal(self.visualRect(index).bottomRight() + QtCore.QPoint(self.verticalHeader().width(), 0) + QtCore.QPoint(0, editorHeight))
editorArea = QtCore.QRect(editor_tl, editor_br)
cursorPos = QtGui.QCursor().pos()
if editorArea.contains(cursorPos):
# Click was inside of editor area so open it for the index
self.setCurrentIndex(index)
self.edit(index)
else:
# Can't get this to work. I want to close the editor here (without committing any data).
print "\tclicked off - I want to close teh editor now if it's open" * 50
class VersionSyncWindow(QtWidgets.QWidget):
'''Main GUI for the version sync app'''
def __init__(self, parent=None):
super(VersionSyncWindow, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.Tool)
self.initUI()
self.__prepModel()
self.connectSignals()
def __prepModel(self):
'''Deal with proxy models and model/view assignments'''
self.versionModel = VersionTableModel()
self.tableViewReference.setModel(self.versionModel)
def connectSignals(self):
# perform the requested version sync
self.btnBox.rejected.connect(self.close)
def initUI(self):
# layouts
mainLayout = QtWidgets.QVBoxLayout()
self.setLayout(mainLayout)
# widgets
self.tableViewReference = VersionTableView()
self.tableViewReference.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
self.tableViewReference.setFocusPolicy(QtCore.Qt.NoFocus)
self.tableViewReference.setItemDelegate(VersionItemDelegate())
self.btnBox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Apply | QtWidgets.QDialogButtonBox.Cancel)
mainLayout.addWidget(self.tableViewReference)
mainLayout.addWidget(self.btnBox)
class VersionItemDelegate(QtWidgets.QStyledItemDelegate):
def __init__(self, parent=None):
super(VersionItemDelegate, self).__init__(parent)
self.editorHeight = 20
def createEditor(self, parent, option, index):
'''Creates a combo box to chose the version to sync in case tehre are mote than one used in a sequence.
Only show the editor if the mouse click ocurrs in the area where the editor lives.
'''
editor = QtWidgets.QComboBox(parent)
editor.setMaximumHeight(self.editorHeight)
return editor
def setEditorData(self, editor, index):
for n in xrange(10):
editor.addItem(str(n))
editor.showPopup()
def updateEditorGeometry(self, editor, option, index):
'''Move combo box down and make sure it fills the width of the cell'''
editor.move(option.rect.topLeft().x(), option.rect.height() - editor.height())
editor.resize(option.rect.width(), editor.height())
def paint(self, painter, option, index):
super(VersionItemDelegate, self).paint(painter, option, index)
# paint bottom bit
rect_to_paint = QtCore.QRect(option.rect.topLeft().x(), option.rect.bottomLeft().y() - self.editorHeight,
option.rect.width(), option.rect.height()*.3)
painter.setPen(QtGui.QPen(QtCore.Qt.NoPen))
painter.setBrush(QtGui.QBrush(QtCore.Qt.darkGreen))
painter.drawRect(rect_to_paint)
def sizeHint(self, option, index):
'''Adjust size hint for table view to resize to contents properly'''
return QtCore.QSize(200, 70)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication([])
mainWindow = VersionSyncWindow()
mainWindow.show()
sys.exit(app.exec_())
_______________________________________________
PySide mailing list
[email protected]
http://lists.qt-project.org/mailman/listinfo/pyside