[app] re-organization of ui classes

This commit is contained in:
Jan Grewe 2021-01-09 15:16:03 +01:00
parent 93d552265f
commit 20c1d02073
5 changed files with 580 additions and 263 deletions

View File

@ -1,12 +1,8 @@
import os from PyQt5.QtWidgets import QStackedLayout, QWidget
from PyQt5.QtWidgets import QComboBox, QFrame, QGroupBox, QHBoxLayout, QLabel, QListWidget, QListWidgetItem, QSplitter, QStackedLayout, QAbstractItemView, QTextEdit, QVBoxLayout, QWidget, QGridLayout
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import QItemSelectionModel, Qt, QSettings, pyqtSignal
from nixview.file_handler import FileHandler, ItemDescriptor from nixview.ui.plotscreen import PlotScreen
import nixview.communicator as comm from nixview.ui.splashscreen import SplashScreen
import nixview.constants as cnst from nixview.ui.filescreen import FileScreen
from nixview.data_models.tree_model import NixTreeView, TreeModel, TreeType
class CentralWidget(QWidget): class CentralWidget(QWidget):
@ -14,7 +10,7 @@ class CentralWidget(QWidget):
super().__init__(parent=parent) super().__init__(parent=parent)
self._splash = SplashScreen() self._splash = SplashScreen()
self._file_view = FileView(self) self._file_view = FileScreen(self)
self._plot_screen = PlotScreen(self) self._plot_screen = PlotScreen(self)
self._plot_screen.close_signal.connect(self.on_plot_close) self._plot_screen.close_signal.connect(self.on_plot_close)
self._stack = QStackedLayout(self) self._stack = QStackedLayout(self)
@ -38,221 +34,3 @@ class CentralWidget(QWidget):
self._file_view.reset() self._file_view.reset()
self._splash.reset() self._splash.reset()
self._stack.setCurrentIndex(0) self._stack.setCurrentIndex(0)
class FileView(QWidget):
def __init__(self, parent=None) -> None:
super().__init__(parent=parent)
self._file_handler = FileHandler()
vbox = QVBoxLayout()
self.setLayout(vbox)
main_splitter = QSplitter(Qt.Vertical)
self.layout().addWidget(main_splitter)
self._info = EntityInfo(self)
main_splitter.addWidget(self._info)
self._data_tree = NixTreeView(self)
self._tree_type_combo = QComboBox()
self._tree_type_combo.adjustSize()
self._tree_type_combo.addItems([TreeType.Data.value, TreeType.Full.value, TreeType.Metadata.value])
self._tree_type_combo.currentTextChanged.connect(self.update)
hbox = QHBoxLayout()
hbox.addWidget(QLabel("Tree type:"))
hbox.addWidget(self._tree_type_combo)
hbox.addStretch()
data_group = QGroupBox("Data")
data_vbox = QVBoxLayout()
data_vbox.setContentsMargins(1, 10, 1, 1)
data_vbox.addLayout(hbox)
data_vbox.addWidget(self._data_tree)
data_group.setLayout(data_vbox)
main_splitter.addWidget(data_group)
main_splitter.setSizes([200, 600])
vbox.addWidget(main_splitter)
def dataTreeSelection(self, current_index, last_index):
if not current_index.isValid():
return
item = current_index.internalPointer()
comm.communicator.item_selected.emit(item)
self._info.setEntityInfo(item.node_descriptor)
def update(self):
tt = TreeType.Data
if self._tree_type_combo.currentText() == TreeType.Data.value:
tt = TreeType.Data
elif self._tree_type_combo.currentText() == TreeType.Full.value:
tt = TreeType.Full
elif self._tree_type_combo.currentText() == TreeType.Metadata.value:
tt = TreeType.Metadata
self._info.setEntityInfo(None)
data_model = TreeModel(self._file_handler, tt)
self._data_tree.setModel(data_model)
selection_model = QItemSelectionModel(data_model)
self._data_tree.setSelectionModel(selection_model)
selection_model.currentChanged.connect(self.dataTreeSelection)
for i in range(data_model.columnCount(None)):
self._data_tree.resizeColumnToContents(i)
self._info.setFileInfo(self._file_handler.file_descriptor)
def reset(self):
pass
class EntityInfo(QWidget):
def __init__(self, parent):
super().__init__(parent=parent)
self._file_handler = FileHandler()
self.setLayout(QHBoxLayout())
self._metadata_tree = NixTreeView()
mdata_grp = QGroupBox("Metadata")
mdata_grp.setLayout(QVBoxLayout())
mdata_grp.layout().setContentsMargins(1, 10, 1, 1)
mdata_grp.layout().addWidget(self._metadata_tree)
file_info_grp = QGroupBox("File info")
file_info_grp.setLayout(QVBoxLayout())
file_info_grp.layout().setContentsMargins(1, 10, 1, 1)
self._file_info = QTextEdit("File information")
self._file_info.setEnabled(True)
self._file_info.setTextInteractionFlags(Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse)
self._file_info.setFrameShape(QFrame.NoFrame)
self._file_info.setLineWrapMode(QTextEdit.WidgetWidth)
file_info_grp.layout().addWidget(self._file_info)
entity_info_grp = QGroupBox("Entity info")
entity_info_grp.setLayout(QVBoxLayout())
entity_info_grp.layout().setContentsMargins(1, 10, 1, 1)
self._entity_info = QTextEdit("Entity information")
self._file_info.setEnabled(True)
self._file_info.setTextInteractionFlags(Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse)
self._file_info.setFrameShape(QFrame.NoFrame)
self._file_info.setLineWrapMode(QTextEdit.WidgetWidth)
entity_info_grp.layout().addWidget(self._entity_info)
self._splitter = QSplitter(Qt.Horizontal)
self._splitter.addWidget(file_info_grp)
self._splitter.addWidget(entity_info_grp)
self._splitter.addWidget(mdata_grp)
self._splitter.setSizes([200, 400, 0])
self._splitter.setStretchFactor(0, 0)
self._splitter.setStretchFactor(1, 1)
self._splitter.setStretchFactor(2, 1)
self.layout().addWidget(self._splitter)
def setFileInfo(self, file_info):
if file_info is not None:
self._file_info.setText(file_info.toHtml())
def setEntityInfo(self, entity_info):
if entity_info is None or not isinstance(entity_info, ItemDescriptor):
self._splitter.setSizes([200, 400, 0])
self._entity_info.setText("")
self._metadata_tree.setModel(None)
return
if entity_info.metadata_id is not None:
self._splitter.setSizes([200, 400, 400])
else:
self._splitter.setSizes([200, 400, 0])
self._entity_info.setText(entity_info.to_html())
metadata_model = TreeModel(self._file_handler, TreeType.Metadata, root_section_id=entity_info.metadata_id)
self._metadata_tree.setModel(metadata_model)
for i in range(metadata_model.columnCount(None)):
self._metadata_tree.resizeColumnToContents(i)
class SplashScreen(QWidget):
keyPressed = pyqtSignal(int)
def __init__(self, parent=None) -> None:
super().__init__(parent=parent)
#self.setStyleSheet("background-color: white;")
layout = QGridLayout()
layout.setColumnStretch(0, 2)
layout.setColumnStretch(1, 1)
layout.setColumnStretch(2, 1)
layout.setColumnStretch(3, 1)
layout.setColumnStretch(4, 2)
layout.setRowStretch(0, 1)
layout.setRowStretch(1, 0)
layout.setRowStretch(2, 1)
layout.setRowStretch(3, 2)
self.setLayout(layout)
label = QLabel()
label.setPixmap(QPixmap(os.path.join(cnst.ICONS_FOLDER, "nixview_transparent.png")))
label.setMaximumWidth(300)
label.setAlignment(Qt.AlignCenter)
layout.addWidget(label, 1, 1, 1, 3, Qt.AlignCenter)
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.setFrameShape(QFrame.NoFrame)
self.keyPressed.connect(self._on_key_pressed)
l.addWidget(self._file_list)
frame.setLayout(l)
layout.addWidget(frame, 3, 1, 1, 3)
self._file_map = {}
self._read_recent_files()
def keyPressEvent(self, event):
super(SplashScreen, self).keyPressEvent(event)
if event.key() == Qt.Key_Return:
self.keyPressed.emit(event.key())
def _create_short_filename(self, original, index, max_len=40):
short = original
parts = original.split(os.sep)
if len(parts) == 1:
short = "%i: %s" % (index, short[:max_len])
else:
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_key_pressed(self, key):
item = self._file_list.currentItem()
if item is not None and key == Qt.Key_Return:
comm.communicator.open_recent.emit(self._file_map[item.text()])

