How to dynamically compose QtCore.Qt.MatchgFlag(s) together rather than hard-coding them

I am trying to write a small app to control FastAPI server’s configuration, using a dictionary. Due to the fact that I am using a QTreeView, and would like to create a search box for entering text value for the dictionary key, and asking the GUI app to expand the key, and highlight the interested key, value pair, so I can jumping to edit and change the configuration onfly. There is a search MatchFlag, but I do not know how it is implemented in C++ end, this MatchFlag doesn’t behave like Python 3.9 Flag class, so I wrapped with this:

import re
from enum import Enum, Flag
from PyQt5 import QtCore
from collections import OrderedDict
from definition import Definitions as df
import logging

class GUIMatchFlag(Flag):
    SelectSearchOptions = -1
    MatchWrap = QtCore.Qt.MatchFlag.MatchWrap
    MatchRecursive = QtCore.Qt.MatchFlag.MatchRecursive
    MatchContains = QtCore.Qt.MatchFlag.MatchContains
    MatchExactly = QtCore.Qt.MatchFlag.MatchExactly
    MatchStartsWith = QtCore.Qt.MatchFlag.MatchStartsWith
    MatchEndsWith = QtCore.Qt.MatchFlag.MatchEndsWith
    MatchRegularExpression = QtCore.Qt.MatchFlag.MatchRegularExpression
    MatchWildcard = QtCore.Qt.MatchFlag.MatchWildcard
    MatchFixedString = QtCore.Qt.MatchFlag.MatchFixedString
    MatchCaseSensitive = QtCore.Qt.MatchFlag.MatchCaseSensitive

    # flag_list = None

    @classmethod
    def splitTitleChar(cls, txt: str, is_name_only=False):
        new_txt = re.sub(r'([a-z])([A-Z)])', r'1 2', txt)
        new_txt = (new_txt.split('.')[1] if is_name_only else new_txt)
        return new_txt


    @classmethod
    def getFlagDict(cls, is_name_only=False):
        attrib_name = ("name_only_flag_list" if is_name_only else "flag_list")
        is_init = not hasattr(cls, attrib_name)
        if is_init:
            flag_dict = OrderedDict()
            for item in GUIMatchFlag:
                split_name = cls.splitTitleChar(str(item), is_name_only=is_name_only)
                entry = {split_name: item.value}
                flag_dict.update(entry)
            setattr(cls, attrib_name, flag_dict)
        return getattr(cls, attrib_name)

    @classmethod
    def getQtFlagValue(cls, flag_name: str, is_name_only=False):
        name_to_find = cls.splitTitleChar(flag_name)
        flag_dict = cls.getFlagDict(is_name_only=is_name_only)
        find_value = flag_dict[name_to_find]
        return find_value

    @classmethod
    def getIndexForName(cls, flag_name: str, is_name_only=False):
        flag_dict = cls.getFlagDict(is_name_only=is_name_only)
        name_index_list = [(name, index) for (index, (name, value)) in enumerate(flag_dict.items()) if (name == flag_name)]
        return name_index_list[0][1]

    @classmethod
    def getQtComposeFlagValues(cls, flag_list: list[str]):
        logger.info(f'flag_list:{flag_list}')
        # local_list = [
        #     QtCore.Qt.MatchFlag.MatchWrap,
        #     QtCore.Qt.MatchFlag.MatchRecursive,
        #     QtCore.Qt.MatchFlag.MatchContains,
        #     QtCore.Qt.MatchFlag.MatchExactly,
        #     QtCore.Qt.MatchFlag.MatchStartsWith,
        #     QtCore.Qt.MatchFlag.MatchEndsWith,
        #     QtCore.Qt.MatchFlag.MatchRegularExpression,
        #     QtCore.Qt.MatchFlag.MatchWildcard,
        #     QtCore.Qt.MatchFlag.MatchFixedString,
        #     QtCore.Qt.MatchFlag.MatchCaseSensitive,
        # ]

        compose_flag = None
        for index, flag_entry in enumerate(flag_list):
            (flag_name, flag_val) = flag_entry
            # local_list_index = cls.getIndexForName(flag_name, is_name_only=True)
            # local_list_index -= 1
            # actual_flag_val = local_list[local_list_index]
            is_first = (index == 0)
            if is_first:
                compose_flag = flag_val
            else:
                compose_flag |= flag_val
        return compose_flag

and whenever the event “pressed” fired, I will call this function to update the flag:

    def searchOptionChanged(self, item:QStandardItem, is_checked: bool=False):
        item_txt = item.text()
        if not is_checked:
            try:
                del self.search_option_flag_checked_dict[item_txt]
                logger.info(f'Removing item {item_txt}')
            except KeyError as e:
                logger.info(f'Removing item {item_txt} causing exception: {e}')
        else:
            flag_dict = GUIMatchFlag.getFlagDict(is_name_only=True)
            search_flag_value = flag_dict[item_txt]
            new_search_flag_entry = {item_txt: search_flag_value}
            self.search_option_flag_checked_dict.update(new_search_flag_entry)

        flag_list = list(self.search_option_flag_checked_dict.items())
        logger.info(f'flag_list {flag_list}')
        self.search_option_flag = GUIMatchFlag.getQtComposeFlagValues(flag_list=flag_list)
        logger.info(f'search_option_flag: {self.search_option_flag}')

Here is my CheckableCombobox

from definition import Definitions as df

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from typing import Callable
from typing import Iterable
from collections import OrderedDict
import logging

logger = logging.getLogger(df.LOGGING_NAME)

