コード例 #1
0
 def _load_sprite_data_from_anime(anime_path) -> RelevantSpriteData:
     common_module_service = locator.get_scoped("CommonModuleService")
     template = locator.get_scoped(
         "ModuleService").get_common_module_template("Sprite Bin Data")
     module = common_module_service.open_common_module(template, anime_path)
     entry = module.entries[0]
     return RelevantSpriteData(entry)
コード例 #2
0
ファイル: supports_service.py プロジェクト: thane98/paragon
 def open_support_conversation_for_characters(self, character1, character2):
     part1 = character1["PID"].value[4:]
     part2 = character2["PID"].value[4:]
     path1 = "m/%s_%s.bin.lz" % (part1, part2)
     path2 = "m/%s_%s.bin.lz" % (part2, part1)
     archive = self._try_open_conversation(path1)
     if not archive:
         archive = self._try_open_conversation(path2)
         if not archive:
             archive = MessageArchive()
             archive.title = "MESS_ARCHIVE_%s_%s" % (part1, part2)
             archive.insert_or_overwrite_message(
                 "MID_支援_%s_%s_C" % (part1, part2), "")
             archive.insert_or_overwrite_message(
                 "MID_支援_%s_%s_B" % (part1, part2), "")
             archive.insert_or_overwrite_message(
                 "MID_支援_%s_%s_A" % (part1, part2), "")
             archive.insert_or_overwrite_message(
                 "MID_支援_%s_%s_S" % (part1, part2), "")
             locator.get_scoped(
                 "OpenFilesService").register_or_overwrite_message_archive(
                     path1, archive)
     editor_title = "Support - %s and %s" % (character1.get_display_name(),
                                             character2.get_display_name())
     editor = FE14ConversationEditor(archive,
                                     title=editor_title,
                                     owner=self,
                                     is_support=True)
     self._conversation_editors.append(editor)
     editor.show()
コード例 #3
0
 def import_values(self, values_json: Any):
     if not values_json:
         self.value = None
     else:
         self.value = values_json
         locator.get_scoped("Driver").register_unresolved_import_reference(
             self)
コード例 #4
0
 def get_display_name(self, fid: str):
     if fid == "FID_username":
         return self.get_avatar_name()
     else:
         portrait_entry = locator.get_scoped("PortraitService").get_portrait_entry_for_fid(fid, "st")
         if not portrait_entry:
             portrait_entry = locator.get_scoped("PortraitService").get_portrait_entry_for_fid("FID_フードマン", "st")
     return portrait_entry["Name"].value
コード例 #5
0
ファイル: open_files_model.py プロジェクト: thane98/paragon
    def close(self, index):
        (key, value) = self._get_elem(index)
        logging.info("Closing file " + key)
        archive = value.file

        self.beginRemoveRows(QModelIndex(), index, index + 1)
        locator.get_scoped("Driver").close_archive(archive)
        self.endRemoveRows()
コード例 #6
0
 def get_portraits_for_fid(self, fid: str, mode: str = "st"):
     portrait_service = locator.get_scoped("PortraitService")
     if fid == "FID_username":
         portraits = locator.get_scoped("PortraitService").get_avatar_portraits(self.avatar_is_female())
     else:
         portraits = portrait_service.get_portraits_for_fid(fid, mode)
         if not portraits:
             portraits = portrait_service.get_portraits_for_fid("FID_フードマン", mode)
     return portraits
