From 594c1cc0bfd25e6109b3d80caec6acbc1ec72542 Mon Sep 17 00:00:00 2001 From: BHARATH0153 Date: Mon, 8 Jun 2026 10:19:09 +0530 Subject: [PATCH 1/2] fix: use Qt flag_val() for PySide6 compat in IDA plugin --- capa/ida/plugin/item.py | 10 +++++----- capa/ida/plugin/qt_compat.py | 16 +++++++++------- capa/ida/plugin/view.py | 12 ++++++------ 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/capa/ida/plugin/item.py b/capa/ida/plugin/item.py index 3292de1c0a..4e6db7a552 100644 --- a/capa/ida/plugin/item.py +++ b/capa/ida/plugin/item.py @@ -21,7 +21,7 @@ import capa.ida.helpers from capa.features.address import Address, FileOffsetAddress, AbsoluteVirtualAddress -from capa.ida.plugin.qt_compat import QtCore, qt_get_item_flag_tristate +from capa.ida.plugin.qt_compat import QtCore, qt_get_item_flag_tristate, flag_val def info_to_name(display): @@ -52,10 +52,10 @@ def __init__(self, parent: Optional["CapaExplorerDataItem"], data: list[str], ca self._can_check = can_check # default state for item - self.flags = QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable + self.flags = flag_val(QtCore.Qt.ItemIsEnabled) | flag_val(QtCore.Qt.ItemIsSelectable) if self._can_check: - self.flags = self.flags | QtCore.Qt.ItemIsUserCheckable | qt_get_item_flag_tristate() + self.flags = self.flags | flag_val(QtCore.Qt.ItemIsUserCheckable) | qt_get_item_flag_tristate() if self.pred: self.pred.appendChild(self) @@ -66,9 +66,9 @@ def setIsEditable(self, isEditable=False): @param isEditable: True, can edit, False cannot edit """ if isEditable: - self.flags |= QtCore.Qt.ItemIsEditable + self.flags |= flag_val(QtCore.Qt.ItemIsEditable) else: - self.flags &= ~QtCore.Qt.ItemIsEditable + self.flags &= ~flag_val(QtCore.Qt.ItemIsEditable) def setChecked(self, checked): """set item as checked diff --git a/capa/ida/plugin/qt_compat.py b/capa/ida/plugin/qt_compat.py index 7b3858a719..8e8fdf2da1 100644 --- a/capa/ida/plugin/qt_compat.py +++ b/capa/ida/plugin/qt_compat.py @@ -41,6 +41,12 @@ Qt = QtCore.Qt +def flag_val(flag): + if hasattr(flag, 'value'): + return flag.value + return flag + + def qt_get_item_flag_tristate(): """ Get the tristate item flag compatible with Qt5 and Qt6. @@ -59,12 +65,8 @@ def qt_get_item_flag_tristate(): AttributeError: If the tristate flag cannot be found in the Qt library """ if QT_LIBRARY == "PySide6": - # Qt6: ItemIsTristate was removed, replaced with ItemIsAutoTristate - # Try different possible locations (API varies slightly across PySide6 versions) - if hasattr(Qt, "ItemIsAutoTristate"): - return Qt.ItemIsAutoTristate - elif hasattr(Qt, "ItemFlag") and hasattr(Qt.ItemFlag, "ItemIsAutoTristate"): - return Qt.ItemFlag.ItemIsAutoTristate + if hasattr(Qt, "ItemFlag") and hasattr(Qt.ItemFlag, "ItemIsAutoTristate"): + return Qt.ItemFlag.ItemIsAutoTristate.value else: raise AttributeError( "Cannot find ItemIsAutoTristate in PySide6. " @@ -76,4 +78,4 @@ def qt_get_item_flag_tristate(): return Qt.ItemIsTristate -__all__ = ["qt_get_item_flag_tristate", "Signal", "QAction", "QtGui", "QtCore", "QtWidgets"] +__all__ = ["flag_val", "qt_get_item_flag_tristate", "Signal", "QAction", "QtGui", "QtCore", "QtWidgets"] diff --git a/capa/ida/plugin/view.py b/capa/ida/plugin/view.py index 7a77591647..7254c1b6ef 100644 --- a/capa/ida/plugin/view.py +++ b/capa/ida/plugin/view.py @@ -26,7 +26,7 @@ from capa.ida.plugin.item import CapaExplorerFunctionItem from capa.features.address import FileOffsetAddress, AbsoluteVirtualAddress, _NoAddress from capa.ida.plugin.model import CapaExplorerDataModel -from capa.ida.plugin.qt_compat import QtGui, QtCore, Signal, QAction, QtWidgets +from capa.ida.plugin.qt_compat import QtGui, QtCore, Signal, QAction, QtWidgets, flag_val MAX_SECTION_SIZE = 750 @@ -484,9 +484,9 @@ def slot_item_double_clicked(self, o, column): CapaExplorerRulegenEditor.get_column_comment_index(), CapaExplorerRulegenEditor.get_column_description_index(), ): - o.setFlags(o.flags() | QtCore.Qt.ItemIsEditable) + o.setFlags(int(o.flags()) | flag_val(QtCore.Qt.ItemIsEditable)) self.editItem(o, column) - o.setFlags(o.flags() & ~QtCore.Qt.ItemIsEditable) + o.setFlags(int(o.flags()) & ~flag_val(QtCore.Qt.ItemIsEditable)) self.is_editing = True def update_preview(self): @@ -601,13 +601,13 @@ def set_expression_node(self, o): def set_feature_node(self, o): """ """ setattr(o, "capa_type", CapaExplorerRulegenEditor.get_node_type_feature()) - o.setFlags(o.flags() & ~QtCore.Qt.ItemIsDropEnabled) + o.setFlags(int(o.flags()) & ~flag_val(QtCore.Qt.ItemIsDropEnabled)) self.style_feature_node(o) def set_comment_node(self, o): """ """ setattr(o, "capa_type", CapaExplorerRulegenEditor.get_node_type_comment()) - o.setFlags(o.flags() & ~QtCore.Qt.ItemIsDropEnabled) + o.setFlags(int(o.flags()) & ~flag_val(QtCore.Qt.ItemIsDropEnabled)) self.style_comment_node(o) @@ -1009,7 +1009,7 @@ def style_leaf_node(self, o): def set_parent_node(self, o): """ """ - o.setFlags(o.flags() & ~QtCore.Qt.ItemIsSelectable) + o.setFlags(int(o.flags()) & ~flag_val(QtCore.Qt.ItemIsSelectable)) setattr(o, "capa_type", CapaExplorerRulegenFeatures.get_node_type_parent()) self.style_parent_node(o) From c3e59136dda41a5e3008b13af74da6c23ef54ce2 Mon Sep 17 00:00:00 2001 From: chandra Date: Mon, 8 Jun 2026 10:20:56 +0530 Subject: [PATCH 2/2] Update capa/ida/plugin/qt_compat.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- capa/ida/plugin/qt_compat.py | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/capa/ida/plugin/qt_compat.py b/capa/ida/plugin/qt_compat.py index 8e8fdf2da1..1f3d44edfb 100644 --- a/capa/ida/plugin/qt_compat.py +++ b/capa/ida/plugin/qt_compat.py @@ -57,16 +57,12 @@ def qt_get_item_flag_tristate(): ItemIsAutoTristate automatically manages tristate based on child checkboxes, matching the original ItemIsTristate behavior where parent checkboxes reflect the check state of their children. - - Returns: - int: The appropriate flag value for the Qt version - - Raises: - AttributeError: If the tristate flag cannot be found in the Qt library - """ +def qt_get_item_flag_tristate(): if QT_LIBRARY == "PySide6": - if hasattr(Qt, "ItemFlag") and hasattr(Qt.ItemFlag, "ItemIsAutoTristate"): - return Qt.ItemFlag.ItemIsAutoTristate.value + if hasattr(Qt, "ItemIsAutoTristate"): + return flag_val(Qt.ItemIsAutoTristate) + elif hasattr(Qt, "ItemFlag") and hasattr(Qt.ItemFlag, "ItemIsAutoTristate"): + return flag_val(Qt.ItemFlag.ItemIsAutoTristate) else: raise AttributeError( "Cannot find ItemIsAutoTristate in PySide6. " @@ -74,8 +70,7 @@ def qt_get_item_flag_tristate(): + f"Available Qt attributes: {[attr for attr in dir(Qt) if 'Item' in attr]}" ) else: - # Qt5: Use the original ItemIsTristate flag - return Qt.ItemIsTristate + return flag_val(Qt.ItemIsTristate) __all__ = ["flag_val", "qt_get_item_flag_tristate", "Signal", "QAction", "QtGui", "QtCore", "QtWidgets"]