141
nixview/ui/filescreen.py Normal file
View File

@ -0,0 +1,141 @@
from PyQt5.QtWidgets import QComboBox, QFrame, QGroupBox, QHBoxLayout, QLabel, QSplitter, QTextEdit, QVBoxLayout, QWidget
from PyQt5.QtCore import QItemSelectionModel, Qt
from nixview.file_handler import FileHandler, ItemDescriptor
import nixview.communicator as comm
import nixview.constants as cnst
from nixview.data_models.tree_model import NixTreeView, TreeModel, TreeType
class FileScreen(QWidget):
def __init__(self, parent=None) -> None:
super().__init__(parent=parent)
self._file_handler = FileHandler()
vbox = QVBoxLayout()
self.setLayout(vbox)
main_splitter = QSplitter(Qt.Vertical)
self.layout().addWidget(main_splitter)
self._info = EntityInfo(self)
main_splitter.addWidget(self._info)
self._data_tree = NixTreeView(self)
self._tree_type_combo = QComboBox()
self._tree_type_combo.adjustSize()
self._tree_type_combo.addItems([TreeType.Data.value, TreeType.Full.value, TreeType.Metadata.value])
self._tree_type_combo.currentTextChanged.connect(self.update)
hbox = QHBoxLayout()
hbox.addWidget(QLabel("Tree type:"))
hbox.addWidget(self._tree_type_combo)
hbox.addStretch()
data_group = QGroupBox("Data")
data_vbox = QVBoxLayout()
data_vbox.setContentsMargins(1, 10, 1, 1)
data_vbox.addLayout(hbox)
data_vbox.addWidget(self._data_tree)
data_group.setLayout(data_vbox)
main_splitter.addWidget(data_group)
main_splitter.setSizes([200, 600])
vbox.addWidget(main_splitter)
def dataTreeSelection(self, current_index, last_index):
if not current_index.isValid():
return
item = current_index.internalPointer()
comm.communicator.item_selected.emit(item)
self._info.setEntityInfo(item.node_descriptor)
def update(self):
tt = TreeType.Data
if self._tree_type_combo.currentText() == TreeType.Data.value:
tt = TreeType.Data
elif self._tree_type_combo.currentText() == TreeType.Full.value:
tt = TreeType.Full
elif self._tree_type_combo.currentText() == TreeType.Metadata.value:
tt = TreeType.Metadata
self._info.setEntityInfo(None)
data_model = TreeModel(self._file_handler, tt)
self._data_tree.setModel(data_model)
selection_model = QItemSelectionModel(data_model)
self._data_tree.setSelectionModel(selection_model)
selection_model.currentChanged.connect(self.dataTreeSelection)
for i in range(data_model.columnCount(None)):
self._data_tree.resizeColumnToContents(i)
self._info.setFileInfo(self._file_handler.file_descriptor)
def reset(self):
pass
class EntityInfo(QWidget):
def __init__(self, parent):
super().__init__(parent=parent)
self._file_handler = FileHandler()
self.setLayout(QHBoxLayout())
self._metadata_tree = NixTreeView()
mdata_grp = QGroupBox("Metadata")
mdata_grp.setLayout(QVBoxLayout())
mdata_grp.layout().setContentsMargins(1, 10, 1, 1)
mdata_grp.layout().addWidget(self._metadata_tree)
file_info_grp = QGroupBox("File info")
file_info_grp.setLayout(QVBoxLayout())
file_info_grp.layout().setContentsMargins(1, 10, 1, 1)
self._file_info = QTextEdit("File information")
self._file_info.setEnabled(True)
self._file_info.setTextInteractionFlags(Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse)
self._file_info.setFrameShape(QFrame.NoFrame)
self._file_info.setLineWrapMode(QTextEdit.WidgetWidth)
file_info_grp.layout().addWidget(self._file_info)
entity_info_grp = QGroupBox("Entity info")
entity_info_grp.setLayout(QVBoxLayout())
entity_info_grp.layout().setContentsMargins(1, 10, 1, 1)
self._entity_info = QTextEdit("Entity information")
self._file_info.setEnabled(True)
self._file_info.setTextInteractionFlags(Qt.TextSelectableByKeyboard | Qt.TextSelectableByMouse)
self._file_info.setFrameShape(QFrame.NoFrame)
self._file_info.setLineWrapMode(QTextEdit.WidgetWidth)
entity_info_grp.layout().addWidget(self._entity_info)
self._splitter = QSplitter(Qt.Horizontal)
self._splitter.addWidget(file_info_grp)
self._splitter.addWidget(entity_info_grp)
self._splitter.addWidget(mdata_grp)
self._splitter.setSizes([200, 400, 0])
self._splitter.setStretchFactor(0, 0)
self._splitter.setStretchFactor(1, 1)
self._splitter.setStretchFactor(2, 1)
self.layout().addWidget(self._splitter)
def setFileInfo(self, file_info):
if file_info is not None:
self._file_info.setText(file_info.toHtml())
def setEntityInfo(self, entity_info):
if entity_info is None or not isinstance(entity_info, ItemDescriptor):
self._splitter.setSizes([200, 400, 0])
self._entity_info.setText("")
self._metadata_tree.setModel(None)
return
if entity_info.metadata_id is not None:
self._splitter.setSizes([200, 400, 400])
else:
self._splitter.setSizes([200, 400, 0])
self._entity_info.setText(entity_info.to_html())
metadata_model = TreeModel(self._file_handler, TreeType.Metadata, root_section_id=entity_info.metadata_id)
self._metadata_tree.setModel(metadata_model)
for i in range(metadata_model.columnCount(None)):
self._metadata_tree.resizeColumnToContents(i)