コード例 #7
0
    def get_sprite_for_character(self, character: PropertyContainer,
                                 team: int) -> Optional[QPixmap]:
        assets_service = locator.get_scoped("AssetsService")
        class_module: TableModule = locator.get_scoped(
            "ModuleService").get_module("Classes")
        sprite_file_name = get_sprite_file_name_from_team(team)
        class_id = character[_CLASS_KEY].value
        job = class_module.entries[class_id]
        jid = job[_JID_KEY].value
        aid = character[_AID_KEY].value
        if not aid:
            aid = jid

        unique_path = _UNIQUE_FILE_TEMPLATE % (jid[4:], aid[4:],
                                               sprite_file_name)
        head_dir_path = _HEAD_FILE_TEMPLATE % (aid[4:], sprite_file_name)
        body_dir_path = _BODY_FILE_TEMPLATE % (jid[4:], sprite_file_name)
        body_anime_path = _BODY_ANIME_TEMPLATE % jid[4:]

        if unique_path in _CACHE:
            return _CACHE[unique_path].toqpixmap()
        if head_dir_path + body_dir_path in _CACHE:
            return _CACHE[head_dir_path + body_dir_path].toqpixmap()

        unique_texture: Optional[Dict[str, Texture]] = assets_service.load_bch(
            unique_path)
        if unique_texture:
            unique_texture_key = next(iter(unique_texture), None)
            if unique_texture_key:
                result = self._assemble_unique_sprite(
                    unique_texture[unique_texture_key])
                if result:
                    _CACHE[unique_path] = result
                return result.toqpixmap()
        head_texture: Optional[Dict[str, Texture]] = assets_service.load_bch(
            head_dir_path)
        if not head_texture:
            return None
        body_texture: Optional[Dict[str, Texture]] = assets_service.load_bch(
            body_dir_path)
        if not body_texture:
            return None

        relevant_sprite_data = self._load_sprite_data_from_anime(
            body_anime_path)
        head_texture_key = next(iter(head_texture), None)
        body_texture_key = next(iter(body_texture), None)
        if head_texture_key and body_texture_key:
            result = self._assemble_sprite(head_texture[head_texture_key],
                                           body_texture[body_texture_key],
                                           relevant_sprite_data)
            if result:
                _CACHE[unique_path] = result
            return result.toqpixmap()
        else:
            return None
コード例 #8
0
def _open_person(chapter):
    target_file = "%s.bin.lz" % chapter["CID"].value[4:]
    target_path = search_all_routes_for_file("/GameData/Person/", target_file)
    if not target_path:
        return None
    module_service = locator.get_scoped("ModuleService")
    common_module_service = locator.get_scoped("CommonModuleService")
    module_template = module_service.get_common_module_template("Person")
    module = common_module_service.open_common_module(module_template,
                                                      target_path)
    module_service.set_module_in_use(module)
    return module
コード例 #9
0
ファイル: driver.py プロジェクト: thane98/paragon
    def save():
        services_to_save = [
            locator.get_scoped("DedicatedEditorsService"),
            locator.get_scoped("ModuleService"),
            locator.get_scoped("CommonModuleService"),
            locator.get_scoped("OpenFilesService")
        ]

        success = True
        for service in services_to_save:
            if not service.save():
                success = False
        return success
コード例 #10
0
def _open_map_config(chapter):
    truncated_cid = chapter["CID"].value[4:]
    target_path = "/map/config/%s.bin" % truncated_cid
    open_files_service = locator.get_scoped("OpenFilesService")
    if not open_files_service.exists(target_path):
        return None
    module_service = locator.get_scoped("ModuleService")
    common_module_service = locator.get_scoped("CommonModuleService")
    module_template = module_service.get_common_module_template("Map Config")
    module = common_module_service.open_common_module(module_template,
                                                      target_path)
    module_service.set_module_in_use(module)
    return module
コード例 #11
0
ファイル: main_window.py プロジェクト: thane98/paragon
 def _on_import_triggered(self):
     file_name, ok = QFileDialog.getOpenFileName(self,
                                                 "Select file.",
                                                 filter="*.json")
     if ok:
         try:
             locator.get_scoped("Driver").import_from_json(file_name)
             self.statusbar.showMessage("Import succeeded!", 5000)
         except:
             logging.exception("An error occurred during importing.")
             self.error_dialog = ErrorDialog(
                 "Importing failed. See the log for details.")
             self.error_dialog.show()
             self.statusbar.showMessage("Importing failed.", 5000)
コード例 #12
0
ファイル: main_window.py プロジェクト: thane98/paragon
    def _set_view_models(self):
        module_service = locator.get_scoped("ModuleService")
        dedicated_editors_service = locator.get_scoped(
            "DedicatedEditorsService")
        self.proxy_model = ModuleFilterModel()
        self.open_file_model = OpenFilesModel()

        self.proxy_model.setSourceModel(module_service.get_module_model())
        self.module_list_view.setModel(self.proxy_model)
        self.editors_list_view.setModel(
            dedicated_editors_service.get_dedicated_editors_model())
        self.file_list_view.setModel(self.open_file_model)
        self.module_list_view.setHeaderHidden(True)
        self.module_list_view.setEditTriggers(
            QtWidgets.QAbstractItemView.NoEditTriggers)
