diff --git a/src/gui_qt/_py/basewindow.py b/src/gui_qt/_py/basewindow.py
index 42d4e34..a5e7ab9 100644
--- a/src/gui_qt/_py/basewindow.py
+++ b/src/gui_qt/_py/basewindow.py
@@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'src/resources/_ui/basewindow.ui'
#
-# Created by: PyQt5 UI code generator 5.15.7
+# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
@@ -75,7 +75,7 @@ class Ui_BaseWindow(object):
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, 24))
self.menubar.setObjectName("menubar")
self.menuFile = QtWidgets.QMenu(self.menubar)
self.menuFile.setObjectName("menuFile")
@@ -413,7 +413,6 @@ class Ui_BaseWindow(object):
self.menuFit.addAction(self.action_create_fit_function)
self.menuFit.addAction(self.actionFunction_editor)
self.menuFit.addSeparator()
- self.menuFit.addAction(self.actionShow_fit_parameter)
self.menuFit.addAction(self.menuMethod.menuAction())
self.menuFit.addAction(self.menuLimits.menuAction())
self.menuOptions.addAction(self.actionMouse_behaviour)
@@ -480,7 +479,7 @@ class Ui_BaseWindow(object):
self.retranslateUi(BaseWindow)
self.tabWidget.setCurrentIndex(0)
- self.action_close.triggered.connect(BaseWindow.close) # type: ignore
+ self.action_close.triggered.connect(BaseWindow.close)
QtCore.QMetaObject.connectSlotsByName(BaseWindow)
def retranslateUi(self, BaseWindow):
diff --git a/src/gui_qt/fit/function_creation_dialog.py b/src/gui_qt/fit/function_creation_dialog.py
index 8d6c2a0..b63ee29 100644
--- a/src/gui_qt/fit/function_creation_dialog.py
+++ b/src/gui_qt/fit/function_creation_dialog.py
@@ -2,7 +2,8 @@ from __future__ import annotations
import inspect
import numbers
-import textwrap
+import pathlib
+import re
from typing import Any
import numpy as np
@@ -14,15 +15,18 @@ from gui_qt.lib.namespace import QNamespaceWidget
__all__ = ['QUserFitCreator']
validator = QtGui.QRegExpValidator(QtCore.QRegExp('[A-Za-z]\S*'))
+pattern = re.compile(r'def func\(.*\):', flags=re.MULTILINE)
class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
- classCreated = QtCore.pyqtSignal(object)
+ classCreated = QtCore.pyqtSignal()
- def __init__(self, parent=None):
+ def __init__(self, filepath: str|pathlib.Path, parent=None):
super().__init__(parent=parent)
self.setupUi(self)
+ self.filepath = pathlib.Path(filepath)
+
self.description_widget = DescWidget(self)
self.args_widget = ArgWidget(self)
self.kwargs_widget = KwargsWidget(self)
@@ -44,10 +48,23 @@ class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
self.update_function()
- def __call__(self, *args, **kwargs):
+ def __call__(self, filepath: str|pathlib.Path):
+ self.filepath = pathlib.Path(filepath)
+
return self
def update_function(self):
+ prev_text = self.plainTextEdit.toPlainText().split('\n')
+ func_body = ''
+ in_body = False
+ for line in prev_text:
+ if in_body:
+ func_body += line
+ continue
+
+ if pattern.search(line) is not None:
+ in_body = True
+
try:
var = self.args_widget.get_parameter()
var += self.kwargs_widget.get_parameter()
@@ -67,7 +84,12 @@ class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
k += self.kwargs_widget.get_strings()
k += '\n @staticmethod\n'
- k += f" def func(x, {', '.join(var)}):\n"
+ if var:
+ k += f" def func(x, {', '.join(var)}):\n"
+ else:
+ k += f' def func(x):\n'
+
+ k += func_body
self.plainTextEdit.setPlainText(k)
except Exception as e:
@@ -85,6 +107,7 @@ class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
ns = self.namespace_widget.namespace.namespace
func_value = ns[invalue][0]
ret_func = ''
+ import_name = ''
if func_value is None:
ret_func = invalue
@@ -99,15 +122,28 @@ class QUserFitCreator(QtWidgets.QDialog, Ui_Dialog):
else:
f_string = ns[invalue][-1]
args = f_string[f_string.find('('):]
+
if inspect.ismethod(func_value):
ret_func = func_value.__self__.__name__ + '.func'+args
+ import_name = func_value.__self__.__name__
+
elif hasattr(func_value, '__qualname__'):
- ret_func = func_value.__qualname__.split('.')[0]
- self._imports.add((inspect.getmodule(func_value).__name__, ret_func))
+ import_name = func_value.__qualname__.split('.')[0]
+ ret_func = func_value.__qualname__ + args
+
+ self._imports.add((inspect.getmodule(func_value).__name__, import_name))
self.plainTextEdit.insertPlainText(ret_func)
self.update_function()
+ def accept(self):
+ # maybe add a check for correctness
+
+ with self.filepath.open('a') as f:
+ f.write('\n\n')
+ f.write(self.plainTextEdit.toPlainText())
+ self.classCreated.emit()
+ super().accept()
class KwargsWidget(QtWidgets.QWidget):
Changed = QtCore.pyqtSignal()
@@ -363,7 +399,7 @@ class ArgWidget(QtWidgets.QWidget):
return var
- def get_strings(self):
+ def get_strings(self) -> str:
args = []
bnds = []
for row in range(self.table.rowCount()):
@@ -434,7 +470,7 @@ class DescWidget(QtWidgets.QWidget):
raise ValueError('Class name is empty')
stringi = f'class {self.klass_lineedit.text()}:\n' \
f' name = {self.name_lineedit.text()!r}\n' \
- f' group = {self.group_lineedit.text()!r}\n' \
+ f' type = {self.group_lineedit.text()!r}\n' \
f' equation = {self.eq_lineedit.text()!r}\n'
return stringi
diff --git a/src/gui_qt/lib/utils.py b/src/gui_qt/lib/utils.py
index bafa3c6..c632038 100644
--- a/src/gui_qt/lib/utils.py
+++ b/src/gui_qt/lib/utils.py
@@ -13,7 +13,7 @@ import requests
from numpy import linspace
from scipy.interpolate import interp1d
-from gui_qt.Qt import QtGui, QtWidgets, QtCore
+from ..Qt import QtGui, QtWidgets, QtCore
@contextmanager
diff --git a/src/gui_qt/main/mainwindow.py b/src/gui_qt/main/mainwindow.py
index 1ccad4a..c9fc62b 100644
--- a/src/gui_qt/main/mainwindow.py
+++ b/src/gui_qt/main/mainwindow.py
@@ -917,6 +917,16 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.editor.setWindowModality(QtCore.Qt.ApplicationModal)
self.editor.show()
+ @QtCore.pyqtSlot(name='on_action_create_fit_function_triggered')
+ def open_fitmodel_wizard(self):
+ from ..fit.function_creation_dialog import QUserFitCreator
+
+ helper = QUserFitCreator(config_paths() / 'usermodels.py', parent=self)
+ helper.classCreated.connect(lambda: self.fit_dialog.read_and_load_functions())
+
+ helper.show()
+
+
@QtCore.pyqtSlot(name='on_actionShift_triggered')
def shift_dialog(self):
s = QShift(self)
diff --git a/src/resources/_ui/basewindow.ui b/src/resources/_ui/basewindow.ui
index d80e9f0..0cb9372 100644
--- a/src/resources/_ui/basewindow.ui
+++ b/src/resources/_ui/basewindow.ui
@@ -136,7 +136,7 @@
0
0
1386
- 20
+ 24