more_bugs (#51)

closes #46, #47, #7

Co-authored-by: Dominik Demuth <dominik.demuth@physik.tu-darmstadt.de>
Reviewed-on: #51
This commit is contained in:
Dominik Demuth 2023-04-16 15:40:58 +00:00
parent bb3d5ac58b
commit 59625c1581
6 changed files with 142 additions and 57 deletions

View File

@ -70,12 +70,12 @@ class Ui_BaseWindow(object):
self.integralwidget = IntegralWidget()
self.integralwidget.setObjectName("integralwidget")
self.tabWidget.addTab(self.integralwidget, "")
self.area = QtWidgets.QMdiArea(self.splitter)
self.area = MdiAreaTile(self.splitter)
self.area.setObjectName("area")
self.horizontalLayout.addWidget(self.splitter)
BaseWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(BaseWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1386, 20))
self.menubar.setGeometry(QtCore.QRect(0, 0, 1386, 22))
self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
@ -261,6 +261,10 @@ class Ui_BaseWindow(object):
self.actionMaximize.setObjectName("actionMaximize")
self.actionTile = QtWidgets.QAction(BaseWindow)
self.actionTile.setObjectName("actionTile")
self.actionTileVertical = QtWidgets.QAction(BaseWindow)
self.actionTileVertical.setObjectName("actionTileVertical")
self.actionTileHorizontal = QtWidgets.QAction(BaseWindow)
self.actionTileHorizontal.setObjectName("actionTileHorizontal")
self.actionMinimize = QtWidgets.QAction(BaseWindow)
self.actionMinimize.setCheckable(True)
self.actionMinimize.setVisible(False)
@ -428,6 +432,8 @@ class Ui_BaseWindow(object):
self.menuOptions.addAction(self.actionConfiguration)
self.menuOptions.addAction(self.actionCreate_starter)
self.menuView.addAction(self.actionTile)
self.menuView.addAction(self.actionTileVertical)
self.menuView.addAction(self.actionTileHorizontal)
self.menuView.addAction(self.actionCascade_windows)
self.menuWindow.addAction(self.actionNew_window)
self.menuWindow.addAction(self.actionDelete_window)
@ -571,6 +577,8 @@ class Ui_BaseWindow(object):
self.actionGuide_lines.setText(_translate("BaseWindow", "Draw lines..."))
self.actionMaximize.setText(_translate("BaseWindow", "Maximize"))
self.actionTile.setText(_translate("BaseWindow", "Tile windows"))
self.actionTileVertical.setText(_translate("BaseWindow", "Tile windows vertically"))
self.actionTileHorizontal.setText(_translate("BaseWindow", "Tile windows horizontally"))
self.actionMinimize.setText(_translate("BaseWindow", "Minimize"))
self.actionNew_window.setText(_translate("BaseWindow", "New graph"))
self.actionDelete_window.setText(_translate("BaseWindow", "Delete graph"))
@ -626,4 +634,5 @@ from ..data.signaledit.editsignalwidget import EditSignalWidget
from ..data.valueeditwidget import ValueEditWidget
from ..fit.fitwindow import QFitDialog
from ..graphs.drawings import DrawingsWidget
from ..lib.mdiarea import MdiAreaTile
from ..nmr.t1widget import QT1Widget

50
src/gui_qt/lib/mdiarea.py Normal file
View File

