Source code for radioviz.views.image_metadata_window

#  Copyright 2026 European Union
#  Author: Bulgheroni Antonio (antonio.bulgheroni@ec.europa.eu)
#  SPDX-License-Identifier: EUPL-1.2
"""
View for displaying image metadata in a read-only window.

This module provides a simple sub-window that presents metadata as
label/value pairs in a table, allowing users to inspect tags without
editing them.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Optional

from PySide6.QtCore import Qt
from PySide6.QtWidgets import (
    QAbstractItemView,
    QApplication,
    QHBoxLayout,
    QHeaderView,
    QLineEdit,
    QPushButton,
    QTableWidget,
    QTableWidgetItem,
    QVBoxLayout,
    QWidget,
)

from radioviz.views.sub_window import SubWindow

if TYPE_CHECKING:
    from radioviz.controllers.image_metadata_window_controller import ImageMetadataWindowController


[docs] class ImageMetadataWindow(SubWindow['ImageMetadataWindowController']): """ Sub-window that displays image metadata entries. The view shows metadata in a two-column, read-only table with tag labels and their corresponding values. """ def __init__(self, controller: 'ImageMetadataWindowController', parent: Optional[QWidget] = None) -> None: """ Initialize the metadata window view. :param controller: Controller providing metadata entries. :type controller: radioviz.controllers.image_metadata_window_controller.ImageMetadataWindowController :param parent: Optional parent widget. :type parent: Optional[QWidget] """ super().__init__(controller=controller, parent=parent) container = QWidget(self) layout = QVBoxLayout(container) layout.setContentsMargins(6, 6, 6, 6) controls_layout = QHBoxLayout() self.filter_input = QLineEdit(container) self.filter_input.setPlaceholderText('Filter tags...') self.copy_value_button = QPushButton('Copy value', container) self.copy_value_button.clicked.connect(self._copy_selected_value) controls_layout.addWidget(self.filter_input) controls_layout.addWidget(self.copy_value_button) self.table = QTableWidget(container) self.table.setColumnCount(3) self.table.setHorizontalHeaderLabels(['Tag', 'Name', 'Value']) self.table.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers) self.table.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows) self.table.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection) self.table.verticalHeader().setVisible(False) self.table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeMode.ResizeToContents) self.table.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.ResizeToContents) self.table.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeMode.Stretch) self.table.setAlternatingRowColors(True) self._populate_table() self.filter_input.textChanged.connect(self._apply_filter) layout.addLayout(controls_layout) layout.addWidget(self.table) self.setWidget(container) self.setWindowTitle(self.controller.name) self.resize(460, 320)
[docs] def _populate_table(self) -> None: """ Populate the table with metadata entries from the controller. :return: None :rtype: None """ entries = self.controller.metadata_items() if not entries: entries = [('', 'No metadata available', '')] self.table.setRowCount(len(entries)) for row, (tag, name, value) in enumerate(entries): tag_item = QTableWidgetItem(tag) name_item = QTableWidgetItem(name) value_item = QTableWidgetItem(value) tag_item.setFlags(tag_item.flags() & ~Qt.ItemFlag.ItemIsEditable) name_item.setFlags(name_item.flags() & ~Qt.ItemFlag.ItemIsEditable) value_item.setFlags(value_item.flags() & ~Qt.ItemFlag.ItemIsEditable) if value: value_item.setToolTip(value) self.table.setItem(row, 0, tag_item) self.table.setItem(row, 1, name_item) self.table.setItem(row, 2, value_item) self._apply_filter(self.filter_input.text())
[docs] def _apply_filter(self, text: str) -> None: """ Filter table rows based on the provided text. :param text: Filter text to apply. :type text: str :return: None :rtype: None """ needle = text.strip().lower() for row in range(self.table.rowCount()): if not needle: self.table.setRowHidden(row, False) continue tag_item = self.table.item(row, 0) name_item = self.table.item(row, 1) value_item = self.table.item(row, 2) haystack = ' '.join( [ tag_item.text() if tag_item else '', name_item.text() if name_item else '', value_item.text() if value_item else '', ] ).lower() self.table.setRowHidden(row, needle not in haystack)
[docs] def _copy_selected_value(self) -> None: """ Copy the selected row's value to the clipboard. :return: None :rtype: None """ row = self.table.currentRow() if row < 0: return item = self.table.item(row, 2) if item is None: return QApplication.clipboard().setText(item.text())