From ea62a05bd3c45386d4ce97ca1075f6471423c9ce Mon Sep 17 00:00:00 2001 From: Dominik Demuth Date: Tue, 19 Sep 2023 16:32:54 +0200 Subject: [PATCH] improve performance for show/hide graphs --- src/gui_qt/data/datawidget/datawidget.py | 27 ++++++++++++------------ src/gui_qt/graphs/graphwindow.py | 15 ++++++++++--- src/gui_qt/main/management.py | 14 +++++++----- src/nmreval/io/hdfreader.py | 7 +++--- 4 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/gui_qt/data/datawidget/datawidget.py b/src/gui_qt/data/datawidget/datawidget.py index 01c30a2..28dc1c1 100644 --- a/src/gui_qt/data/datawidget/datawidget.py +++ b/src/gui_qt/data/datawidget/datawidget.py @@ -84,7 +84,7 @@ class DataTree(QtWidgets.QTreeWidget): self.update_indexes() @QtCore.pyqtSlot(QtWidgets.QTreeWidgetItem) - def data_change(self, item: QtWidgets.QTreeWidgetItem) -> tuple[set, set]: + def data_change(self, item: QtWidgets.QTreeWidgetItem, emit: bool = True) -> tuple[set, set]: idd = item.data(0, QtCore.Qt.UserRole) is_selected = item.checkState(0) == QtCore.Qt.Checked to_be_hidden = set() @@ -142,9 +142,10 @@ class DataTree(QtWidgets.QTreeWidget): pass else: - self.keyChanged.emit(idd, item.text(0)) + if emit: + self.keyChanged.emit(idd, item.text(0)) - if to_be_shown or to_be_hidden: + if (to_be_shown or to_be_hidden) and emit: self.stateChanged.emit(list(to_be_shown), list(to_be_hidden)) return to_be_shown, to_be_hidden @@ -316,26 +317,24 @@ class DataTree(QtWidgets.QTreeWidget): if idx.column() != 0: continue item = self.itemFromIndex(idx) - if item.parent() is None: - is_selected = item.checkState(0) - self.blockSignals(True) for i in range(item.childCount()): child = item.child(i) from_parent.append(child) - self.blockSignals(False) - if is_selected == QtCore.Qt.Checked: - item.setCheckState(0, QtCore.Qt.Unchecked) - else: - item.setCheckState(0, QtCore.Qt.Checked) - - else: - sets.append(item) + sets.append(item) + to_be_hidden = set() + to_be_shown = set() + self.blockSignals(True) for it in sets: if it in from_parent: continue it.setCheckState(0, QtCore.Qt.Unchecked if it.checkState(0) == QtCore.Qt.Checked else QtCore.Qt.Checked) + s1, s2 = self.data_change(it, emit=False) + to_be_hidden |= s2 + to_be_shown |= s1 + self.blockSignals(False) + self.stateChanged.emit(list(to_be_shown), list(to_be_hidden)) else: super().keyPressEvent(evt) diff --git a/src/gui_qt/graphs/graphwindow.py b/src/gui_qt/graphs/graphwindow.py index ad6755f..6d7eb16 100644 --- a/src/gui_qt/graphs/graphwindow.py +++ b/src/gui_qt/graphs/graphwindow.py @@ -177,9 +177,9 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow): if isinstance(name, str): name = [name] plots = [plots] - + toplevel = len(self.sets) + self.listWidget.blockSignals(True) for (real_plot, imag_plot, err_plot), n in zip(plots, name): - toplevel = len(self.sets) self.sets.append(n) if real_plot: @@ -199,7 +199,16 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow): list_item.setCheckState(QtCore.Qt.Checked) self.listWidget.addItem(list_item) - self.show_item(name) + toplevel += 1 + self.listWidget.blockSignals(False) + + if len(name) < 200: + self.show_item(name) + else: + QtWidgets.QMessageBox.warning(self, 'Display disabled', + 'If more than 200 sets are added at once, they are not displayed to avoid major performance issues.\n' + 'Building the data tree may still take some time, the checkmark on the left is invalid.\n' + 'Please display them manually in smaller batches, thank you!') def remove(self, name: str | list): if isinstance(name, str): diff --git a/src/gui_qt/main/management.py b/src/gui_qt/main/management.py index ca5b065..4e6a09e 100644 --- a/src/gui_qt/main/management.py +++ b/src/gui_qt/main/management.py @@ -385,12 +385,16 @@ class UpperManagement(QtCore.QObject): def change_visibility(self, selected: list, deselected: list): """Change status of list of ids after status change in datawidget""" + for item_list, func in [(selected, 'show_item'), (deselected, 'hide_item')]: + grouping = {} + for s in item_list: + g = self.data[s].graph + if g not in grouping: + grouping[g] = [] + grouping[g].append(s) - for s in selected: - self.graphs[self.data[s].graph].show_item([s]) - - for d in deselected: - self.graphs[self.data[d].graph].hide_item([d]) + for k, v in grouping.items(): + getattr(self.graphs[k], func)(v) @QtCore.pyqtSlot(str, str) def change_keys(self, identifier: str, name: str): diff --git a/src/nmreval/io/hdfreader.py b/src/nmreval/io/hdfreader.py index 8c681ce..f3fe96e 100644 --- a/src/nmreval/io/hdfreader.py +++ b/src/nmreval/io/hdfreader.py @@ -134,8 +134,8 @@ class HdfNode: else: self.parameter[key] = value - if self.parent is not None: - self.parent.set_parameter(key, value, keep=True) + # if self.parent is not None: + # self.parent.set_parameter(key, value, keep=True) def set_title_parameter(self, child_node, params): if params: @@ -174,7 +174,7 @@ class HdfReader(HdfNode): self.create_node(self.file[base], parent=self) except OSError: self.file = None - raise IOError('Invalid file ' + filename) + raise IOError(f'Invalid file {filename}') def __call__(self, filename, base='data_pool'): super().clear() @@ -215,6 +215,7 @@ class HdfReader(HdfNode): parent[name] = data parent.num_signals += 1 + # searching for attributes is performance bottleneck but necessary for desc in attr.keys(): # looking for description_KEY in attributes m = re.search(r'description_(?P\S+)', desc)