It looks like you're new here. If you want to get involved, click one of these buttons!
Hello,
I am creating table model for my pya based gui and I was able to insert checkbox as widget while using QTableWidget, but after switching to QTableView I don't see checkbox, however, I developed similar application using raw PyQt and checkbox was there.
I am trying to put it into first column and here is my model:
class DRCTableModel(pya.QAbstractTableModel):
...
def data(self, index, role=pya.Qt_ItemDataRole.DisplayRole):
if role == pya.Qt_ItemDataRole.DisplayRole.to_i():
if index.column() == 0:
value = self.rules[index.row()].rule
elif index.column() == 1:
value = self.rules[index.row()].value
elif index.column() == 2:
if self.rules[index.row()].status != RuleStatus.UNKNOWN:
value = self.rules[index.row()].status.name
else:
value = ""
elif index.column() == 3:
value = self.rules[index.row()].category
elif index.column() == 4:
value = self.rules[index.row()].description
else:
value = ""
return value
elif role == pya.Qt_ItemDataRole.CheckStateRole.to_i() and index.column() == 0:
return pya.Qt_CheckState.Checked if self.rules[index.row()].is_checked else pya.Qt_CheckState.Unchecked
elif role == pya.Qt_ItemDataRole.BackgroundColorRole.to_i():
if index.column() == 2 and self.rules[index.row()].status == RuleStatus.PASS:
bgColor = pya.QColor(188, 247, 204)
elif index.column() == 2 and self.rules[index.row()].status == RuleStatus.FAIL:
bgColor = pya.QColor(255, 187, 181)
else:
bgColor = pya.QColor(pya.Qt.white)
return bgColor
else:
return pya.QVariant()
def flags(self, index):
fl = pya.QAbstractTableModel.flags(self, index)
if index.column() == 0:
fl |= pya.Qt_ItemFlag.ItemIsEditable | pya.Qt_ItemFlag.ItemIsUserCheckable
return fl
def setData(self, index, value, role=pya.Qt_ItemDataRole.EditRole):
if not index.isValid():
return False
if role == pya.Qt_ItemDataRole.CheckStateRole.to_i():
self.rules[index.row()].is_checked = value
return True
return False
I presented only those methods that important for checkbox column functionality.
Do I need actually to implement my own delegate? Or checkable item functionality does exists in pya?
thank you
Comments
See https://www.klayout.de/forum/discussion/2047/problem-with-qtreewidgetitem-setbackground as example of
CheckState
usage inQTreeWidget
.Hi @EugeneZelenko, thanks for the comment. I am not sure that understand it completely, but it looks like you are referring to changing check state of particular item in your QTreeWidget, am I right?
The point is that this is widget based way and it works for me as well (for QTableWidget) but I am trying switching to model-view architecture and check state in this way can be controlled through model directly. As I said, with raw Qt or PyQt I know how to do that but here checkbox is not plotting. Please, correct me if I misinterpreted your message.
Custom editing elements can be handled through user's delegate class, but for checking items it was always possible to use standard delegate.
@alexlpn I cannot debug or reproduce that isuee with partial code. Could you paste a full sample that allows me to reproduce the problem?
The reason may be manifold. I'm not using the Qt classes to an extent I have much experience with that myself.
A note of caution: the Qt bindings do not have the quality of PyQt, but I could not use PyQt. The reason is that PyQt is build atop of Python while in KLayout, Python sits atop of the application. That is a difference. Plus there was not PyQt equivalent for Ruby. So KLayout's Qt binding is supposed to provide the necessary API for utility UIs, but C++ to Python transition is tricky and I cannot give warranty that all functionality is properly implemented. The Qt API is simply too huge to give it a thorough testing.
I'd like to debug the issue, but please do not ask me to create a functional sample myself.
Matthias
Hi @Matthias , here I tried to compile small example (actually two).
This one is raw PyQt5 based:
This one is pya based (the difference is in Qt.CheckStateRole -> Qt.CheckStateRole.to_i() and similar roles :
Here are the plots of what gives PyQt and pya in comparison:
Those checkboxes I am talking about. Usually when I am flagging item as Qt.ItemIsUserCheckable this delegate will be plotted automatically.
I hope this highlights the issue.
Thanks, a lot for that nice test case.
I could debug the problem and fix it by using
(note the
to_i()
in the return statement).Here is my explanation: KLayout treats enums as typed objects. So if you have
Qt.CheckStateRole
it is actually a constant of typeQt::ItemDataRole
.That usually works nicely, but for the
QAbstractItemModel
, for some reason the role is declared as "int" in C++. Hence for the comparison you need to convert to int withto_i
. Maybe that can be simplified if I implement some "enum == int" compare. Until then you'll needto_i
.The same thing happens on the return side. The
QVariant
binding does not support "enum type to int" automatic conversion, but the C++ API requires an integer value. So again, you'll need to convert to int again. Maybe it's also possible to rectify that so eventually code is more compatible with PyQt5. Right now, I suggest the "to_i" workaround.Kind regards,
Matthias
I have issue a PR which should enable enum-to-int conversion in both directions (https://github.com/KLayout/klayout/pull/1055). This should remove the need for adding to_i. It's a too deep change to go into a minor release, but I'll include it in the next major one.
Matthias, this is great, thanks a lot!