import os from PyQt5 import QtWidgets from PyQt5.QtWidgets import QFrame, QGroupBox, QLabel, QListWidget, QListWidgetItem, QSplitter, QStackedLayout, QAbstractItemView, QVBoxLayout, QWidget, QGridLayout, QSpacerItem, QSizePolicy, QTreeView, QHeaderView from PyQt5.QtGui import QPixmap from PyQt5.QtCore import QItemSelectionModel, Qt, QSettings, QSize from file_handler import FileHandler from plot_screen import PlotScreen import communicator as comm import constants as cnst from tree_model import TreeModel, TreeType class CentralWidget(QWidget): def __init__(self, parent=None) -> None: super().__init__(parent=parent) self._splash = SplashScreen() self._file_view = FileView(self) self._plot_screen = PlotScreen(self) self._plot_screen.close_signal.connect(self.on_plot_close) self._stack = QStackedLayout(self) self._stack.addWidget(self._splash) self._stack.addWidget(self._file_view) self._stack.addWidget(self._plot_screen) self.setLayout(self._stack) #self.setStyleSheet("background-color: white;") def show_file_content(self): self._stack.setCurrentIndex(1) self._file_view.update() def plot_item(self, item): self._stack.setCurrentIndex(2) self._plot_screen.plot(item) def on_plot_close(self): self._stack.setCurrentIndex(1) def reset(self): self._file_view.reset() self._splash.reset() self._stack.setCurrentIndex(0) class FileView(QWidget): icon_size = QSize(30, 30) def __init__(self, parent=None) -> None: super().__init__(parent=parent) self._file_handler = FileHandler() vbox = QVBoxLayout() self.setLayout(vbox) splitter = QSplitter(Qt.Vertical) self._mdata_tree = QTreeView(self) self._mdata_tree.expanded.connect(self.metadataTreeResize) self._mdata_tree.collapsed.connect(self.metadataTreeResize) self._mdata_tree.setAlternatingRowColors(True) self._mdata_tree.setUniformRowHeights(True) # Allows for scrolling optimizations. self._mdata_tree.setWindowTitle("Metadata Tree") self._mdata_tree.setIconSize(self.icon_size) mheader = self._mdata_tree.header() mheader.setStretchLastSection(False) mheader.setSectionResizeMode(1, QHeaderView.ResizeToContents) mheader.setSectionResizeMode(2, QHeaderView.ResizeToContents) mheader.setSectionResizeMode(0, QHeaderView.Stretch) mdata_group = QGroupBox("Metadata") mdata_group.setLayout(QVBoxLayout()) mdata_group.layout().addWidget(self._mdata_tree) self._data_tree = QTreeView(self) self._data_tree.expanded.connect(self.dataTreeResize) self._data_tree.collapsed.connect(self.dataTreeResize) self._data_tree.setAlternatingRowColors(True) self._data_tree.setUniformRowHeights(True) # Allows for scrolling optimizations. self._data_tree.setWindowTitle("Data Tree") self._data_tree.setIconSize(self.icon_size) self._data_tree.setSelectionBehavior(QAbstractItemView.SelectItems) self._data_tree.setSelectionMode(QAbstractItemView.SingleSelection) header = self._data_tree.header() header.setStretchLastSection(False) header.setSectionResizeMode(1, QHeaderView.ResizeToContents) header.setSectionResizeMode(2, QHeaderView.ResizeToContents) header.setSectionResizeMode(0, QHeaderView.Stretch) data_group = QGroupBox("Data") data_vbox = QVBoxLayout() data_vbox.addWidget(self._data_tree) data_group.setLayout(data_vbox) splitter.insertWidget(0, mdata_group) splitter.insertWidget(1, data_group) vbox.addWidget(splitter) def metadataTreeResize(self, index): self._mdata_tree.resizeColumnToContents(index.column()) def dataTreeResize(self, index): self._data_tree.resizeColumnToContents(index.column()) def dataTreeSelection(self, current_index, last_index): if not current_index.isValid(): return item = current_index.internalPointer() comm.communicator.item_selected.emit(item) def update(self): data_model = TreeModel(self._file_handler, TreeType.Data) metadata_model = TreeModel(self._file_handler, TreeType.Metadata) self._data_tree.setModel(data_model) selection_model = QItemSelectionModel(data_model) self._data_tree.setSelectionModel(selection_model) selection_model.currentChanged.connect(self.dataTreeSelection) self._mdata_tree.setModel(metadata_model) for i in range(data_model.columnCount(None)): self._data_tree.resizeColumnToContents(i) self._mdata_tree.resizeColumnToContents(i) def reset(self): print("FileView ", self._file_handler.is_valid) pass class SplashScreen(QWidget): def __init__(self, parent=None) -> None: super().__init__(parent=parent) layout = QGridLayout() self.setLayout(layout) self.setStyleSheet("background-color: white;") label = QLabel() label.setPixmap(QPixmap("./icons/nixview256.png")) label.setAlignment(Qt.AlignCenter) layout.addWidget(label, 1, 1) verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) verticalSpacer2 = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) hSpacer = QSpacerItem(400, 20, QSizePolicy.Maximum, QSizePolicy.Expanding) hSpacer2 = QSpacerItem(400, 20, QSizePolicy.Maximum, QSizePolicy.Expanding) layout.addItem(verticalSpacer, 0, 1) layout.addItem(verticalSpacer2, 2, 1) layout.addItem(hSpacer, 1, 0) layout.addItem(hSpacer2, 1, 2) frame = QFrame() l = QVBoxLayout() l.addWidget(QLabel("Recently opened files:")) self._file_list = QListWidget(self) self._file_list.setSelectionMode(QAbstractItemView.SingleSelection) self._file_list.itemClicked.connect(self._on_file_clicked) self._file_list.itemSelectionChanged.connect(self._on_selection_changed) l.addWidget(self._file_list) frame.setLayout(l) layout.addWidget(frame, 3, 1) self._file_map = {} self._read_recent_files() def _create_short_filename(self, original, index, max_len=40): short = original parts = original.split(os.sep) post = parts[-1] if len(post) > max_len - 4: post = post[:max_len - 4] short = str("%i: " % index) + "... " + post else: short = str("%i: " % index) + " ... ".join([original[:max_len - len(post) - 4], post]) return short def _read_recent_files(self): settings = QSettings(cnst.organization, cnst.application) filenames = settings.value(cnst.settings_recent_files_key, []) del settings for i, f in enumerate(filenames): shortname = self._create_short_filename(f, i + 1, max_len=38) self._file_map[shortname] = f item = QListWidgetItem(shortname) item.setToolTip(f) self._file_list.addItem(item) def reset(self): self._file_list.clear() self._read_recent_files() def _on_file_clicked(self, item): comm.communicator.open_recent.emit(self._file_map[item.text()]) def _on_selection_changed(self): item = self._file_list.currentItem() comm.communicator.open_recent.emit(self._file_map[item.text()])