From 24640d374ea418c4e5d2c898cb93b52ec9f400f5 Mon Sep 17 00:00:00 2001 From: Dominik Demuth Date: Wed, 7 Feb 2024 18:58:18 +0000 Subject: [PATCH] handle graph export with empty data (#239); closes #233 Co-authored-by: Dominik Demuth Reviewed-on: https://gitea.pkm.physik.tu-darmstadt.de/IPKM/nmreval/pulls/239 --- src/gui_qt/data/valueeditwidget.py | 43 ++++++++++++++++-------------- src/gui_qt/graphs/graphwindow.py | 27 ++++++++++++------- src/gui_qt/lib/pg_objects.py | 5 +++- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/src/gui_qt/data/valueeditwidget.py b/src/gui_qt/data/valueeditwidget.py index c85f1d1..ae95a5f 100644 --- a/src/gui_qt/data/valueeditwidget.py +++ b/src/gui_qt/data/valueeditwidget.py @@ -3,10 +3,10 @@ from __future__ import annotations from typing import Any from numpy import ndarray, iscomplexobj, asarray -from pyqtgraph import PlotDataItem from ..Qt import QtGui, QtCore, QtWidgets from .._py.valueeditor import Ui_MaskDialog +from ..lib.pg_objects import PlotItem class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog): @@ -35,13 +35,13 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog): self.tableView.setModel(self.model) self.tableView.setSelectionModel(self.selection_model) - self.tableView.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) + self.tableView.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu) self.tableView.customContextMenuRequested.connect(self.ctx) - self.selection_real = PlotDataItem(x=[], y=[], symbolSize=25, symbol='x', - pen=None, symbolPen='#c9308e', symbolBrush='#c9308e') - self.selection_imag = PlotDataItem(x=[], y=[], symbolSize=25, symbol='+', - pen=None, symbolPen='#dcdcdc', symbolBrush='#dcdcdc') + self.selection_real = PlotItem(x=[], y=[], symbolSize=25, symbol='x', + pen=None, symbolPen='#c9308e', symbolBrush='#c9308e') + self.selection_imag = PlotItem(x=[], y=[], symbolSize=25, symbol='+', + pen=None, symbolPen='#dcdcdc', symbolBrush='#dcdcdc') def __call__(self, items: dict): self.items = items @@ -133,7 +133,7 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog): def keyPressEvent(self, evt): if evt.matches(QtGui.QKeySequence.Copy): self.copy_selection() - elif evt.key() == QtCore.Qt.Key_Delete: + elif evt.key() == QtCore.Qt.Key.Key_Delete: self.delete_item() else: super().keyPressEvent(evt) @@ -229,7 +229,7 @@ class ValueModel(QtCore.QAbstractTableModel): """ itemChanged = QtCore.pyqtSignal(int, int, str) load_number = 20 - maskRole = QtCore.Qt.UserRole+321 + maskRole = QtCore.Qt.ItemDataRole.UserRole+321 def __init__(self, parent=None): super().__init__(parent=parent) @@ -240,7 +240,7 @@ class ValueModel(QtCore.QAbstractTableModel): self.mask = None self.headers = ['x', 'y', '\u0394y'] for i, hd in enumerate(self.headers): - self.setHeaderData(i, QtCore.Qt.Horizontal, hd) + self.setHeaderData(i, QtCore.Qt.Orientation.Horizontal, hd) def rowCount(self, *args, **kwargs) -> int: return self.total_rows @@ -258,25 +258,28 @@ class ValueModel(QtCore.QAbstractTableModel): self.mask = mask.tolist() self.endResetModel() - self.dataChanged.emit(self.index(0, 0), self.index(0, 1), [QtCore.Qt.DisplayRole]) + self.dataChanged.emit( + self.index(0, 0), + self.index(0, 1), [QtCore.Qt.ItemDataRole.DisplayRole] + ) - def data(self, idx: QtCore.QModelIndex, role=QtCore.Qt.DisplayRole) -> Any: + def data(self, idx: QtCore.QModelIndex, role=QtCore.Qt.ItemDataRole.DisplayRole) -> Any: if not idx.isValid(): return row = idx.row() - if role in [QtCore.Qt.DisplayRole, QtCore.Qt.EditRole]: + if role in [QtCore.Qt.ItemDataRole.DisplayRole, QtCore.Qt.ItemDataRole.EditRole]: val = self._data[row][idx.column()] return self.as_string(val) - elif role == QtCore.Qt.BackgroundRole: + elif role == QtCore.Qt.ItemDataRole.BackgroundRole: pal = QtGui.QGuiApplication.palette() if not self.mask[row]: return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Base) else: return pal.color(QtGui.QPalette.Base) - elif role == QtCore.Qt.ForegroundRole: + elif role == QtCore.Qt.ItemDataRole.ForegroundRole: pal = QtGui.QGuiApplication.palette() if not self.mask[row]: return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Text) @@ -289,7 +292,7 @@ class ValueModel(QtCore.QAbstractTableModel): else: return - def setData(self, idx: QtCore.QModelIndex, value: str | bool, role=QtCore.Qt.DisplayRole) -> Any: + def setData(self, idx: QtCore.QModelIndex, value: str | bool, role=QtCore.Qt.ItemDataRole.DisplayRole) -> Any: col, row = idx.column(), idx.row() if role == ValueModel.maskRole: @@ -299,7 +302,7 @@ class ValueModel(QtCore.QAbstractTableModel): return True if value: - if role == QtCore.Qt.EditRole: + if role == QtCore.Qt.ItemDataRole.EditRole: if value == self.as_string(self._data[row][col]): return True @@ -322,9 +325,9 @@ class ValueModel(QtCore.QAbstractTableModel): else: return False - def headerData(self, section: int, orientation, role=QtCore.Qt.DisplayRole) -> Any: - if role == QtCore.Qt.DisplayRole: - if orientation == QtCore.Qt.Horizontal: + def headerData(self, section: int, orientation, role=QtCore.Qt.ItemDataRole.DisplayRole) -> Any: + if role == QtCore.Qt.ItemDataRole.DisplayRole: + if orientation == QtCore.Qt.Orientation.Horizontal: return self.headers[section] else: return str(section+1) @@ -346,7 +349,7 @@ class ValueModel(QtCore.QAbstractTableModel): self.endInsertRows() def flags(self, idx: QtCore.QModelIndex) -> QtCore.Qt.ItemFlag: - return QtCore.QAbstractTableModel.flags(self, idx) | QtCore.Qt.ItemIsEditable + return QtCore.QAbstractTableModel.flags(self, idx) | QtCore.Qt.ItemFlag.ItemIsEditable def removeRows(self, pos: int, rows: int, parent=None, *args, **kwargs) -> bool: self.beginRemoveRows(parent, pos, pos+rows-1) diff --git a/src/gui_qt/graphs/graphwindow.py b/src/gui_qt/graphs/graphwindow.py index 9369bf3..405e520 100644 --- a/src/gui_qt/graphs/graphwindow.py +++ b/src/gui_qt/graphs/graphwindow.py @@ -670,11 +670,14 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow): else: if os.path.exists(outfile): - if QtWidgets.QMessageBox.warning(self, 'Export graphic', - f'{os.path.split(outfile)[1]} already exists.\n' - f'Do you REALLY want to replace it?', - QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, - QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No: + if QtWidgets.QMessageBox.warning( + self, + 'Export graphic', + f'{os.path.split(outfile)[1]} already exists.\n' + f'Do you REALLY want to replace it?', + QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, + QtWidgets.QMessageBox.No + ) == QtWidgets.QMessageBox.No: return bg_color = self._bgcolor @@ -716,16 +719,20 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow): logger.exception(f'{item} could not exported because {e.args}') continue - if len(item) == 2: - # plot can show errorbars - item_dic['yerr'] = item[1].opts['topData'] - if item_dic: + if len(item) == 2: + # plot can show errorbars + if len(item_dic['x']): + item_dic['yerr'] = item[1].opts['topData'] + else: + item_dic['yerr'] = [] dic['items'].append(item_dic) for item in self._external_items: try: - dic['items'].append(item.get_data_opts()) + item_dic = item.get_data_opts() + if item_dic: + dic['items'].append(item_dic) except Exception as e: logger.exception(f'{item} could not be exported because {e.args}') continue diff --git a/src/gui_qt/lib/pg_objects.py b/src/gui_qt/lib/pg_objects.py index 923ca88..fa678e1 100644 --- a/src/gui_qt/lib/pg_objects.py +++ b/src/gui_qt/lib/pg_objects.py @@ -183,6 +183,8 @@ class PlotItem(PlotDataItem): brush = self.opts['symbolBrush'] if isinstance(brush, tuple): self.opts['symbolcolor'] = brush + elif isinstance(brush, str): + self.opts['symbolcolor'] = int(f'0x{brush[1:3]}', 16), int(f'0x{brush[3:5]}', 16), int(f'0x{brush[5:7]}', 16) else: c = brush.color() self.opts['symbolcolor'] = c.red(), c.green(), c.blue() @@ -340,7 +342,8 @@ class PlotItem(PlotDataItem): opts = self.opts item_dic = { - 'x': x, 'y': y, + 'x': x, + 'y': y, 'name': opts.get('name', ''), 'symbolsize': opts['symbolSize'], }