コード例 #13
0
ファイル: loading_state.py プロジェクト: thane98/paragon
 def run(self):
     locator.clear_scoped_services()
     try:
         locator.register_scoped("Driver", Driver(self.project))
         locator.register_scoped("OpenFilesService", OpenFilesService(self.project.filesystem))
         locator.register_scoped("ModuleDataService", ModuleDataService())
         locator.register_scoped("ModuleService", ModuleService(self.project))
         locator.register_scoped("CommonModuleService", CommonModuleService())
         locator.register_scoped("DedicatedEditorsService", DedicatedEditorsService(self.project.game))
         locator.get_scoped("ModuleService").load_files_and_generate_model()
         locator.get_static("SettingsService").save(self.project)
         self.over.emit()
     except Exception as e:
         logging.exception(e)
         self.failed.emit()
コード例 #14
0
ファイル: ai_data_service.py プロジェクト: thane98/paragon
    def _try_load_ai_data(self):
        self._loaded = True
        open_files_service = locator.get_scoped("OpenFilesService")
        try:
            bin_archive = open_files_service.open(_AI_DATA_PATH)
            reader = BinArchiveReader(bin_archive)
            ac_ptr = reader.read_internal_pointer()
            mi_ptr = reader.read_internal_pointer()
            at_ptr = reader.read_internal_pointer()
            mv_ptr = reader.read_internal_pointer()
            ac_table = self._read_null_terminated_list(reader, ac_ptr)
            mi_table = self._read_null_terminated_list(reader, mi_ptr)
            at_table = self._read_null_terminated_list(reader, at_ptr)
            mv_table = self._read_null_terminated_list(reader, mv_ptr)

            ac_labels = self._read_mapped_pointers(reader, ac_table)
            mi_labels = self._read_mapped_pointers(reader, mi_table)
            at_labels = self._read_mapped_pointers(reader, at_table)
            mv_labels = self._read_mapped_pointers(reader, mv_table)

            self.ac = ac_labels
            self.mi = mi_labels
            self.at = at_labels
            self.mv = mv_labels
        except:
            logging.exception("Unable to load AI data.")
コード例 #15
0
 def load(self):
     if not self.loaded:
         open_files_service = locator.get_scoped("OpenFilesService")
         for dialogue in self.dialogues:
             archive = open_files_service.open_message_archive(dialogue.path)
             self.archives[dialogue] = archive
         self.loaded = True
コード例 #16
0
    def open_common_module(self, module_template: Module,
                           file_path: str) -> Module:
        # First, check the cache.
        key = (module_template, file_path)
        if key in self._open_modules:
            return self._open_modules[key]

        # Not in the cache. Need to open the selected file and create a module copy.
        # First, convert the file path to one that starts at the ROM root.
        open_files_service: OpenFilesService = locator.get_scoped(
            "OpenFilesService")
        valid_path = open_files_service.to_valid_path_in_filesystem(file_path)
        if not valid_path:
            raise ValueError

        # Create the module copy and attach to the target file.
        module = module_template.duplicate()
        archive = None  # TODO: This should be a method of the Module class.
        try:
            archive = open_files_service.open(valid_path)
            module.attach_to(archive)
        except Exception as ex:
            logging.exception("Failed to attach to module.")
            open_files_service.close_archive(archive)
            raise ex
        self._open_modules[key] = module
        return module
コード例 #17
0
    def get_avatar_portraits(self, is_female: bool, mode: str = "st"):
        if self._cached_avatar and self._cached_avatar_is_female == is_female:
            return self._cached_avatar

        assets_service = locator.get_scoped("AssetsService")
        if is_female:
            portraits = self.get_portraits_from_arc(
                _FEMALE_AVATAR_PORTRAIT_FILE)
            hair = assets_service.load_bch(_FEMALE_AVATAR_HAIR_FILE)
        else:
            portraits = self.get_portraits_from_arc(_MALE_AVATAR_PORTRAIT_FILE)
            hair = assets_service.load_bch(_MALE_AVATAR_HAIR_FILE)
        if not portraits or not hair:
            portraits = self.get_portraits_for_fid("FID_フードマン", mode)
        else:
            hair_texture_key = next(iter(hair), None)
            if hair_texture_key:
                hair_texture: Texture = hair[hair_texture_key]
                for portrait in portraits.values():
                    if portrait != "汗" and portrait != "照":
                        portrait.raw_image().paste(hair_texture.raw_image(),
                                                   (0, 0),
                                                   hair_texture.raw_image())
        self._cached_avatar = portraits
        self._cached_avatar_is_female = is_female
        return portraits
