# Copyright 2026 European Union
# Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
# SPDX-License-Identifier: EUPL-1.2
"""Dialog for selecting processors to add to the pipeline.
:Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
:Description: Display available processors in a list and return the selected names.
"""
from __future__ import annotations
from PySide6.QtCore import QSortFilterProxyModel, QStringListModel, Qt
from PySide6.QtGui import QFontMetrics
from PySide6.QtWidgets import (
QDialog,
QHBoxLayout,
QLabel,
QLineEdit,
QListView,
QPushButton,
QVBoxLayout,
QWidget,
)
[docs]
class AddProcessorDialog(QDialog):
"""Dialog presenting a selectable list of processors."""
def __init__(self, processors: list[str], parent: QWidget | None = None) -> None:
super().__init__(parent)
self.setWindowTitle('Add Processor')
self._model = QStringListModel(processors)
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.ExtendedSelection)
self.filter_edit = QLineEdit()
self.filter_edit.setClearButtonEnabled(True)
self.filter_edit.setPlaceholderText('Filter processors...')
self._processors = processors
self._prompt = QLabel('Select one or more processors to append to the pipeline')
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._adjust_width()
[docs]
def selected_names(self) -> list[str]:
"""Return the currently selected processor names."""
indexes = self.list_view.selectionModel().selectedIndexes()
return [idx.data() for idx in indexes]
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 _adjust_width(self) -> None:
metrics = QFontMetrics(self.list_view.font())
longest = 0
for name in self._processors:
longest = max(longest, metrics.horizontalAdvance(name))
padding = metrics.horizontalAdvance('W') * 4
minimum = longest + padding
minimum = max(minimum, self._prompt.sizeHint().width())
minimum = max(minimum, self.filter_edit.sizeHint().width())
if minimum < 200:
minimum = 200
self.list_view.setMinimumWidth(minimum)
self.setMinimumWidth(minimum + 80)
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)