Qt UI: Multiselection combobox PySide6 compatibility (#5314)

* convert state to value for pyside compatibility
use ItemIsUserTristate for keyboard event

* use whole field length to select item

* process keyboard tristate correctly

* get initial check state data as value

* try get state value for backwards compatibility

* formatting

* revert MouseButtonRelease event checks

* added new utils constant for tristate constant

* fixed both multiselection comboboxes

* fixed sorting of projects in project manager

* forgotten conversion of enum to int

---------

Co-authored-by: Jakub Trllo <jakub.trllo@gmail.com>
This commit is contained in:
Alexey Bogomolov 2023-07-18 17:00:36 +03:00 committed by GitHub
parent 961bfe6c2e
commit e917d2b91f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 21 deletions

View file

@ -84,6 +84,13 @@ class ProjectProxyFilter(QtCore.QSortFilterProxyModel):
super(ProjectProxyFilter, self).__init__(*args, **kwargs)
self._filter_default = False
def lessThan(self, left, right):
if left.data(PROJECT_NAME_ROLE) is None:
return True
if right.data(PROJECT_NAME_ROLE) is None:
return False
return super(ProjectProxyFilter, self).lessThan(left, right)
def set_filter_default(self, enabled=True):
"""Set if filtering of default item is enabled."""
if enabled == self._filter_default:

View file

@ -1,6 +1,14 @@
from qtpy import QtCore, QtWidgets
from openpype.tools.utils.lib import checkstate_int_to_enum
from openpype.tools.utils.lib import (
checkstate_int_to_enum,
checkstate_enum_to_int,
)
from openpype.tools.utils.constants import (
CHECKED_INT,
UNCHECKED_INT,
ITEM_IS_USER_TRISTATE,
)
class ComboItemDelegate(QtWidgets.QStyledItemDelegate):
@ -107,9 +115,9 @@ class MultiSelectionComboBox(QtWidgets.QComboBox):
return
if state == QtCore.Qt.Unchecked:
new_state = QtCore.Qt.Checked
new_state = CHECKED_INT
else:
new_state = QtCore.Qt.Unchecked
new_state = UNCHECKED_INT
elif event.type() == QtCore.QEvent.KeyPress:
# TODO: handle QtCore.Qt.Key_Enter, Key_Return?
@ -117,15 +125,15 @@ class MultiSelectionComboBox(QtWidgets.QComboBox):
# toggle the current items check state
if (
index_flags & QtCore.Qt.ItemIsUserCheckable
and index_flags & QtCore.Qt.ItemIsTristate
and index_flags & ITEM_IS_USER_TRISTATE
):
new_state = QtCore.Qt.CheckState((int(state) + 1) % 3)
new_state = (checkstate_enum_to_int(state) + 1) % 3
elif index_flags & QtCore.Qt.ItemIsUserCheckable:
if state != QtCore.Qt.Checked:
new_state = QtCore.Qt.Checked
new_state = CHECKED_INT
else:
new_state = QtCore.Qt.Unchecked
new_state = UNCHECKED_INT
if new_state is not None:
model.setData(current_index, new_state, QtCore.Qt.CheckStateRole)
@ -180,9 +188,9 @@ class MultiSelectionComboBox(QtWidgets.QComboBox):
for idx in range(self.count()):
value = self.itemData(idx, role=QtCore.Qt.UserRole)
if value in values:
check_state = QtCore.Qt.Checked
check_state = CHECKED_INT
else:
check_state = QtCore.Qt.Unchecked
check_state = UNCHECKED_INT
self.setItemData(idx, check_state, QtCore.Qt.CheckStateRole)
def value(self):

View file

@ -1,5 +1,13 @@
from qtpy import QtCore, QtGui, QtWidgets
from openpype.tools.utils.lib import checkstate_int_to_enum
from openpype.tools.utils.lib import (
checkstate_int_to_enum,
checkstate_enum_to_int,
)
from openpype.tools.utils.constants import (
CHECKED_INT,
UNCHECKED_INT,
ITEM_IS_USER_TRISTATE,
)
class ComboItemDelegate(QtWidgets.QStyledItemDelegate):
@ -30,7 +38,7 @@ class MultiSelectionComboBox(QtWidgets.QComboBox):
QtCore.Qt.Key_PageDown,
QtCore.Qt.Key_PageUp,
QtCore.Qt.Key_Home,
QtCore.Qt.Key_End
QtCore.Qt.Key_End,
}
top_bottom_padding = 2
@ -127,25 +135,25 @@ class MultiSelectionComboBox(QtWidgets.QComboBox):
return
if state == QtCore.Qt.Unchecked:
new_state = QtCore.Qt.Checked
new_state = CHECKED_INT
else:
new_state = QtCore.Qt.Unchecked
new_state = UNCHECKED_INT
elif event.type() == QtCore.QEvent.KeyPress:
# TODO: handle QtCore.Qt.Key_Enter, Key_Return?
if event.key() == QtCore.Qt.Key_Space:
# toggle the current items check state
if (
index_flags & QtCore.Qt.ItemIsUserCheckable
and index_flags & QtCore.Qt.ItemIsTristate
and index_flags & ITEM_IS_USER_TRISTATE
):
new_state = QtCore.Qt.CheckState((int(state) + 1) % 3)
new_state = (checkstate_enum_to_int(state) + 1) % 3
elif index_flags & QtCore.Qt.ItemIsUserCheckable:
# toggle the current items check state
if state != QtCore.Qt.Checked:
new_state = QtCore.Qt.Checked
new_state = CHECKED_INT
else:
new_state = QtCore.Qt.Unchecked
new_state = UNCHECKED_INT
if new_state is not None:
model.setData(current_index, new_state, QtCore.Qt.CheckStateRole)
@ -249,7 +257,6 @@ class MultiSelectionComboBox(QtWidgets.QComboBox):
QtWidgets.QStyle.SC_ComboBoxArrow
)
total_width = option.rect.width() - btn_rect.width()
font_metricts = self.fontMetrics()
line = 0
self.lines = {line: []}
@ -305,9 +312,9 @@ class MultiSelectionComboBox(QtWidgets.QComboBox):
for idx in range(self.count()):
value = self.itemData(idx, role=QtCore.Qt.UserRole)
if value in values:
check_state = QtCore.Qt.Checked
check_state = CHECKED_INT
else:
check_state = QtCore.Qt.Unchecked
check_state = UNCHECKED_INT
self.setItemData(idx, check_state, QtCore.Qt.CheckStateRole)
self.update_size_hint()

View file

@ -5,6 +5,12 @@ UNCHECKED_INT = getattr(QtCore.Qt.Unchecked, "value", 0)
PARTIALLY_CHECKED_INT = getattr(QtCore.Qt.PartiallyChecked, "value", 1)
CHECKED_INT = getattr(QtCore.Qt.Checked, "value", 2)
# Checkbox state
try:
ITEM_IS_USER_TRISTATE = QtCore.Qt.ItemIsUserTristate
except AttributeError:
ITEM_IS_USER_TRISTATE = QtCore.Qt.ItemIsTristate
DEFAULT_PROJECT_LABEL = "< Default >"
PROJECT_NAME_ROLE = QtCore.Qt.UserRole + 101
PROJECT_IS_ACTIVE_ROLE = QtCore.Qt.UserRole + 102