View File

@ -1,36 +0,0 @@
from PyQt5.QtWidgets import QHBoxLayout, QPushButton, QVBoxLayout, QWidget
from PyQt5.QtCore import QObject, pyqtSignal, Qt
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure
class MplCanvas(FigureCanvasQTAgg):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
super(MplCanvas, self).__init__(fig)
class PlotScreen(QWidget):
close_signal = pyqtSignal()
def __init__(self, parent) -> None:
super().__init__(parent=parent)
sc = MplCanvas(self, width=5, height=4, dpi=100)
sc.axes.plot([0,1,2,3,4], [10,1,20,3,40])
self.setLayout(QVBoxLayout())
self.layout().addWidget(sc)
close_btn = QPushButton("close")
close_btn.clicked.connect(self.on_close)
self.layout().addWidget(close_btn)
def on_close(self):
self.close_signal.emit()
def plot(self, item):
print("plot!", item)

343
nixview/ui/plotscreen.py Normal file
View File

@ -0,0 +1,343 @@
from PyQt5.QtWidgets import QHBoxLayout, QPushButton, QVBoxLayout, QWidget
from PyQt5.QtCore import QObject, pyqtSignal, Qt
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
import nixio as nix
def create_label(entity):
label = ""
if hasattr(entity, "label"):
label += (entity.label if entity.label is not None else "")
if len(label) == 0 and hasattr(entity, "name"):
label += entity.name
if hasattr(entity, "unit") and entity.unit is not None:
label += " [%s]" % entity.unit
return label
class Plotter(object):
def show(self):
plt.show()
class EventPlotter(Plotter):
def __init__(self, data_array, xdim=-1):
self.array = data_array
self.sc = None
self.dim_count = len(data_array.dimensions)
if xdim == -1:
self.xdim = guess_best_xdim(self.array)
elif xdim > 1:
raise ValueError("EventPlotter: xdim is larger than 2! "
"Cannot plot that kind of data")
else:
self.xdim = xdim
def plot(self, axis=None):
if axis is None:
self.fig = plt.figure(figsize=[5.5, 2.])
self.axis = self.fig.add_axes([0.15, .2, 0.8, 0.75])
self.axis.set_title(self.array.name)
else:
self.fig = axis.figure
self.axis = axis
if len(self.array.dimensions) == 1:
return self.plot_1d()
else:
return None
def plot_1d(self):
data = self.array[:]
xlabel = create_label(self.array.dimensions[self.xdim])
dim = self.array.dimensions[self.xdim]
if dim.dimension_type == nix.DimensionType.Range and not dim.is_alias:
ylabel = create_label(self.array)
else:
ylabel = ""
self.sc = self.axis.scatter(data, np.ones(data.shape))
self.axis.set_ylim([0.5, 1.5])
self.axis.set_yticks([1.])
self.axis.set_yticklabels([])
self.axis.set_xlabel(xlabel)
self.axis.set_ylabel(ylabel)
return self.axis
class CategoryPlotter(Plotter):
def __init__(self, data_array, xdim=-1):
self.array = data_array
self.bars = []
if xdim == -1:
self.xdim = guess_best_xdim(self.array)
elif xdim > 2:
raise ValueError("CategoryPlotter: xdim is larger than 2! "
"Cannot plot that kind of data")
else:
self.xdim = xdim
def plot(self, axis=None):
if axis is None:
self.fig = plt.figure()
self.axis = self.fig.add_axes([0.15, .2, 0.8, 0.75])
self.axis.set_title(self.array.name)
else:
self.fig = axis.figure
self.axis = axis
if len(self.array.dimensions) == 1:
return self.plot_1d()
elif len(self.array.dimensions) == 2:
return self.plot_2d()
else:
return None
def plot_1d(self):
data = self.array[:]
dim = self.array.dimensions[self.xdim]
if dim.dimension_type == nix.DimensionType.Set:
categories = list(dim.labels)
else:
return None
if categories is None:
categories = ["Cat-%i" % i for i in range(len(data))]
ylabel = create_label(self.array)
if len(categories) == 0:
raise ValueError("Cannot plot a bar chart without any labels")
self.bars.append(self.axis.bar(range(1, len(categories)+1), data,
tick_label=categories))
self.axis.set_ylabel(ylabel)
return self.axis
def plot_2d(self):
data = self.array[:]
if self.xdim == 1:
data = data.T
dim = self.array.dimensions[self.xdim]
if dim.dimension_type == nix.DimensionType.Set:
categories = list(dim.labels)
if len(categories) == 0:
categories = ["Cat-%i" % i for i in range(data.shape[self.xdim])]
dim = self.array.dimensions[1-self.xdim]
if dim.dimension_type == nix.DimensionType.Set:
series_names = list(dim.labels)
if len(series_names) == 0:
series_names = ["Series-%i" % i
for i in range(data.shape[1-self.xdim])]
bar_width = 1/data.shape[1] * 0.75
for i in range(data.shape[1]):
x_values = np.arange(data.shape[0]) + i * bar_width
self.bars.append(self.axis.bar(x_values, data[:, i],
width=bar_width,
align="center")[0])
self.axis.set_xticks(np.arange(data.shape[0]) +
data.shape[1] * bar_width/2)
self.axis.set_xticklabels(categories)
self.axis.legend(self.bars, series_names, loc=1)
return self.axis
class ImagePlotter(Plotter):
def __init__(self, data_array, xdim=-1):
self.array = data_array
self.image = None
def plot(self, axis=None):
dim_count = len(self.array.dimensions)
if axis is None:
self.fig = plt.figure()
self.axis = self.fig.add_axes([0.15, .2, 0.8, 0.75])
self.axis.set_title(self.array.name)
else:
self.fig = axis.figure
self.axis = axis
if dim_count == 2:
return self.plot_2d()
elif dim_count == 3:
return self.plot_3d()
else:
return None
def plot_2d(self):
data = self.array[:]
x = self.array.dimensions[0].axis(data.shape[0])
y = self.array.dimensions[1].axis(data.shape[1])
xlabel = create_label(self.array.dimensions[0])
ylabel = create_label(self.array.dimensions[1])
self.image = self.axis.imshow(data, extent=[x[0], x[-1], y[0], y[-1]])
self.axis.set_xlabel(xlabel)
self.axis.set_ylabel(ylabel)
self.axis.set
return self.axis
def plot_3d(self):
if self.array.shape[2] > 3:
print("cannot plot 3d data with more than 3 channels "
"in the third dim")
return None
return self.plot_2d()
class LinePlotter(Plotter):
def __init__(self, data_array, xdim=-1):
self.array = data_array
self.lines = []
self.dim_count = len(data_array.dimensions)
if xdim == -1:
self.xdim = guess_best_xdim(self.array)
elif xdim > 2:
raise ValueError("LinePlotter: xdim is larger than 2! "
"Cannot plot that kind of data")
else:
self.xdim = xdim
self.fig = None
self.axis = None
def plot(self, axis=None, maxpoints=100000):
self.maxpoints = maxpoints
if axis is None:
self.fig = plt.figure()
self.axis = self.fig.add_axes([0.15, .2, 0.8, 0.75])
self.axis.set_title(self.array.name)
self.__add_slider()
else:
self.axis = axis
dim_count = len(self.array.dimensions)
if dim_count > 2:
return
if dim_count == 1:
return self.plot_array_1d()
else:
return self.plot_array_2d()
def __add_slider(self):
steps = self.array.shape[self.xdim] / self.maxpoints
slider_ax = self.fig.add_axes([0.15, 0.025, 0.8, 0.025])
self.slider = Slider(slider_ax, 'Slider', 1., steps, valinit=1.,
valstep=0.25)
self.slider.on_changed(self.__update)
def __update(self, val):
if len(self.lines) > 0:
minimum = val * self.maxpoints - self.maxpoints
start = minimum if minimum > 0 else 0
end = val * self.maxpoints
self.__draw(start, end)
self.fig.canvas.draw_idle()
def __draw(self, start, end):
if self.dim_count == 1:
self.__draw_1d(start, end)
else:
self.__draw_2d(start, end)
def __draw_1d(self, start, end):
if start < 0:
start = 0
if end > self.array.shape[self.xdim]:
end = self.array.shape[self.xdim]
y = self.array[int(start):int(end)]
dim = self.array.dimensions[self.xdim]
x = np.asarray(dim.axis(len(y), int(start)))
if len(self.lines) == 0:
l, = self.axis.plot(x, y, label=self.array.name)
self.lines.append(l)
else:
self.lines[0].set_ydata(y)
self.lines[0].set_xdata(x)
self.axis.set_xlim([x[0], x[-1]])
def __draw_2d(self, start, end):
if start < 0:
start = 0
if end > self.array.shape[self.xdim]:
end = self.array.shape[self.xdim]
x_dimension = self.array.dimensions[self.xdim]
x = np.asarray(x_dimension.axis(int(end-start), start))
y_dimension = self.array.dimensions[1-self.xdim]
labels = y_dimension.labels
if len(labels) == 0:
labels = list(map(str, range(self.array.shape[1-self.xdim])))
for i, l in enumerate(labels):
if (self.xdim == 0):
y = self.array[int(start):int(end), i]
else:
y = self.array[i, int(start):int(end)]
if len(self.lines) <= i:
ll, = self.axis.plot(x, y, label=l)
self.lines.append(ll)
else:
self.lines[i].set_ydata(y)
self.lines[i].set_xdata(x)
self.axis.set_xlim([x[0], x[-1]])
def plot_array_1d(self):
self.__draw_1d(0, self.maxpoints)
xlabel = create_label(self.array.dimensions[self.xdim])
ylabel = create_label(self.array)
self.axis.set_xlabel(xlabel)
self.axis.set_ylabel(ylabel)
return self.axis
def plot_array_2d(self):
self.__draw_2d(0, self.maxpoints)
xlabel = create_label(self.array.dimensions[self.xdim])
ylabel = create_label(self.array)
self.axis.set_xlabel(xlabel)
self.axis.set_ylabel(ylabel)
self.axis.legend(loc=1)
return self.axis
class MplCanvas(FigureCanvasQTAgg):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
super(MplCanvas, self).__init__(fig)
class PlotScreen(QWidget):
close_signal = pyqtSignal()
def __init__(self, parent) -> None:
super().__init__(parent=parent)
sc = MplCanvas(self, width=5, height=4, dpi=100)
sc.axes.plot([0,1,2,3,4], [10,1,20,3,40])
self.setLayout(QVBoxLayout())
self.layout().addWidget(sc)
close_btn = QPushButton("close")
close_btn.clicked.connect(self.on_close)
self.layout().addWidget(close_btn)
def on_close(self):
self.close_signal.emit()
def plot(self, item):
print("plot!", item)

