Source code for IQM_Vis.UI.layout

'''
UI create layout
'''
# Author: Matt Clifford <matt.clifford@bristol.ac.uk>
# License: BSD 3-Clause License

import os
import warnings
from PyQt6.QtWidgets import (QMainWindow,
                             QGridLayout,
                             QHBoxLayout,
                             QVBoxLayout,
                             QTabWidget,
                             QWidget)
from IQM_Vis.UI import utils

# sub class used by IQM_Vis.main.make_app to initialise layout of the UI
# uses widgets from IQM_Vis.widgets.app_widgets
# class layout(QMainWindow):
[docs]class layout(QMainWindow):
[docs] def __init__(self, **kwargs): super().__init__()
[docs] def init_layout(self): self.tabs = {} self._init_generic_layout() self.main_widget = QWidget() self.main_widget.setLayout(self.main_layout) self.setCentralWidget(self.main_widget) self.show() return self
def _init_generic_layout(self): ''' place all the widgets in the window ''' # sizes im_width = 10 im_height = 4 # save window tabs to self self.tabs = {} '''image rows displaying image, metric graphs and metric images''' image_layouts = QVBoxLayout() metric_layouts = QVBoxLayout() graph_layouts = QVBoxLayout() for i in self.widget_row: '''image and transformed image''' image_layout = QHBoxLayout() for image_name in self.widget_row[i]['images']: single_image = QVBoxLayout() single_image.addWidget(self.widget_row[i]['images'][image_name]['label']) single_image.addWidget(self.widget_row[i]['images'][image_name]['data']) image_layout.addLayout(single_image) image_layouts.addLayout(image_layout) image_layouts.addStretch() '''metric images''' metric_layout = QHBoxLayout() for metric_name in self.widget_row[i]['metric_images']: single_metric = QVBoxLayout() single_metric.addWidget(self.widget_row[i]['metric_images'][metric_name]['label']) single_metric.addWidget(self.widget_row[i]['metric_images'][metric_name]['data']) single_metric.addStretch() metric_layout.addLayout(single_metric) metric_layout.addStretch() metric_layouts.addLayout(metric_layout) metric_layouts.addStretch() '''graphs''' self.tabs['graph'] = QTabWidget() # '''metrics graphs''' metric_bar = QVBoxLayout() metric_bar.addWidget(self.widget_row[i]['metrics']['info']['label']) metric_bar.addWidget(self.widget_row[i]['metrics']['info']['data']) utils.add_layout_to_tab(self.tabs['graph'], metric_bar, 'Metrics') if 'avg' in self.widget_row[i]['metrics'].keys(): avg_graph = QVBoxLayout() avg_graph.addWidget(self.widget_row[i]['metrics']['avg']['label']) graph = QGridLayout() graph.addWidget(self.widget_row[i]['metrics']['avg']['data'], 0, 0, im_height, im_width) avg_graph.addLayout(graph) # need for matplotlib? - test this... (grid) graph_save = QHBoxLayout() graph_save.addWidget(self.widget_row[i]['metrics']['avg']['save_button']) avg_graph.addLayout(graph_save) utils.add_layout_to_tab(self.tabs['graph'], avg_graph, 'Radar') if 'range' in self.widget_row[i]['metrics'].keys(): range_graph = QVBoxLayout() range_graph.addWidget(self.widget_row[i]['metrics']['range']['label']) graph = QGridLayout() graph.addWidget(self.widget_row[i]['metrics']['range']['data'], 0, 0, im_height, im_width) range_graph.addLayout(graph) # need for matplotlib? - test this... (grid) '''graph controls''' # will add to last one since there is one widget to control all graph_controls = QHBoxLayout() graph_controls.addWidget(self.widget_controls['button']['prev_metric_graph']) graph_controls.addWidget(self.widget_controls['button']['next_metric_graph']) range_graph.addLayout(graph_controls) graph_save = QHBoxLayout() graph_save.addWidget(self.widget_row[i]['metrics']['range']['save_button']) range_graph.addLayout(graph_save) utils.add_layout_to_tab(self.tabs['graph'], range_graph, 'Range') if 'correlation' in self.widget_row[i]['metrics'].keys(): correlation_graph = QVBoxLayout() correlation_graph.addWidget(self.widget_row[i]['metrics']['correlation']['label']) graph = QGridLayout() graph.addWidget(self.widget_row[i]['metrics']['correlation']['data'], 0, 0, im_height, im_width) correlation_graph.addLayout(graph) # need for matplotlib? - test this... (grid) '''graph controls''' # will add to last one since there is one widget to control all graph_controls = QHBoxLayout() graph_controls.addWidget(self.widget_controls['button']['prev_correlation_graph']) graph_controls.addWidget(self.widget_controls['button']['next_correlation_graph']) correlation_graph.addLayout(graph_controls) '''load experiment''' correlation_graph.addWidget(self.widget_controls['button']['load_exp']) utils.add_layout_to_tab(self.tabs['graph'], correlation_graph, 'Correlation') if 'JND' in self.widget_row[i]['metrics'].keys(): JND_graph = QVBoxLayout() JND_graph.addWidget(self.widget_row[i]['metrics']['JND']['label']) graph = QGridLayout() graph.addWidget(self.widget_row[i]['metrics']['JND']['data'], 0, 0, im_height, im_width) JND_graph.addLayout(graph) # need for matplotlib? - test this... (grid) '''graph controls''' # will add to last one since there is one widget to control all graph_controls = QHBoxLayout() JND_graph.addLayout(graph_controls) '''load experiment''' JND_graph.addWidget(self.widget_controls['button']['load_exp_JND']) utils.add_layout_to_tab(self.tabs['graph'], JND_graph, 'JND') graph_layouts.addWidget(self.tabs['graph']) graph_layouts.addStretch() '''dataset controls''' # prev/next buttons dataset_layout = QHBoxLayout() if self.dataset: dataset_layout.addWidget(self.widget_controls['label']['data']) dataset_layout.addWidget(self.widget_controls['button']['prev_data']) for im in range(self.num_images_scroll_show): dataset_layout.addWidget(self.widget_controls['images'][im]) dataset_layout.addWidget(self.widget_controls['button']['next_data']) dataset_layout.addWidget(self.widget_controls['label']['data_num']) '''transform controls''' image_controls = QVBoxLayout() # transform sliders for key in self.sliders['transforms']: tran_layout_top = QHBoxLayout() tran_layout_top.addWidget(self.widget_controls['slider'][key]['label']) tran_layout_top.addWidget(self.widget_controls['slider'][key]['value']) tran_layout_bottom = QHBoxLayout() tran_layout_bottom.addWidget(self.sliders['transforms'][key]['min_edit']) tran_layout_bottom.addWidget(self.widget_controls['slider'][key]['data']) tran_layout_bottom.addWidget(self.sliders['transforms'][key]['max_edit']) trans_layout = QVBoxLayout() trans_layout.addLayout(tran_layout_top) trans_layout.addLayout(tran_layout_bottom) image_controls.addLayout(trans_layout) image_controls.addStretch() reset_button = QHBoxLayout() reset_button.addWidget(self.widget_controls['button']['transforms']['reset_sliders']) reset_button.addStretch() image_controls.addLayout(reset_button) '''metric_param controls''' metric_controls = QVBoxLayout() for key in self.sliders['metric_params']: inner_metric_layout = QHBoxLayout() inner_metric_layout.addWidget(self.widget_controls['slider'][key]['label']) inner_metric_layout.addWidget(self.widget_controls['slider'][key]['data']) inner_metric_layout.addWidget(self.widget_controls['slider'][key]['value']) metric_controls.addLayout(inner_metric_layout) reset_button = QHBoxLayout() reset_button.addWidget(self.widget_controls['button']['metric_params']['reset_sliders']) reset_button.addStretch() metric_controls.addLayout(reset_button) metric_controls.addStretch() '''settings controls''' settings_controls = QVBoxLayout() for key, item in self.widget_settings.items(): inner_layout = QHBoxLayout() if isinstance(item, dict): inner_layout.addWidget(item['label']) inner_layout.addWidget(item['widget']) else: inner_layout.addWidget(item) inner_layout.addStretch() settings_controls.addLayout(inner_layout) settings_controls.addStretch() ''' experiment controls''' experiment_controls = QVBoxLayout() # tranformations for trans_name in self.widget_experiment_params: experiment_trans = QHBoxLayout() for _, widget in self.widget_experiment_params[trans_name].items(): experiment_trans.addWidget(widget) experiment_trans.addStretch() experiment_controls.addLayout(experiment_trans) experiment_controls.addStretch() # Save folder save_button_exp = QHBoxLayout() save_button_exp.addWidget(self.widget_controls['label']['exp_change_save']) save_button_exp.addWidget(self.widget_controls['button']['exp_change_save']) save_button_exp.addStretch() experiment_controls.addLayout(save_button_exp) # Dataset Name dataset_name_exp = QHBoxLayout() dataset_name_exp.addWidget( self.widget_controls['label']['exp_change_dataset_name']) dataset_name_exp.addWidget( self.widget_controls['button']['exp_change_dataset_name']) dataset_name_exp.addStretch() experiment_controls.addLayout(dataset_name_exp) # Dataset Range nums dataset_range_exp = QHBoxLayout() dataset_range_exp.addWidget( self.widget_controls['label']['exp_im_nums']) dataset_range_exp.addWidget( self.widget_controls['label']['range_edit_lower']) dataset_range_exp.addWidget( self.widget_controls['label']['exp_im_nums_dash']) dataset_range_exp.addWidget( self.widget_controls['label']['range_edit_upper']) dataset_range_exp.addStretch() experiment_controls.addLayout(dataset_range_exp) # run experiment button experiment_button = QHBoxLayout() experiment_button.addWidget(self.widget_controls['button']['launch_exp_2AFC']) experiment_button.addWidget(self.widget_controls['button']['launch_exp_JND']) experiment_button.addStretch() experiment_controls.addLayout(experiment_button) '''export images''' export_controls = QVBoxLayout() for trans_name in self.widget_export: export_trans = QHBoxLayout() for _, widget in self.widget_export[trans_name].items(): export_trans.addWidget(widget) export_trans.addStretch() export_controls.addLayout(export_trans) export_controls.addStretch() # Save folder save_button_exp = QHBoxLayout() save_button_exp.addWidget(self.widget_controls['label']['export_change_save']) save_button_exp.addWidget(self.widget_controls['button']['export_change_save']) save_button_exp.addStretch() export_controls.addLayout(save_button_exp) # export images button export_button = QHBoxLayout() export_button.addWidget(self.widget_controls['button']['export_images']) export_button.addStretch() export_controls.addLayout(export_button) ''' add to parameter controls tab''' self.tabs['slider'] = QTabWidget() for tab_layout, tab_name in zip([image_controls, metric_controls, settings_controls, experiment_controls, export_controls], ['transforms', 'metric params', 'image settings', 'experiment', 'export']): utils.add_layout_to_tab(self.tabs['slider'], tab_layout, tab_name) '''re calc graphs button''' graph_button = QVBoxLayout() if (self.metrics_avg_graph or self.metric_range_graph): graph_button.addWidget(self.widget_controls['button']['force_update']) graph_button.addWidget(self.widget_controls['check_box']['graph_limits']) graph_button.addStretch() ''' put the whole layout together ''' image_left_side = QVBoxLayout() image_left_side.addLayout(image_layouts) image_left_side.addLayout(dataset_layout) image_middle = QVBoxLayout() image_middle.addLayout(metric_layouts) all_images = QHBoxLayout() all_images.addLayout(image_left_side) all_images.addLayout(image_middle) controls = QVBoxLayout() controls.addWidget(self.tabs['slider']) images_plus_controls = QVBoxLayout() images_plus_controls.addLayout(all_images) images_plus_controls.addLayout(controls) graph_right = QVBoxLayout() graph_right.addLayout(graph_layouts) graph_right.addLayout(graph_button) self.main_layout = QHBoxLayout() self.main_layout.addLayout(images_plus_controls) self.main_layout.addLayout(graph_right) # self.main_layout.setColumnStretch(1, 1) # self.main_layout.setSpacing(0) # self.main_layout.setContentsMargins(0, 0, 0, 0)
[docs] def init_style(self, style='light', css_file=None): if css_file == None: dir = os.path.dirname(os.path.abspath(__file__)) # css_file = os.path.join(dir, 'style-light.css') css_file = os.path.join(dir, f'style-{style}.css') if os.path.isfile(css_file): with open(css_file, 'r') as file: self.app.setStyleSheet(file.read()) else: warnings.warn('Cannot load css style sheet - file not found')