コード例 #18
0
ファイル: main_window.py プロジェクト: thane98/paragon
 def save(self):
     driver = locator.get_scoped("Driver")
     if driver.save():
         self.statusbar.showMessage("Save succeeded!", 5000)
     else:
         self.statusbar.showMessage("Save failed. See the log for details.",
                                    5000)
コード例 #19
0
    def __init__(self, is_person=False, parent=None):
        super().__init__(parent)
        self.is_person = is_person
        self.module: TableModule = locator.get_scoped("ModuleService").get_module("Characters")
        self.proxy_model = QSortFilterProxyModel()
        self.proxy_model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.proxy_model.setSourceModel(self.module.entries_model)
        self.characters_list_view.setModel(self.proxy_model)
        self.selection: Optional[PropertyContainer] = None

        self.character_details_form_1 = PropertyForm(self.module.element_template, category="character_description_1")
        self.character_details_form_contents_1.setLayout(self.character_details_form_1)
        self.character_details_form_2 = PropertyForm(self.module.element_template, category="character_description_2")
        self.character_details_form_contents_2.setLayout(self.character_details_form_2)
        self.character_details_form_2.fix_editor_width(100)
        self.stats_editor = MergedStatsEditor(["Bases", "Growths", "Modifiers", "Penalties", "Bonuses"])
        self.stats_form = PropertyForm(self.module.element_template, category="stats")
        self.stats_layout.addWidget(self.stats_editor)
        self.stats_layout.addLayout(self.stats_form)
        self.skills_form = PropertyForm(self.module.element_template, category="skills", sort_editors=True)
        self.skills_contents.setLayout(self.skills_form)
        self.flags_editor = MergedFlagsEditor(
            ["Bitflags (1)", "Bitflags (2)", "Bitflags (3)", "Bitflags (4)"],
            self.module.element_template
        )
        self.flags_editor_2 = MergedFlagsEditor(
            ["Bitflags (5)", "Bitflags (6)", "Bitflags (7)", "Bitflags (8)"],
            self.module.element_template
        )
        self.misc_form = PropertyForm(self.module.element_template, category="misc")
        self.misc_layout.addWidget(self.flags_editor)
        self.misc_layout.addWidget(self.flags_editor_2)
        self.misc_layout.addLayout(self.misc_form)
        self.ids_form = PropertyForm(self.module.element_template, category="ids")
        self.ids_tab.setLayout(self.ids_form)
        self.classes_form = PropertyForm(self.module.element_template, category="classes", sort_editors=True)
        self.classes_tab.setLayout(self.classes_form)
        if not self.is_person:
            self.dialogue_tab = DialogueEditor()
            self.supports_tab = QWidget()
            self.supports_layout = QHBoxLayout()
            self.supports_widget = FE14SupportWidget()
            self.supports_scroll = QScrollArea()
            self.supports_scroll_contents = QWidget()
            self.supports_scroll.setWidget(self.supports_scroll_contents)
            self.supports_scroll.setWidgetResizable(True)
            self.supports_layout.addWidget(self.supports_widget)
            self.supports_layout.addWidget(self.supports_scroll)
            self.supports_tab.setLayout(self.supports_layout)
            self.supports_form = PropertyForm(self.module.element_template, category="supports")
            self.supports_scroll_contents.setLayout(self.supports_form)
            self.tab_widget.addTab(self.supports_tab, "Supports")
            self.tab_widget.addTab(self.dialogue_tab, "Dialogue")

        self.context_menu = QMenu(self)
        self.context_menu.addActions([self.action_add, self.action_remove, self.action_copy_to])
        self.clear_selection_shortcut = QShortcut(QKeySequence.Cancel, self)

        self._install_signals()
        self._clear()