View File

@ -0,0 +1,91 @@
import os
from PyQt5.QtWidgets import QWidget, QGridLayout, QLabel, QFrame, QVBoxLayout, QListWidget, QAbstractItemView, QListWidgetItem
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt, QSettings, pyqtSignal
import nixview.communicator as comm
import nixview.constants as cnst
class SplashScreen(QWidget):
keyPressed = pyqtSignal(int)
def __init__(self, parent=None) -> None:
super().__init__(parent=parent)
#self.setStyleSheet("background-color: white;")
layout = QGridLayout()
layout.setColumnStretch(0, 2)
layout.setColumnStretch(1, 1)
layout.setColumnStretch(2, 1)
layout.setColumnStretch(3, 1)
layout.setColumnStretch(4, 2)
layout.setRowStretch(0, 1)
layout.setRowStretch(1, 0)
layout.setRowStretch(2, 1)
layout.setRowStretch(3, 2)
self.setLayout(layout)
label = QLabel()
label.setPixmap(QPixmap(os.path.join(cnst.ICONS_FOLDER, "nixview_transparent.png")))
label.setMaximumWidth(300)
label.setAlignment(Qt.AlignCenter)
layout.addWidget(label, 1, 1, 1, 3, Qt.AlignCenter)
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.setFrameShape(QFrame.NoFrame)
self.keyPressed.connect(self._on_key_pressed)
l.addWidget(self._file_list)
frame.setLayout(l)
layout.addWidget(frame, 3, 1, 1, 3)
self._file_map = {}
self._read_recent_files()
def keyPressEvent(self, event):
super(SplashScreen, self).keyPressEvent(event)
if event.key() == Qt.Key_Return:
self.keyPressed.emit(event.key())
def _create_short_filename(self, original, index, max_len=40):
short = original
parts = original.split(os.sep)
if len(parts) == 1:
short = "%i: %s" % (index, short[:max_len])
else:
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_key_pressed(self, key):
item = self._file_list.currentItem()
if item is not None and key == Qt.Key_Return:
comm.communicator.open_recent.emit(self._file_map[item.text()])