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())