@ -0,0 +1,50 @@
from __future__ import annotations
from ..Qt import QtWidgets, QtCore
from nmreval.lib.logger import logger
from ..graphs.graphwindow import QGraphWindow
class MdiAreaTile(QtWidgets.QMdiArea):
def __init__(self, parent=None):
super().__init__(parent=parent)
def tileSubWindowsVertically(self):
window_list = self.subWindowList()
rect = QtCore.QRect(0, 0, self.width(), int(self.height() / len(window_list)))
pos = QtCore.QPoint(0, 0)
for win in window_list:
win.setGeometry(rect)
win.move(pos)
pos.setY(pos.y() + win.height())
def tileSubWindowsHorizontally(self):
window_list = self.subWindowList()
rect = QtCore.QRect(0, 0, int(self.width() / len(window_list)), self.height())
pos = QtCore.QPoint(0, 0)
for win in window_list:
print(win.minimumSize())
win.setGeometry(rect)
win.move(pos)
pos.setX(pos.x() + win.width())
def addSubWindow(self, widget: QtWidgets.QWidget, flags: QtCore.Qt.WindowFlags = QtCore.Qt.WindowFlags()) -> QtWidgets.QMdiSubWindow | None:
subwindow = super().addSubWindow(widget)
subwindow.setOption(QtWidgets.QMdiSubWindow.RubberBandMove, True)
subwindow.setOption(QtWidgets.QMdiSubWindow.RubberBandResize, True)
subwindow.setMinimumHeight(240)
subwindow.setMinimumWidth(360)
return subwindow
def setActiveSubWidget(self, key: str):
for win in self.subWindowList():
wdgt = win.widget()
if isinstance(wdgt, QGraphWindow) and wdgt.id == key:
self.setActiveSubWindow(win)
break

View File

@ -6,7 +6,7 @@ import numpy as np
from ..Qt import QtWidgets, QtCore, QtGui
__all__ = ['Game']
__all__ = ['Game', 'QMines']
class Game(QtWidgets.QDialog):

View File

