handle graph export with empty data #239
@ -3,10 +3,10 @@ from __future__ import annotations
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from numpy import ndarray, iscomplexobj, asarray
|
from numpy import ndarray, iscomplexobj, asarray
|
||||||
from pyqtgraph import PlotDataItem
|
|
||||||
|
|
||||||
from ..Qt import QtGui, QtCore, QtWidgets
|
from ..Qt import QtGui, QtCore, QtWidgets
|
||||||
from .._py.valueeditor import Ui_MaskDialog
|
from .._py.valueeditor import Ui_MaskDialog
|
||||||
|
from ..lib.pg_objects import PlotItem
|
||||||
|
|
||||||
|
|
||||||
class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
||||||
@ -35,12 +35,12 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
|||||||
|
|
||||||
self.tableView.setModel(self.model)
|
self.tableView.setModel(self.model)
|
||||||
self.tableView.setSelectionModel(self.selection_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.tableView.customContextMenuRequested.connect(self.ctx)
|
||||||
|
|
||||||
self.selection_real = PlotDataItem(x=[], y=[], symbolSize=25, symbol='x',
|
self.selection_real = PlotItem(x=[], y=[], symbolSize=25, symbol='x',
|
||||||
pen=None, symbolPen='#c9308e', symbolBrush='#c9308e')
|
pen=None, symbolPen='#c9308e', symbolBrush='#c9308e')
|
||||||
self.selection_imag = PlotDataItem(x=[], y=[], symbolSize=25, symbol='+',
|
self.selection_imag = PlotItem(x=[], y=[], symbolSize=25, symbol='+',
|
||||||
pen=None, symbolPen='#dcdcdc', symbolBrush='#dcdcdc')
|
pen=None, symbolPen='#dcdcdc', symbolBrush='#dcdcdc')
|
||||||
|
|
||||||
def __call__(self, items: dict):
|
def __call__(self, items: dict):
|
||||||
@ -133,7 +133,7 @@ class ValueEditWidget(QtWidgets.QWidget, Ui_MaskDialog):
|
|||||||
def keyPressEvent(self, evt):
|
def keyPressEvent(self, evt):
|
||||||
if evt.matches(QtGui.QKeySequence.Copy):
|
if evt.matches(QtGui.QKeySequence.Copy):
|
||||||
self.copy_selection()
|
self.copy_selection()
|
||||||
elif evt.key() == QtCore.Qt.Key_Delete:
|
elif evt.key() == QtCore.Qt.Key.Key_Delete:
|
||||||
self.delete_item()
|
self.delete_item()
|
||||||
else:
|
else:
|
||||||
super().keyPressEvent(evt)
|
super().keyPressEvent(evt)
|
||||||
@ -229,7 +229,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
"""
|
"""
|
||||||
itemChanged = QtCore.pyqtSignal(int, int, str)
|
itemChanged = QtCore.pyqtSignal(int, int, str)
|
||||||
load_number = 20
|
load_number = 20
|
||||||
maskRole = QtCore.Qt.UserRole+321
|
maskRole = QtCore.Qt.ItemDataRole.UserRole+321
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent=parent)
|
super().__init__(parent=parent)
|
||||||
@ -240,7 +240,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
self.mask = None
|
self.mask = None
|
||||||
self.headers = ['x', 'y', '\u0394y']
|
self.headers = ['x', 'y', '\u0394y']
|
||||||
for i, hd in enumerate(self.headers):
|
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:
|
def rowCount(self, *args, **kwargs) -> int:
|
||||||
return self.total_rows
|
return self.total_rows
|
||||||
@ -258,25 +258,28 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
self.mask = mask.tolist()
|
self.mask = mask.tolist()
|
||||||
|
|
||||||
self.endResetModel()
|
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():
|
if not idx.isValid():
|
||||||
return
|
return
|
||||||
|
|
||||||
row = idx.row()
|
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()]
|
val = self._data[row][idx.column()]
|
||||||
return self.as_string(val)
|
return self.as_string(val)
|
||||||
|
|
||||||
elif role == QtCore.Qt.BackgroundRole:
|
elif role == QtCore.Qt.ItemDataRole.BackgroundRole:
|
||||||
pal = QtGui.QGuiApplication.palette()
|
pal = QtGui.QGuiApplication.palette()
|
||||||
if not self.mask[row]:
|
if not self.mask[row]:
|
||||||
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Base)
|
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Base)
|
||||||
else:
|
else:
|
||||||
return pal.color(QtGui.QPalette.Base)
|
return pal.color(QtGui.QPalette.Base)
|
||||||
|
|
||||||
elif role == QtCore.Qt.ForegroundRole:
|
elif role == QtCore.Qt.ItemDataRole.ForegroundRole:
|
||||||
pal = QtGui.QGuiApplication.palette()
|
pal = QtGui.QGuiApplication.palette()
|
||||||
if not self.mask[row]:
|
if not self.mask[row]:
|
||||||
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Text)
|
return pal.color(QtGui.QPalette.Disabled, QtGui.QPalette.Text)
|
||||||
@ -289,7 +292,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
else:
|
else:
|
||||||
return
|
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()
|
col, row = idx.column(), idx.row()
|
||||||
|
|
||||||
if role == ValueModel.maskRole:
|
if role == ValueModel.maskRole:
|
||||||
@ -299,7 +302,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
if value:
|
if value:
|
||||||
if role == QtCore.Qt.EditRole:
|
if role == QtCore.Qt.ItemDataRole.EditRole:
|
||||||
if value == self.as_string(self._data[row][col]):
|
if value == self.as_string(self._data[row][col]):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -322,9 +325,9 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def headerData(self, section: int, orientation, role=QtCore.Qt.DisplayRole) -> Any:
|
def headerData(self, section: int, orientation, role=QtCore.Qt.ItemDataRole.DisplayRole) -> Any:
|
||||||
if role == QtCore.Qt.DisplayRole:
|
if role == QtCore.Qt.ItemDataRole.DisplayRole:
|
||||||
if orientation == QtCore.Qt.Horizontal:
|
if orientation == QtCore.Qt.Orientation.Horizontal:
|
||||||
return self.headers[section]
|
return self.headers[section]
|
||||||
else:
|
else:
|
||||||
return str(section+1)
|
return str(section+1)
|
||||||
@ -346,7 +349,7 @@ class ValueModel(QtCore.QAbstractTableModel):
|
|||||||
self.endInsertRows()
|
self.endInsertRows()
|
||||||
|
|
||||||
def flags(self, idx: QtCore.QModelIndex) -> QtCore.Qt.ItemFlag:
|
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:
|
def removeRows(self, pos: int, rows: int, parent=None, *args, **kwargs) -> bool:
|
||||||
self.beginRemoveRows(parent, pos, pos+rows-1)
|
self.beginRemoveRows(parent, pos, pos+rows-1)
|
||||||
|
@ -670,11 +670,14 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
if os.path.exists(outfile):
|
if os.path.exists(outfile):
|
||||||
if QtWidgets.QMessageBox.warning(self, 'Export graphic',
|
if QtWidgets.QMessageBox.warning(
|
||||||
|
self,
|
||||||
|
'Export graphic',
|
||||||
f'{os.path.split(outfile)[1]} already exists.\n'
|
f'{os.path.split(outfile)[1]} already exists.\n'
|
||||||
f'Do you REALLY want to replace it?',
|
f'Do you REALLY want to replace it?',
|
||||||
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
|
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
|
||||||
QtWidgets.QMessageBox.No) == QtWidgets.QMessageBox.No:
|
QtWidgets.QMessageBox.No
|
||||||
|
) == QtWidgets.QMessageBox.No:
|
||||||
return
|
return
|
||||||
|
|
||||||
bg_color = self._bgcolor
|
bg_color = self._bgcolor
|
||||||
@ -716,16 +719,20 @@ class QGraphWindow(QtWidgets.QGraphicsView, Ui_GraphWindow):
|
|||||||
logger.exception(f'{item} could not exported because {e.args}')
|
logger.exception(f'{item} could not exported because {e.args}')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if item_dic:
|
||||||
if len(item) == 2:
|
if len(item) == 2:
|
||||||
# plot can show errorbars
|
# plot can show errorbars
|
||||||
|
if len(item_dic['x']):
|
||||||
item_dic['yerr'] = item[1].opts['topData']
|
item_dic['yerr'] = item[1].opts['topData']
|
||||||
|
else:
|
||||||
if item_dic:
|
item_dic['yerr'] = []
|
||||||
dic['items'].append(item_dic)
|
dic['items'].append(item_dic)
|
||||||
|
|
||||||
for item in self._external_items:
|
for item in self._external_items:
|
||||||
try:
|
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:
|
except Exception as e:
|
||||||
logger.exception(f'{item} could not be exported because {e.args}')
|
logger.exception(f'{item} could not be exported because {e.args}')
|
||||||
continue
|
continue
|
||||||
|
@ -183,6 +183,8 @@ class PlotItem(PlotDataItem):
|
|||||||
brush = self.opts['symbolBrush']
|
brush = self.opts['symbolBrush']
|
||||||
if isinstance(brush, tuple):
|
if isinstance(brush, tuple):
|
||||||
self.opts['symbolcolor'] = brush
|
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:
|
else:
|
||||||
c = brush.color()
|
c = brush.color()
|
||||||
self.opts['symbolcolor'] = c.red(), c.green(), c.blue()
|
self.opts['symbolcolor'] = c.red(), c.green(), c.blue()
|
||||||
@ -340,7 +342,8 @@ class PlotItem(PlotDataItem):
|
|||||||
|
|
||||||
opts = self.opts
|
opts = self.opts
|
||||||
item_dic = {
|
item_dic = {
|
||||||
'x': x, 'y': y,
|
'x': x,
|
||||||
|
'y': y,
|
||||||
'name': opts.get('name', ''),
|
'name': opts.get('name', ''),
|
||||||
'symbolsize': opts['symbolSize'],
|
'symbolsize': opts['symbolSize'],
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user