コード例 #20
0
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.pushButton_2.setEnabled(False)
        self.pushButton_3.setEnabled(False)
        self.comboBox.setEnabled(False)
        self.setWindowTitle("Support Editor")
        self.setWindowIcon(QIcon("paragon.ico"))
        self.error_dialog = None

        module_service = locator.get_scoped("ModuleService")
        self.service = None
        self.current_character = None
        self.current_supports = None
        self.current_support = None
        self.model = module_service.get_module("Characters").entries_model
        self.proxy_model = QSortFilterProxyModel(self)
        self.proxy_model.setSourceModel(self.model)
        self.proxy_model.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
        self.characters_list_view.setModel(self.proxy_model)

        self.characters_list_view.selectionModel().currentRowChanged.connect(self._update_selection)
        self.listWidget.selectionModel().currentRowChanged.connect(self._on_target_character_changed)
        self.listWidget_2.selectionModel().currentRowChanged.connect(self._update_support_selection)
        self.lineEdit.textChanged.connect(self._update_filter)
        self.pushButton_2.clicked.connect(self._on_add_support_pressed)
        self.pushButton_3.clicked.connect(self._on_remove_support_pressed)
        self.comboBox.currentIndexChanged.connect(self._on_support_type_changed)
コード例 #21
0
 def _get_model_index_of_character(self, character):
     module_service = locator.get_scoped("ModuleService")
     entries = module_service.get_module("Characters").entries
     for i in range(0, len(entries)):
         if entries[i] == character:
             return self.model.index(i)
     return QModelIndex()
コード例 #22
0
 def _get_model_index_of_character(self, character):
     driver = locator.get_scoped("Driver")
     entries = driver.modules["Characters"].entries
     for i in range(0, len(entries)):
         if entries[i] == character:
             return self.model.index(i)
     return QModelIndex()
コード例 #23
0
 def get_blush_and_sweat_coordinates(self, fid: str, mode: str):
     if fid == "FID_username":
         if self.avatar_is_female():
             fid = "FID_マイユニ_女2_顔A"
         else:
             fid = "FID_マイユニ_男1_顔B"
     return locator.get_scoped("PortraitService").get_blush_and_sweat_coordinates(fid, mode)
コード例 #24
0
    def __init__(self):
        open_files_service = locator.get_scoped("OpenFilesService")
        self.archive = open_files_service.open("GameData/GameData.bin.lz")
        self.editor = FE14SupportEditor()

        if self.archive:
            open_files_service.set_archive_in_use(self.archive)
コード例 #25
0
 def __init__(self):
     super().__init__()
     self.chapter_data = None
     module_service = locator.get_scoped("ModuleService")
     config_module = module_service.get_common_module_template("Map Config")
     self.module = module_service.get_module("Chapters")
     self.text_data_widget = FE14ChapterTextDataWidget()
     self.header_scroll, self.header_property_form = PropertyForm.create_with_scroll(
         self.module.element_template)
     self.config_scroll, self.config_property_form = PropertyForm.create_with_scroll(
         config_module.element_template)
     self.header_property_form.editors["CID"].setEnabled(False)
     self.header_property_form.editors["Key (CID)"].setEnabled(False)
     self.vertical_layout = QVBoxLayout(parent=self)
     self.splitter = QSplitter(parent=self)
     self.splitter.setOrientation(QtCore.Qt.Vertical)
     self.splitter2 = QSplitter(parent=self)
     self.splitter2.setOrientation(QtCore.Qt.Horizontal)
     self.splitter.addWidget(self.text_data_widget)
     self.splitter.addWidget(self.splitter2)
     self.splitter2.addWidget(self.header_scroll)
     self.splitter2.addWidget(self.config_scroll)
     self.vertical_layout.addWidget(self.splitter)
     self.scroll_content = QWidget()
     self.scroll_content.setLayout(self.vertical_layout)
     self.setWidget(self.scroll_content)
     self.setWidgetResizable(True)
コード例 #26
0
 def __init__(self):
     super().__init__()
     open_files_service = locator.get_scoped("OpenFilesService")
     self.archive = open_files_service.open("GameData/GameData.bin.lz")
     self.dialogues = self._read_dialogue_data()
     self.archives = {}
     self.loaded = False