@ -2,7 +2,6 @@ from __future__ import annotations
import datetime
import os
import pathlib
import re
from pathlib import Path
@ -115,7 +114,10 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.mousepos = QtWidgets.QLabel('')
self.status = QtWidgets.QLabel('')
# noinspection PyUnresolvedReferences
self.statusBar.addWidget(self.status)
# noinspection PyUnresolvedReferences
self.statusBar.addWidget(self.mousepos)
self.fitregion = RegionItem()
@ -151,8 +153,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.actionUndo.setIcon(icon)
self.menuData.insertAction(self.actionRedo, self.actionUndo)
# self.actionSave.triggered.connect(lambda: self.management.save('/autohome/dominik/nmreval/testdata/test.nmr', ''))
# self.actionSave.triggered.connect(self.save)
self.action_save_fit_parameter.triggered.connect(self.save_fit_parameter)
self.ac_group2.triggered.connect(self.change_fit_limits)
@ -165,6 +165,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.action_new_set.triggered.connect(self.management.create_empty)
self.actionDelete_window.triggered.connect(self.management.delete_sets)
self.actionCascade_windows.triggered.connect(self.area.cascadeSubWindows)
self.actionTile.triggered.connect(self.area.tileSubWindows)
self.actionTileHorizontal.triggered.connect(self.area.tileSubWindowsHorizontally)
self.actionTileVertical.triggered.connect(self.area.tileSubWindowsVertically)
self.datawidget.keyChanged.connect(self.management.change_keys)
self.datawidget.tree.deleteItem.connect(self.management.delete_sets)
self.datawidget.tree.moveItem.connect(self.management.move_sets)
@ -178,7 +184,8 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.datawidget.tree.saveFits.connect(self.save_fit_parameter)
self.datawidget.tree.extendFits.connect(self.extend_fit)
self.management.newData.connect(self.show_new_data)
self.management.newData[list, str].connect(self.show_new_data)
self.management.newData[list, str, bool].connect(self.show_new_data)
self.management.newGraph.connect(self.new_graph)
self.management.dataChanged.connect(self.update_data)
self.management.deleteData.connect(self.delete_data)
@ -191,13 +198,14 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.fit_dialog._management = self.management
self.fit_dialog.preview_emit.connect(self.show_fit_preview)
self.fit_dialog.fitStartSig.connect(self.start_fit)
self.fit_dialog.abortFit.connect(lambda : self.management.stopFit.emit())
self.fit_dialog.abortFit.connect(lambda: self.management.stopFit.emit())
self.movedialog.moveData.connect(self.move_sets)
self.movedialog.copyData.connect(self.management.copy_sets)
self.ptsselectwidget.points_selected.connect(self.management.extract_points)
self.t1tauwidget.newData.connect(self.management.add_new_data)
self.t1tauwidget.newData.connect(self.management.add_new_data)
self.editsignalwidget.do_something.connect(self.management.apply)
@ -279,7 +287,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
use_underscore = save_dialog.checkBox.isChecked()
self.management.save(savefile, selected_filter, strip_spaces=use_underscore)
param_outfile = re.sub('[_\s-]?<label>[_\s-]?', '', savefile.stem)
param_outfile = re.sub(r'[_\s-]?<label>[_\s-]?', '', savefile.stem)
bad_character = r'/*<>\|:"'
for c in bad_character:
@ -321,10 +329,15 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
return w.id
@QtCore.pyqtSlot(list, str)
def show_new_data(self, sets: list, graph: str):
@QtCore.pyqtSlot(list, str, bool)
def show_new_data(self, sets: list, graph: str, skip_change: bool = False):
if len(sets) == 0:
return
prev_graph = ''
if skip_change:
prev_graph = self.management.current_graph
if graph == '':
graph = self.new_graph()
@ -336,16 +349,14 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.datawidget.add_item(new_item.id, new_item.name, graph)
self.datawidget.blockSignals(False)
if graph == self.fit_dialog.connected_figure:
self.fit_dialog.load(self.management.graphs.active(graph))
# if graph == self.fit_dialog.connected_figure:
# self.fit_dialog.load(self.management.graphs.active(graph))
if skip_change:
self.area.setActiveSubWidget(prev_graph)
if self.valuewidget.isVisible():
self.valuewidget(self.management.graphs.tree())
@QtCore.pyqtSlot(name='on_actionDelete_window_triggered')
def delete_windows(self):
self.management.delete_sets()
@QtCore.pyqtSlot(str)
def remove_graph(self, gid: str):
self.datawidget.remove_item([gid])
@ -389,7 +400,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
break
if w is not None:
self.area.removeSubWindow(w)
w.close()
@ -419,7 +429,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.datawidget.blockSignals(False)
w.mousePositionChanged.connect(self.mousemoved)
w.aboutToClose.connect(self.delete_windows)
w.aboutToClose.connect(self.management.delete_sets)
w.positionClicked.connect(self.point_selected)
w.show()
@ -430,7 +440,9 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
@QtCore.pyqtSlot(QtWidgets.QMdiSubWindow, name='on_area_subWindowActivated')
def change_window(self, wd):
""" Called every time focus moves from or to a subwindow. Returns None if current focus is not on a subwindow"""
if wd is not None:
if wd is None:
return
if self.current_graph_widget is not None:
self.current_graph_widget.closable = True
@ -459,14 +471,6 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.datawidget.tree.highlight(self.management.current_graph)
self.datawidget.tree.blockSignals(False)
@QtCore.pyqtSlot(name='on_actionCascade_windows_triggered')
@QtCore.pyqtSlot(name='on_actionTile_triggered')
def change_window_size(self):
if self.sender() == self.actionCascade_windows:
self.area.cascadeSubWindows()
elif self.sender() == self.actionTile:
self.area.tileSubWindows()
@QtCore.pyqtSlot(name='on_actionChange_datatypes_triggered')
def type_change_dialog(self):
from ..data.conversion import ConversionDialog
@ -558,8 +562,9 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.management.graphs[current_graph].add_external(self.valuewidget.selection_imag)
else:
if self.valuewidget.connected_figure is not None:
self.management.graphs[self.valuewidget.connected_figure].remove_external(self.valuewidget.selection_real)
self.management.graphs[self.valuewidget.connected_figure].remove_external(self.valuewidget.selection_imag)
conn_fig = self.valuewidget.connected_figure
self.management.graphs[conn_fig].remove_external(self.valuewidget.selection_real)
self.management.graphs[conn_fig].remove_external(self.valuewidget.selection_imag)
def _select_integralwidget(self, onoff: bool, pick_required: bool, block_window: bool) -> tuple[bool, bool]:
if self.current_graph_widget is None:
@ -623,6 +628,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
@QtCore.pyqtSlot(str)
def get_data(self, key: str):
if hasattr(self.sender(), 'set_data'):
self.sender().set_data(self.management[key])
@QtCore.pyqtSlot(name='on_actionCalculateT1_triggered')
@ -832,6 +838,7 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
except KeyError:
ret_val = None
# noinspection PyUnresolvedReferences
self.sender().receive_data(ret_val)
return ret_val
@ -928,7 +935,8 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
res_dialog.show()
@QtCore.pyqtSlot(dict, list, str, bool, bool, list)
def accepts_fit(self, res: dict, opts: list, param_graph: str, show_fit: bool, parts: bool, extrapolate: list) -> None:
def accepts_fit(self, res: dict, opts: list, param_graph: str,
show_fit: bool, parts: bool, extrapolate: list) -> None:
self.fit_dialog.set_parameter(res)
self.management.make_fits(res, opts, param_graph, show_fit, parts, extrapolate)

