Creation and editing of data objects

This commit is contained in:
Hanna K 2021-11-08 10:14:53 +01:00
parent 1f715cbd9f
commit 70c4469ac7
6 changed files with 411 additions and 4 deletions

View File

@ -41,9 +41,9 @@ MOC_DIR = build
OBJECTS_DIR = build
DEFINES += VERSION=\\\"$$VERSION\\\"
HEADERS += src/calendarconversiondialog.h src/csvdialog.h src/datasetsdialog.h src/expressionedit.h src/fpconversiondialog.h src/functioneditdialog.h src/functionsdialog.h src/historyview.h src/itemproxymodel.h src/keypadwidget.h src/matrixwidget.h src/percentagecalculationdialog.h src/plotdialog.h src/preferencesdialog.h src/qalculateqtsettings.h src/qalculatewindow.h src/unitsdialog.h src/uniteditdialog.h src/unknowneditdialog.h src/variableeditdialog.h src/variablesdialog.h
HEADERS += src/calendarconversiondialog.h src/csvdialog.h src/dataseteditdialog.h src/datasetsdialog.h src/expressionedit.h src/fpconversiondialog.h src/functioneditdialog.h src/functionsdialog.h src/historyview.h src/itemproxymodel.h src/keypadwidget.h src/matrixwidget.h src/percentagecalculationdialog.h src/plotdialog.h src/preferencesdialog.h src/qalculateqtsettings.h src/qalculatewindow.h src/unitsdialog.h src/uniteditdialog.h src/unknowneditdialog.h src/variableeditdialog.h src/variablesdialog.h
SOURCES += src/calendarconversiondialog.cpp src/csvdialog.cpp src/datasetsdialog.cpp src/expressionedit.cpp src/fpconversiondialog.cpp src/functioneditdialog.cpp src/functionsdialog.cpp src/historyview.cpp src/itemproxymodel.cpp src/keypadwidget.cpp src/main.cpp src/matrixwidget.cpp src/percentagecalculationdialog.cpp src/plotdialog.cpp src/preferencesdialog.cpp src/qalculateqtsettings.cpp src/qalculatewindow.cpp src/unitsdialog.cpp src/uniteditdialog.cpp src/unknowneditdialog.cpp src/variableeditdialog.cpp src/variablesdialog.cpp
SOURCES += src/calendarconversiondialog.cpp src/csvdialog.cpp src/dataseteditdialog.cpp src/datasetsdialog.cpp src/expressionedit.cpp src/fpconversiondialog.cpp src/functioneditdialog.cpp src/functionsdialog.cpp src/historyview.cpp src/itemproxymodel.cpp src/keypadwidget.cpp src/main.cpp src/matrixwidget.cpp src/percentagecalculationdialog.cpp src/plotdialog.cpp src/preferencesdialog.cpp src/qalculateqtsettings.cpp src/qalculatewindow.cpp src/unitsdialog.cpp src/uniteditdialog.cpp src/unknowneditdialog.cpp src/variableeditdialog.cpp src/variablesdialog.cpp
LANGUAGES = ca de es fr nl pt_BR ru sl sv zh_CN

230
src/dataseteditdialog.cpp Normal file
View File

@ -0,0 +1,230 @@
/*
Qalculate (QT UI)
Copyright (C) 2021 Hanna Knutsson (hanna.knutsson@protonmail.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/
#include <QDialogButtonBox>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QGridLayout>
#include <QTabWidget>
#include <QPushButton>
#include <QLabel>
#include <QLineEdit>
#include <QAction>
#include <QPlainTextEdit>
#include <QComboBox>
#include <QDebug>
#include "qalculateqtsettings.h"
#include "functioneditdialog.h"
#include "dataseteditdialog.h"
DataSetEditDialog::DataSetEditDialog(QWidget *parent) : QDialog(parent) {
o_dataset = NULL;
name_edited = false;
namesEditDialog = NULL;
QVBoxLayout *box = new QVBoxLayout(this);
tabs = new QTabWidget(this);
tabs->setUsesScrollButtons(false);
box->addWidget(tabs);
QWidget *w1 = new QWidget(this);
QWidget *w2 = new QWidget(this);
QWidget *w3 = new QWidget(this);
tabs->addTab(w1, tr("General"));
tabs->addTab(w2, tr("Properties"));
tabs->addTab(w3, tr("Function"));
QGridLayout *grid = new QGridLayout(w1);
grid->addWidget(new QLabel(tr("Title:"), this), 0, 0);
titleEdit = new QLineEdit(this);
grid->addWidget(titleEdit, 0, 1);
grid->addWidget(new QLabel(tr("Data file:"), this), 1, 0);
fileEdit = new QLineEdit(this);
grid->addWidget(fileEdit, 1, 1);
grid->addWidget(new QLabel(tr("Description:"), this), 2, 0, 1, 2);
descriptionEdit = new SmallTextEdit(3, this);
grid->addWidget(descriptionEdit, 5, 0, 1, 2);
grid->addWidget(new QLabel(tr("Copyright:"), this), 4, 0, 1, 2);
copyrightEdit = new SmallTextEdit(3, this);
grid->addWidget(copyrightEdit, 5, 0, 1, 2);
grid = new QGridLayout(w2);
grid = new QGridLayout(w3);
grid->addWidget(new QLabel(tr("Name:"), this), 0, 0);
nameEdit = new QLineEdit(this);
connect(nameEdit->addAction(LOAD_ICON("configure"), QLineEdit::TrailingPosition), SIGNAL(triggered()), this, SLOT(editNames()));
#ifdef _WIN32
# if (QT_VERSION < QT_VERSION_CHECK(6, 2, 0))
nameEdit->setTextMargins(0, 0, 22, 0);
# endif
#endif
grid->addWidget(nameEdit, 0, 1);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok, Qt::Horizontal, this);
buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
buttonBox->button(QDialogButtonBox::Cancel)->setAutoDefault(false);
okButton = buttonBox->button(QDialogButtonBox::Ok);
box->addWidget(buttonBox);
nameEdit->setFocus();
connect(nameEdit, SIGNAL(textEdited(const QString&)), this, SLOT(onNameEdited(const QString&)));
connect(descriptionEdit, SIGNAL(textChanged()), this, SLOT(onDatasetChanged()));
connect(copyrightEdit, SIGNAL(textChanged()), this, SLOT(onDatasetChanged()));
connect(titleEdit, SIGNAL(textEdited(const QString&)), this, SLOT(onDatasetChanged()));
connect(buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject()));
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
okButton->setEnabled(false);
if(settings->always_on_top) setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
}
DataSetEditDialog::~DataSetEditDialog() {}
void DataSetEditDialog::editNames() {
if(!namesEditDialog) {
namesEditDialog = new NamesEditDialog(TYPE_FUNCTION, this, nameEdit->isReadOnly());
namesEditDialog->setNames(o_dataset, nameEdit->text());
}
namesEditDialog->exec();
nameEdit->setText(namesEditDialog->firstName());
name_edited = false;
onDatasetChanged();
}
void DataSetEditDialog::onNameEdited(const QString &str) {
if(!str.trimmed().isEmpty() && !CALCULATOR->functionNameIsValid(str.trimmed().toStdString())) {
nameEdit->setText(QString::fromStdString(CALCULATOR->convertToValidFunctionName(str.trimmed().toStdString())));
}
onDatasetChanged();
name_edited = true;
}
void DataSetEditDialog::onDatasetChanged() {
okButton->setEnabled(!nameEdit->isReadOnly() && !nameEdit->text().trimmed().isEmpty());
}
DataObjectEditDialog::DataObjectEditDialog(DataSet *o, QWidget *parent) : QDialog(parent), ds(o) {
QVBoxLayout *box = new QVBoxLayout(this);
QGridLayout *grid = new QGridLayout();
DataPropertyIter it;
DataProperty *dp = ds->getFirstProperty(&it);
int r = 0;
while(dp) {
grid->addWidget(new QLabel(tr("%1:").arg(QString::fromStdString(dp->title())), this), r, 0);
QLineEdit *w;
if(dp->propertyType() == PROPERTY_EXPRESSION) w = new MathLineEdit(this);
else w = new QLineEdit(this);
valueEdit << w;
grid->addWidget(w, r, 1);
connect(w, SIGNAL(textEdited(const QString&)), this, SLOT(onObjectChanged()));
grid->addWidget(new QLabel(QString::fromStdString(settings->localizeExpression(dp->getUnitString(), true)), this), r, 2);
QComboBox *combo = NULL;
if(dp->propertyType() != PROPERTY_STRING) {
combo = new QComboBox(this);
combo->setEditable(false);
combo->addItem(tr("Default"));
combo->addItem(tr("Approximate"));
combo->addItem(tr("Exact"));
combo->setCurrentIndex(0);
grid->addWidget(combo, r, 3);
connect(combo, SIGNAL(activated(int)), this, SLOT(onObjectChanged()));
}
approxCombo << combo;
r++;
dp = ds->getNextProperty(&it);
}
if(!valueEdit.isEmpty()) valueEdit.at(0)->setFocus();
grid->setColumnStretch(1, 1);
box->addLayout(grid);
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok, Qt::Horizontal, this);
buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
buttonBox->button(QDialogButtonBox::Cancel)->setAutoDefault(false);
okButton = buttonBox->button(QDialogButtonBox::Ok);
box->addWidget(buttonBox);
connect(buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(reject()));
connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
okButton->setEnabled(false);
if(settings->always_on_top) setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
}
DataObjectEditDialog::~DataObjectEditDialog() {}
void DataObjectEditDialog::onObjectChanged() {
okButton->setEnabled(!valueEdit.isEmpty() && !valueEdit.at(0)->isReadOnly());
}
void DataObjectEditDialog::setObject(DataObject *obj) {
DataPropertyIter it;
DataProperty *dp = ds->getFirstProperty(&it);
int r = 0;
while(dp) {
QLineEdit *w = valueEdit.at(r);
QComboBox *combo = approxCombo.at(r);
int iapprox = -1;
w->setReadOnly(!obj->isUserModified());
w->setText(QString::fromStdString(settings->localizeExpression(obj->getProperty(dp, &iapprox))));
if(combo) {
combo->setCurrentIndex(iapprox < 0 ? 0 : (iapprox > 0 ? 2 : 1));
}
r++;
dp = ds->getNextProperty(&it);
}
okButton->setEnabled(false);
}
DataObject *DataObjectEditDialog::createObject() {
DataPropertyIter it;
DataObject *obj = new DataObject(ds);
ds->addObject(obj);
DataProperty *dp = ds->getFirstProperty(&it);
int r = 0;
while(dp) {
if(valueEdit.at(r)->text().trimmed().isEmpty()) {
obj->eraseProperty(dp);
} else {
obj->setProperty(dp, settings->unlocalizeExpression(valueEdit.at(r)->text().trimmed().toStdString()), approxCombo.at(r) ? approxCombo.at(r)->currentIndex() - 1 : -1);
}
r++;
dp = ds->getNextProperty(&it);
}
obj->setUserModified();
return obj;
}
bool DataObjectEditDialog::modifyObject(DataObject *obj) {
DataPropertyIter it;
DataProperty *dp = ds->getFirstProperty(&it);
int r = 0;
while(dp) {
if(valueEdit.at(r)->text().trimmed().isEmpty()) {
obj->eraseProperty(dp);
} else {
obj->setProperty(dp, settings->unlocalizeExpression(valueEdit.at(r)->text().trimmed().toStdString()), approxCombo.at(r) ? approxCombo.at(r)->currentIndex() - 1 : -1);
}
r++;
dp = ds->getNextProperty(&it);
}
obj->setUserModified();
return true;
}
bool DataObjectEditDialog::editObject(QWidget *parent, DataObject *obj) {
DataObjectEditDialog *d = new DataObjectEditDialog(obj->parentSet(), parent);
d->setWindowTitle(tr("Edit Data Object"));
d->setObject(obj);
while(d->exec() == QDialog::Accepted) {
if(d->modifyObject(obj)) {
d->deleteLater();
return true;
}
}
d->deleteLater();
return false;
}
DataObject *DataObjectEditDialog::newObject(QWidget *parent, DataSet *o) {
DataObjectEditDialog *d = new DataObjectEditDialog(o, parent);
d->setWindowTitle(tr("New Data Object"));
DataObject *obj = NULL;
while(d->exec() == QDialog::Accepted) {
obj = d->createObject();
if(obj) break;
}
d->deleteLater();
return obj;
}

84
src/dataseteditdialog.h Normal file
View File

@ -0,0 +1,84 @@
/*
Qalculate (QT UI)
Copyright (C) 2021 Hanna Knutsson (hanna.knutsson@protonmail.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/
#ifndef DATASETEDIT_DIALOG_H
#define DATASETEDIT_DIALOG_H
#include <QDialog>
#include <QVector>
#include <libqalculate/qalculate.h>
class QLineEdit;
class QPlainTextEdit;
class QTabWidget;
class NamesEditDialog;
class QPushButton;
class QComboBox;
class DataSetEditDialog : public QDialog {
Q_OBJECT
protected:
QTabWidget *tabs;
QLineEdit *nameEdit, *titleEdit, *fileEdit;
QPlainTextEdit *descriptionEdit, *copyrightEdit;
QPushButton *okButton;
NamesEditDialog *namesEditDialog;
DataSet *o_dataset;
bool name_edited;
protected slots:
void onDatasetChanged();
void onNameEdited(const QString&);
void editNames();
public:
DataSetEditDialog(QWidget *parent = NULL);
virtual ~DataSetEditDialog();
};
class DataObjectEditDialog : public QDialog {
Q_OBJECT
protected:
QVector<QLineEdit*> valueEdit;
QVector<QComboBox*> approxCombo;
QPushButton *okButton;
DataSet *ds;
protected slots:
void onObjectChanged();
public:
DataObjectEditDialog(DataSet*, QWidget *parent = NULL);
virtual ~DataObjectEditDialog();
DataObject *createObject();
bool modifyObject(DataObject*);
void setObject(DataObject*);
static bool editObject(QWidget *parent, DataObject*);
static DataObject *newObject(QWidget *parent, DataSet*);
};
#endif //DATASETEDIT_DIALOG_H

View File

@ -24,6 +24,7 @@
#include "qalculateqtsettings.h"
#include "datasetsdialog.h"
#include "dataseteditdialog.h"
DataSetsDialog::DataSetsDialog(QWidget *parent) : QDialog(parent) {
selected_dataset = NULL;
@ -46,6 +47,17 @@ DataSetsDialog::DataSetsDialog(QWidget *parent) : QDialog(parent) {
datasetsView->header()->hide();
datasetsView->setColumnCount(1);
box->addWidget(datasetsView);
QHBoxLayout *hbox = new QHBoxLayout();
hbox->addStretch(1);
addDSButton = new QPushButton(tr("Add"), this);
hbox->addWidget(addDSButton);
editDSButton = new QPushButton(tr("Edit"), this);
editDSButton->setEnabled(false);
hbox->addWidget(editDSButton);
delDSButton = new QPushButton(tr("Remove"), this);
delDSButton->setEnabled(false);
hbox->addWidget(delDSButton);
box->addLayout(hbox);
w = new QWidget(this);
box = new QVBoxLayout(w);
vsplitter_l->addWidget(w);
@ -58,6 +70,18 @@ DataSetsDialog::DataSetsDialog(QWidget *parent) : QDialog(parent) {
objectsView->header()->hide();
objectsView->setColumnCount(1);
box->addWidget(objectsView);
hbox = new QHBoxLayout();
hbox->addStretch(1);
addObjButton = new QPushButton(tr("Add"), this);
addObjButton->setEnabled(false);
hbox->addWidget(addObjButton);
editObjButton = new QPushButton(tr("Edit"), this);
editObjButton->setEnabled(false);
hbox->addWidget(editObjButton);
delObjButton = new QPushButton(tr("Remove"), this);
delObjButton->setEnabled(false);
hbox->addWidget(delObjButton);
box->addLayout(hbox);
w = new QWidget(this);
box = new QVBoxLayout(w);
vsplitter_r->addWidget(w);
@ -85,6 +109,12 @@ DataSetsDialog::DataSetsDialog(QWidget *parent) : QDialog(parent) {
QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Close, Qt::Horizontal, this);
topbox->addWidget(buttonBox);
datasetsView->setFocus();
connect(addDSButton, SIGNAL(clicked()), this, SLOT(addDataset()));
connect(editDSButton, SIGNAL(clicked()), this, SLOT(editDataset()));
connect(delDSButton, SIGNAL(clicked()), this, SLOT(delDataset()));
connect(addObjButton, SIGNAL(clicked()), this, SLOT(addObject()));
connect(editObjButton, SIGNAL(clicked()), this, SLOT(editObject()));
connect(delObjButton, SIGNAL(clicked()), this, SLOT(delObject()));
connect(buttonBox->button(QDialogButtonBox::Close), SIGNAL(clicked()), this, SLOT(reject()));
connect(datasetsView, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(selectedDatasetChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
connect(objectsView, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), this, SLOT(selectedObjectChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
@ -111,6 +141,50 @@ DataSetsDialog::DataSetsDialog(QWidget *parent) : QDialog(parent) {
}
DataSetsDialog::~DataSetsDialog() {}
void DataSetsDialog::addDataset() {}
void DataSetsDialog::editDataset() {}
void DataSetsDialog::delDataset() {}
void DataSetsDialog::addObject() {
if(!selected_dataset) return;
DataObject *o = DataObjectEditDialog::newObject(this, selected_dataset);
if(o) {
selected_object = o;
DataPropertyIter pit;
DataProperty *dp = selected_object->parentSet()->getFirstProperty(&pit);
QTreeWidgetItem *item = new QTreeWidgetItem(objectsView);
for(int i = 0; dp; i++) {
if(!dp->isHidden() && dp->isKey()) item->setText(i, QString::fromStdString(selected_object->getPropertyDisplayString(dp)));
dp = selected_object->parentSet()->getNextProperty(&pit);
}
item->setData(0, Qt::UserRole, QVariant::fromValue((void*) selected_object));
objectsView->clearSelection();
objectsView->setCurrentItem(item);
item->setSelected(true);
selectedObjectChanged(item, NULL);
if(objectsView->columnCount() == 1) objectsView->sortItems(0, Qt::AscendingOrder);
}
}
void DataSetsDialog::editObject() {
if(!selected_object) return;
if(DataObjectEditDialog::editObject(this, selected_object)) {
DataPropertyIter pit;
DataProperty *dp = selected_object->parentSet()->getFirstProperty(&pit);
QTreeWidgetItem *item = objectsView->currentItem();
if(!item) return;
for(int i = 0; dp; i++) {
if(!dp->isHidden() && dp->isKey()) item->setText(i, QString::fromStdString(selected_object->getPropertyDisplayString(dp)));
dp = selected_object->parentSet()->getNextProperty(&pit);
}
selectedObjectChanged(item, NULL);
if(objectsView->columnCount() == 1) objectsView->sortItems(0, Qt::AscendingOrder);
}
}
void DataSetsDialog::delObject() {
if(!selected_object) return;
QTreeWidgetItem *item = objectsView->currentItem();
if(item) delete item;
selected_object->parentSet()->delObject(selected_object);
}
void DataSetsDialog::vsplitterlMoved(int, int) {
vsplitter_r->setSizes(vsplitter_l->sizes());
}
@ -123,9 +197,15 @@ void DataSetsDialog::selectedDatasetChanged(QTreeWidgetItem *item, QTreeWidgetIt
objectsView->setColumnCount(1);
descriptionView->clear();
selected_dataset = NULL;
addObjButton->setEnabled(false);
editDSButton->setEnabled(false);
delDSButton->setEnabled(false);
return;
}
DataSet *ds = (DataSet*) item->data(0, Qt::UserRole).value<void*>();
addObjButton->setEnabled(ds->isLocal());
editDSButton->setEnabled(true);
delDSButton->setEnabled(ds->isLocal());
selected_dataset = ds;
DataObjectIter it;
DataPropertyIter pit;
@ -141,7 +221,7 @@ void DataSetsDialog::selectedDatasetChanged(QTreeWidgetItem *item, QTreeWidgetIt
objectsView->setColumnCount(n);
for(int i = 0; i < n; i++) objectsView->headerItem()->setText(i, QString());
n = 0;
if(o) selectedObjectChanged(NULL, NULL);
if(!o) selectedObjectChanged(NULL, NULL);
while(o) {
dp = ds->getFirstProperty(&pit);
QTreeWidgetItem *item = new QTreeWidgetItem(objectsView);
@ -152,6 +232,7 @@ void DataSetsDialog::selectedDatasetChanged(QTreeWidgetItem *item, QTreeWidgetIt
item->setData(0, Qt::UserRole, QVariant::fromValue((void*) o));
n++;
if(o == selected_object || (n == 1 && !selected_object)) {
objectsView->setCurrentItem(item);
item->setSelected(true);
selectedObjectChanged(item, NULL);
}
@ -256,12 +337,16 @@ void DataSetsDialog::selectedObjectChanged(QTreeWidgetItem *item, QTreeWidgetIte
propertiesView->clear();
propertiesView->setColumnCount(3);
if(!item) {
editObjButton->setEnabled(false);
delObjButton->setEnabled(false);
selected_object = NULL;
return;
}
DataObject *o = (DataObject*) item->data(0, Qt::UserRole).value<void*>();
selected_object = o;
DataSet *ds = o->parentSet();
editObjButton->setEnabled(true);
delObjButton->setEnabled(o->isUserModified());
DataPropertyIter it;
DataProperty *dp = ds->getFirstProperty(&it);
QFont bold_font(font());
@ -298,6 +383,7 @@ void DataSetsDialog::updateDatasets() {
QTreeWidgetItem *item = new QTreeWidgetItem(datasetsView, QStringList(QString::fromStdString(ds->title())));
item->setData(0, Qt::UserRole, QVariant::fromValue((void*) ds));
if((!ds && i == 1) || ds == selected_dataset) {
datasetsView->setCurrentItem(item);
item->setSelected(true);
}
}

View File

@ -30,6 +30,7 @@ class DataSetsDialog : public QDialog {
QTreeWidget *datasetsView, *objectsView, *propertiesView;
QTextEdit *descriptionView;
QPushButton *addDSButton, *delDSButton, *editDSButton, *addObjButton, *delObjButton, *editObjButton;
QSplitter *vsplitter_l, *vsplitter_r, *hsplitter;
DataSet *selected_dataset;
DataObject *selected_object;
@ -46,6 +47,12 @@ class DataSetsDialog : public QDialog {
void propertyClicked(QTreeWidgetItem*, int);
void vsplitterrMoved(int, int);
void vsplitterlMoved(int, int);
void addDataset();
void editDataset();
void delDataset();
void addObject();
void editObject();
void delObject();
public:

View File

@ -1045,11 +1045,11 @@ void FunctionEditDialog::setFunction(MathFunction *f) {
expressionEdit->setReadOnly(read_only);
}
void FunctionEditDialog::onNameEdited(const QString &str) {
okButton->setEnabled(!str.trimmed().isEmpty() && (!expressionEdit->isEnabled() || !expressionEdit->document()->isEmpty()));
if(!str.trimmed().isEmpty() && !CALCULATOR->functionNameIsValid(str.trimmed().toStdString())) {
nameEdit->setText(QString::fromStdString(CALCULATOR->convertToValidFunctionName(str.trimmed().toStdString())));
}
name_edited = true;
onFunctionChanged();
}
void FunctionEditDialog::onFunctionChanged() {
okButton->setEnabled(!nameEdit->isReadOnly() && (!expressionEdit->document()->isEmpty() || !expressionEdit->isEnabled()) && !nameEdit->text().trimmed().isEmpty());