コード例 #27
0
 def load_background() -> Optional[QPixmap]:
     assets_service = locator.get_scoped("AssetsService")
     arc = assets_service.load_arc("/effect/Tlp_Ev_t001.arc.lz")
     if not arc or "model.bch" not in arc:
         return None
     image: QImage = arc["model.bch"].image()
     return QPixmap.fromImage(image).copy(56, 8, 400, 240)
コード例 #28
0
ファイル: icon_service.py プロジェクト: thane98/paragon
    def _load_icons(self):
        if self._loaded:
            return
        self._loaded = True
        assets_service = locator.get_scoped("AssetsService")
        icons: Optional[Dict[str, Texture]] = assets_service.load_bch(
            "/icon/Icon.bch.lz")
        if not icons:
            return

        if _SKILL_TEXTURE_KEY in icons:
            skill_icons_texture = icons[_SKILL_TEXTURE_KEY]
            icon_width, icon_height = _SKILL_ICON_DIMENSIONS
            self._skill_icons = self._slice(skill_icons_texture, icon_width,
                                            icon_height)
        if _SKILL2_TEXTURE_KEY in icons:
            skill2_icons_texture = icons[_SKILL2_TEXTURE_KEY]
            icon_width, icon_height = _SKILL_ICON_DIMENSIONS
            self._skill_icons.extend(
                self._slice(skill2_icons_texture, icon_width, icon_height))
        if _ITEM_TEXTURE_KEY in icons:
            item_icons_texture = icons[_ITEM_TEXTURE_KEY]
            icon_width, icon_height = _ITEM_ICON_DIMENSIONS
            self._item_icons = self._slice(item_icons_texture, icon_width,
                                           icon_height)
        if _FACTION_TEXTURE_KEY in icons:
            faction_icons_texture = icons[_FACTION_TEXTURE_KEY]
            icon_width, icon_height = _FACTION_ICON_DIMENSIONS
            self._faction_icons = self._slice(faction_icons_texture,
                                              icon_width, icon_height)
            real_faction_icons = []
            for i in range(0, len(self._faction_icons)):
                if i not in [5, 11, 17]:
                    real_faction_icons.append(self._faction_icons[i])
            self._faction_icons = real_faction_icons
コード例 #29
0
    def _on_add_chapter_triggered(self):
        # Get the chapter to use as a base
        choices = self._create_chapter_choice_list()
        (choice, ok) = QInputDialog.getItem(self, "Select Base Chapter",
                                            "Base Chapter", choices)
        if not ok:
            return
        source_chapter = self._get_chapter_from_choice(choice, choices)

        # Get the desired CID.
        (desired_cid,
         ok) = QInputDialog.getText(self, "Enter a CID for the new chapter.",
                                    "CID")
        if not ok:
            return

        # Validate the CID.
        service = locator.get_scoped("ChapterService")
        if service.is_cid_in_use(desired_cid):
            self.error_dialog = ErrorDialog("The CID \"" + desired_cid +
                                            "\" is already in use.")
            self.error_dialog.show()
            return
        if not desired_cid.startswith("CID_"):
            self.error_dialog = ErrorDialog("CID must start with the \"CID_\"")
            self.error_dialog.show()
            return

        # Create the chapter
        service.create_chapter(source_chapter, desired_cid)
コード例 #30
0
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.pushButton_2.setEnabled(False)
        self.pushButton_3.setEnabled(False)
        self.comboBox.setEnabled(False)
        self.setWindowTitle("Support Editor")
        self.setWindowIcon(QIcon("paragon.ico"))

        driver = locator.get_scoped("Driver")
        self.service = None
        self.current_character = None
        self.current_supports = None
        self.current_support = None
        self.model = driver.modules["Characters"].entries_model
        self.characters_list_view.setModel(self.model)

        self.characters_list_view.selectionModel().currentRowChanged.connect(
            self._update_selection)
        self.listWidget.selectionModel().currentRowChanged.connect(
            self._on_target_character_changed)
        self.listWidget_2.selectionModel().currentRowChanged.connect(
            self._update_support_selection)
        self.pushButton_2.clicked.connect(self._on_add_support_pressed)
        self.pushButton_3.clicked.connect(self._on_remove_support_pressed)
        self.comboBox.currentIndexChanged.connect(
            self._on_support_type_changed)