# Copyright 2026 European Union
# Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
# SPDX-License-Identifier: EUPL-1.2
"""Dialog for selecting filter models to add."""
from __future__ import annotations
from PySide6.QtCore import QSortFilterProxyModel, Qt
from PySide6.QtGui import QStandardItem, QStandardItemModel
from PySide6.QtWidgets import (
QDialog,
QHBoxLayout,
QLabel,
QLineEdit,
QListView,
QPushButton,
QVBoxLayout,
QWidget,
)
[docs]
class AddModelDialog(QDialog):
"""Dialog presenting a selectable list of models."""
def __init__(
self,
advertised_models: list[str],
all_models: list[str],
parent: QWidget | None = None,
) -> None:
super().__init__(parent)
self.setWindowTitle('Add Model Filter')
# Combine models, prioritizing advertised ones
self._advertised_set = set(advertised_models)
# Filter out duplicates from all_models that are already in advertised
others = sorted([m for m in all_models if m not in self._advertised_set])
# Create model items
self._model = QStandardItemModel()
# Add advertised models first (Bold)
for name in advertised_models:
item = QStandardItem(name)
font = item.font()
font.setBold(True)
item.setFont(font)
self._model.appendRow(item)
# Add other models
for name in others:
item = QStandardItem(name)
self._model.appendRow(item)
self._proxy_model = QSortFilterProxyModel(self)
self._proxy_model.setSourceModel(self._model)
self._proxy_model.setFilterCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
self.list_view = QListView()
self.list_view.setModel(self._proxy_model)
self.list_view.setSelectionMode(QListView.SelectionMode.SingleSelection)
self.list_view.setEditTriggers(QListView.EditTrigger.NoEditTriggers)
self.filter_edit = QLineEdit()
self.filter_edit.setClearButtonEnabled(True)
self.filter_edit.setPlaceholderText('Filter models...')
self._prompt = QLabel('Select a model to add as a filter.')
self._prompt.setWordWrap(True)
self.add_button = QPushButton('Add')
self.add_button.setEnabled(False)
self.cancel_button = QPushButton('Cancel')
self._setup_layout()
self._wire_signals()
self.resize(300, 400)
[docs]
def selected_model(self) -> str | None:
"""Return the currently selected model name."""
indexes = self.list_view.selectionModel().selectedIndexes()
if not indexes:
return None
# Map proxy index to source index
proxy_index = indexes[0]
source_index = self._proxy_model.mapToSource(proxy_index)
return self._model.itemFromIndex(source_index).text()
def _setup_layout(self) -> None:
buttons = QHBoxLayout()
buttons.addStretch(1)
buttons.addWidget(self.cancel_button)
buttons.addWidget(self.add_button)
layout = QVBoxLayout()
layout.addWidget(self._prompt)
layout.addWidget(self.filter_edit)
layout.addWidget(self.list_view)
layout.addLayout(buttons)
self.setLayout(layout)
def _wire_signals(self) -> None:
self.list_view.selectionModel().selectionChanged.connect(self._update_add_enabled)
self.list_view.doubleClicked.connect(lambda *_: self.accept())
self.add_button.clicked.connect(self.accept)
self.cancel_button.clicked.connect(self.reject)
self.filter_edit.textChanged.connect(self._proxy_model.setFilterFixedString)
def _update_add_enabled(self, *_: object) -> None:
has_selection = bool(self.list_view.selectionModel().selectedIndexes())
self.add_button.setEnabled(has_selection)