View File

@ -74,7 +74,7 @@ class UpperManagement(QtCore.QObject):
newGraph = QtCore.pyqtSignal()
restoreGraph = QtCore.pyqtSignal(str)
deleteGraph = QtCore.pyqtSignal(str)
newData = QtCore.pyqtSignal(list, str)
newData = QtCore.pyqtSignal([list, str], [list, str, bool])
deleteData = QtCore.pyqtSignal(list)
dataChanged = QtCore.pyqtSignal(str)
fitFinished = QtCore.pyqtSignal(list)
@ -287,6 +287,7 @@ class UpperManagement(QtCore.QObject):
@QtCore.pyqtSlot(list)
@QtCore.pyqtSlot(str)
@QtCore.pyqtSlot()
def delete_sets(self, rm_sets: list = None):
rm_graphs = []
@ -624,8 +625,7 @@ class UpperManagement(QtCore.QObject):
if not graph_id:
graph_id = ''
# TODO add flag that new window will not get focus, because it messes up the data_table in fitwindow
self.newData.emit(p_id_list, graph_id)
self.newData[list, str, bool].emit(p_id_list, graph_id, True)
def save_fit_parameter(self, fname: str | pathlib.Path, fit_sets: list[str] = None):
if fit_sets is None:

View File

@ -125,7 +125,7 @@
</attribute>
</widget>
</widget>
<widget class="QMdiArea" name="area"/>
<widget class="MdiAreaTile" name="area"/>
</widget>
</item>
</layout>
@ -136,7 +136,7 @@
<x>0</x>
<y>0</y>
<width>1386</width>
<height>20</height>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@ -274,6 +274,8 @@
<string>View</string>
</property>
<addaction name="actionTile"/>
<addaction name="actionTileVertical"/>
<addaction name="actionTileHorizontal"/>
<addaction name="actionCascade_windows"/>
</widget>
<addaction name="actionNew_window"/>
@ -743,6 +745,16 @@
<string>Tile windows</string>
</property>
</action>
<action name="actionTileVertical">
<property name="text">
<string>Tile windows vertically</string>
</property>
</action>
<action name="actionTileHorizontal">
<property name="text">
<string>Tile windows horizontally</string>
</property>
</action>
<action name="actionMinimize">
<property name="checkable">
<bool>true</bool>
@ -1060,6 +1072,12 @@
<header>..data.integral_widget</header>
<container>1</container>
</customwidget>
<customwidget>
<class>MdiAreaTile</class>
<extends>QFrame</extends>
<header>..lib.mdiarea</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>