class CheckableComboBox(QComboBox):
    # constructor
    def __init__(self, parent=None, item_pressed_action: Callable=None):
        super(CheckableComboBox, self).__init__(parent)
        # self.setMinimumWidth(200)
        self.setMinimumContentsLength(25)
        self.setSizeAdjustPolicy(QComboBox.AdjustToContentsOnFirstShow)
        self.view().pressed.connect(self.itemPressedAction)
        self.model = QStandardItemModel(self)
        # model.itemChanged.connect(item_pressed_action)
        self.item_pressed_action = item_pressed_action
        self.setModel(self.model)
        self.item_dict = None


    # action called when item get checked
    def do_action(self, item: QStandardItem, is_checked: bool=False):
        item_text = item.text()
        state_msg = (f'{item_text} is ' + "On" if is_checked else "Off")
        logger.info(state_msg)
        # when any item get pressed

    # def setOptionByList(self, flag_list: list[MatchFlag]):
    #     self.model()
    #     for flag in flag_list:
    #
    #         item: QStandardItem = self.model().itemFromIndex(index)
    #         is_checked = (item.checkState() == QtCore.Qt.CheckState.Checked)
    #         new_state = (QtCore.Qt.CheckState.Unchecked if is_checked else QtCore.Qt.CheckState.Checked)
    #         item.setCheckState(new_state)

    def addItems(self, item_list:Iterable, ip_str=None):
        self.item_dict = OrderedDict(item_list)
        for (k, v) in self.item_dict.items():
            self.addItem(k)
        first_index: QModelIndex = self.model.index(0, 0)
        first_item: QStandardItem = self.model.itemFromIndex(first_index)
        first_item.setSelectable(False)

    def itemPressedAction(self, index: QModelIndex):
        # getting the item
        item: QStandardItem = self.model.itemFromIndex(index)

        is_first_item = index.row() == 0
        if is_first_item:
            item.setCheckState(QtCore.Qt.CheckState.Unchecked)
            return

        item: QStandardItem = self.model.itemFromIndex(index)
        old_state = item.checkState()
        is_checked = (old_state == QtCore.Qt.CheckState.Checked)
        new_state = (QtCore.Qt.CheckState.Unchecked if is_checked else QtCore.Qt.CheckState.Checked)

        item.setCheckState(new_state)

        is_checked = (new_state == QtCore.Qt.CheckState.Checked)
        logger.info(f'{item.text()} pressed, is_checked: {is_checked}, old_state:{old_state}, new_state:{new_state}')
        # call the action
        has_external_action = (self.item_pressed_action is not None)
        if has_external_action:
            self.item_pressed_action(item, is_checked)
        else:
            self.do_action(item, is_checked)

What I don’t understand is although the values are identical, when it is passed to search function:

    def searchModelUsingName(self, search_text: QVariant, search_flag: Qt.MatchFlag):
        pattern = df.makePattern(search_text, flags=re.I)

        test_flags = GUIMatchFlag.MatchContains.value | GUIMatchFlag.MatchWrap.value | GUIMatchFlag.MatchRecursive.value
        # search_text = "GitExec"
        local_search_flag = Qt.MatchFlag.MatchContains | Qt.MatchFlag.MatchWrap | Qt.MatchFlag.MatchRecursive #::MatchContains | Qt::MatchWrap | Qt::MatchRecursive
        is_equal = (local_search_flag == test_flags)
        is_equal_search_flag = (local_search_flag == search_flag)
        logger.info(f'test_flags == local_search_flag => is_equal:{is_equal}, is_equal_search_flag:{is_equal_search_flag}')
        model: JsonModel = self.model
        is_valid_index = self.currentIndex().isValid()

        search_start_index: QModelIndex = (self.currentIndex() if is_valid_index else model.index(0, 0))
        next_matches = model.match(search_start_index,
                                   Qt.ItemDataRole.DisplayRole,
                                   search_text,
                                   1,
                                   local_search_flag
                                   )  # supposed to be QList<QModelIndex>, or QModelIndexList
        is_found = len(next_matches) > 0
        if not is_found:
            return

        select_model: QItemSelectionModel = self.selectionModel()
        select_list: list = self.selectionModel().selectedIndexes()
        select_model.clearSelection()
        found_index: QModelIndex = None
        for found_index in next_matches:
            item_found: TreeItem = found_index.internalPointer()
            item_info: ItemInfo = item_found.getItemInfoRecord()
            tree_root: dict = item_info.root
            key_list = item_info.key_list
            key_list.reverse()
            first_level_key = key_list[0]
            has_second_key = len(key_list) > 1
            second_level_key = None
            if has_second_key:
                second_level_key = key_list[1]

            first_parent_item: TreeItem = tree_root[first_level_key]
            first_parent_item_index: QModelIndex = model.getNodeByKey(first_level_key)
            is_expanding = not self.isExpanded(first_parent_item_index)
            if is_expanding:
                self.setExpanded(first_parent_item_index, True)
            # select_model.select(first_parent_item, QItemSelectionModel.Select | QItemSelectionModel.Rows)

            if has_second_key:
                second_parent_item: TreeItem = model.getNodeByKey(second_level_key, first_parent_item_index)
                is_expanding = not self.isExpanded(second_parent_item)
                if is_expanding:
                    self.setExpanded(second_parent_item, True)
                # select_model.select(second_parent_item, QItemSelectionModel.Select | QItemSelectionModel.Rows)
            # else:
            #     select_model.select(first_parent_item, QItemSelectionModel.Select | QItemSelectionModel.Rows)
            select_model.select(found_index, QItemSelectionModel.Select | QItemSelectionModel.Rows)

the dynamically composed flag is NOT equals to the hard-coded composed flag. In the above code, it always said False, though I flagged the same flags as hard-coded one. Could someone please help me to explain why this is the case? I am using Qt5

I was expecting the hard-coded ORred flags and the dynamic ORred flags to be equal

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật