Source code for ClearMap.gui.dialogs
# -*- coding: utf-8 -*-
"""
dialogs
=======
All the independent popup dialogs used by the GUI
"""
__author__ = 'Charly Rousseau <charly.rousseau@icm-institute.org>'
__license__ = 'GPLv3 - GNU General Public License v3 (see LICENSE.txt)'
__copyright__ = 'Copyright © 2022 by Charly Rousseau'
__webpage__ = 'https://idisco.info'
__download__ = 'https://github.com/ClearAnatomics/ClearMap'
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QLabel, QDialogButtonBox, QDialog, QHBoxLayout, QVBoxLayout, QFormLayout,
QPushButton, QLineEdit, QScrollArea, QGroupBox, QCheckBox, QComboBox)
from ClearMap.IO.assets_constants import DATA_CONTENT_TYPES
[docs]
class AboutDialog(QDialog):
def __init__(self, about_info, parent=None):
super().__init__(parent)
self.setWindowTitle(f"About {about_info.software_name}")
about_label = QLabel()
about_label.setOpenExternalLinks(True)
about_label.setTextInteractionFlags(Qt.TextBrowserInteraction)
about_label.setText(about_info.to_html())
layout = QVBoxLayout()
layout.addWidget(about_label)
self.setLayout(layout)
[docs]
class RenameChannelsDialog(QDialog):
def __init__(self, channels, parent=None):
super().__init__(parent)
self.setWindowTitle("Redefine channels")
self.channels = channels
self.new_channels = {}
# Set up the layout
layout = QVBoxLayout()
form_layout = QFormLayout()
# Create input fields for each channel
self.channel_inputs = {}
for channel in channels:
# channel_layout = QHBoxLayout()
name_label = QLabel(f"New name for '{channel}':")
name_input = QLineEdit()
form_layout.addRow(name_label, name_input)
data_type_label = QLabel("Data type:")
data_type_input = QComboBox()
data_type_input.addItems(DATA_CONTENT_TYPES)
form_layout.addRow(data_type_label, data_type_input)
self.channel_inputs[channel] = (name_input, data_type_input)
layout.addLayout(form_layout)
# Add OK and Cancel buttons
button_layout = QHBoxLayout()
ok_button = QPushButton("OK")
ok_button.clicked.connect(self.accept)
button_layout.addWidget(ok_button)
cancel_button = QPushButton("Cancel")
cancel_button.clicked.connect(self.reject)
button_layout.addWidget(cancel_button)
layout.addLayout(button_layout)
self.setLayout(layout)
self.show()
[docs]
def accept(self):
# Collect the new names and data types
for channel, (name_input, data_type_input) in self.channel_inputs.items():
new_name = name_input.text()
data_type = data_type_input.currentText()
self.new_channels[channel] = (new_name, data_type)
super().accept()
[docs]
def get_new_channels(self):
return self.new_channels
[docs]
class VerifyRenamingDialog(QDialog):
def __init__(self, files, parent=None):
super().__init__(parent)
self.setWindowTitle("Verify Renaming")
self.files = files
self.selected_files = []
# Set up the layout
layout = QVBoxLayout()
scroll_area = QScrollArea()
scroll_area.setWidgetResizable(True)
group_box = QGroupBox()
group_layout = QVBoxLayout()
# Create checkboxes for each file
self.checkboxes = {}
for old_name, new_name in files.items():
checkbox = QCheckBox(f"{old_name} -> {new_name}")
checkbox.setChecked(True)
self.checkboxes[(old_name, new_name)] = checkbox
group_layout.addWidget(checkbox)
group_box.setLayout(group_layout)
scroll_area.setWidget(group_box)
layout.addWidget(scroll_area)
# Add OK and Cancel buttons
button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
button_box.accepted.connect(self.accept)
button_box.rejected.connect(self.reject)
layout.addWidget(button_box)
self.setLayout(layout)
[docs]
def accept(self):
# Collect the selected files
for (old_name, new_name), checkbox in self.checkboxes.items():
if checkbox.isChecked():
self.selected_files.append((old_name, new_name))
super().accept()
[docs]
def get_selected_files(self):
return self.selected_files
[docs]
class ResourceTypeToFolderDialog(QDialog):
"""
Simple (k: v) editor for resource_type_to_folder.
- Left column: resource_type (read-only label).
- Right column: editable folder (relative path, may be empty '').
- Optional: checkbox to decide whether to migrate existing folders.
"""
def __init__(self, mapping: dict[str, str], parent=None):
super().__init__(parent)
self.setWindowTitle('Workspace resource sub-folders')
self.setModal(True)
self._rows: dict[str, QLineEdit] = {}
main_layout = QVBoxLayout(self)
info = QLabel('Configure where each resource type is stored, relative to the workspace directory.\n'
'Leave empty to keep files in the main experiment folder.')
info.setWordWrap(True)
main_layout.addWidget(info)
form = QFormLayout()
for rtype, folder in mapping.items():
label = QLabel(rtype)
label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
edit = QLineEdit(str(folder or ''))
edit.setPlaceholderText('<root>')
form.addRow(label, edit)
self._rows[rtype] = edit
main_layout.addLayout(form)
# Whether to migrate existing folders on disk
self.migrate_checkbox = QCheckBox('Move existing data into new folders (migrate on disk)')
self.migrate_checkbox.setChecked(False)
main_layout.addWidget(self.migrate_checkbox)
# Standard buttons
buttons = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
buttons.accepted.connect(self.accept)
buttons.rejected.connect(self.reject)
main_layout.addWidget(buttons)
[docs]
def result_mapping(self) -> dict[str, str]:
"""
Return the edited mapping {resource_type: folder_rel_path}.
"""
out: dict[str, str] = {}
for rtype, edit in self._edits.items():
val = edit.text().strip()
out[rtype] = val
return out
[docs]
def result(self) -> tuple[dict[str, str], bool]:
"""
Convenience: (mapping, migrate_flag).
"""
return self.result_mapping(), self.migrate_checkbox.isChecked()