diff --git a/src/kdefrontend/matrix/MatrixFunctionDialog.cpp b/src/kdefrontend/matrix/MatrixFunctionDialog.cpp index 26e17ca55..81bec3e35 100644 --- a/src/kdefrontend/matrix/MatrixFunctionDialog.cpp +++ b/src/kdefrontend/matrix/MatrixFunctionDialog.cpp @@ -1,255 +1,255 @@ /*************************************************************************** File : MatrixFunctionDialog.cpp Project : LabPlot Description : Dialog for generating matrix values from a mathematical function ------------------------------------------------------------------------ Copyright : (C) 2015-2016 by Alexander Semke (alexander.semke@web.de) Copyright : (C) 2016 by Stefan Gerlach (stefan.gerlach@uni.kn) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "MatrixFunctionDialog.h" #include "backend/lib/macros.h" #include "backend/matrix/Matrix.h" #include "kdefrontend/widgets/ConstantsWidget.h" #include "kdefrontend/widgets/FunctionsWidget.h" extern "C" { #include "backend/gsl/parser.h" } #include #include #include #include #include #include #include #ifndef NDEBUG #include #endif /*! \class MatrixFunctionDialog \brief Dialog for generating matrix values from a mathematical function. \ingroup kdefrontend */ -MatrixFunctionDialog::MatrixFunctionDialog(Matrix* m, QWidget* parent, Qt::WFlags fl) : QDialog(parent, fl), m_matrix(m) { +MatrixFunctionDialog::MatrixFunctionDialog(Matrix* m, QWidget* parent) : QDialog(parent), m_matrix(m) { Q_ASSERT(m_matrix); setWindowTitle(i18nc("@title:window", "Function values")); ui.setupUi(this); setAttribute(Qt::WA_DeleteOnClose); ui.tbConstants->setIcon( QIcon::fromTheme("labplot-format-text-symbol") ); ui.tbFunctions->setIcon( QIcon::fromTheme("preferences-desktop-font") ); QStringList vars; vars << "x" << "y"; ui.teEquation->setVariables(vars); ui.teEquation->setFocus(); ui.teEquation->setMaximumHeight(QLineEdit().sizeHint().height()*2); QString info = '[' + QString::number(m_matrix->xStart()) + ", " + QString::number(m_matrix->xEnd()) + "], " + i18np("%1 value", "%1 values", m_matrix->columnCount()); ui.lXInfo->setText(info); info = '[' + QString::number(m_matrix->yStart()) + ", " + QString::number(m_matrix->yEnd()) + "], " + i18np("%1 value", "%1 values", m_matrix->rowCount()); ui.lYInfo->setText(info); ui.teEquation->setPlainText(m_matrix->formula()); QDialogButtonBox* btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); ui.gridLayout_2->addWidget(btnBox); m_okButton = btnBox->button(QDialogButtonBox::Ok); connect(btnBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &MatrixFunctionDialog::close); connect(btnBox, &QDialogButtonBox::accepted, this, &MatrixFunctionDialog::accept); connect(btnBox, &QDialogButtonBox::rejected, this, &MatrixFunctionDialog::reject); m_okButton->setText(i18n("&Generate")); m_okButton->setToolTip(i18n("Generate function values")); connect(ui.teEquation, &ExpressionTextEdit::expressionChanged, this, &MatrixFunctionDialog::checkValues); connect(ui.tbConstants, &QToolButton::clicked, this, &MatrixFunctionDialog::showConstants); connect(ui.tbFunctions, &QToolButton::clicked, this, &MatrixFunctionDialog::showFunctions); connect(m_okButton, &QPushButton::clicked, this, &MatrixFunctionDialog::generate); resize(QSize(300,0).expandedTo(minimumSize())); } void MatrixFunctionDialog::checkValues() { if (!ui.teEquation->isValid()) { m_okButton->setEnabled(false); return; } m_okButton->setEnabled(true); } void MatrixFunctionDialog::showConstants() { QMenu menu; ConstantsWidget constants(&menu); connect(&constants, &ConstantsWidget::constantSelected, this, &MatrixFunctionDialog::insertConstant); connect(&constants, &ConstantsWidget::constantSelected, &menu, &QMenu::close); connect(&constants, &ConstantsWidget::canceled, &menu, &QMenu::close); QWidgetAction* widgetAction = new QWidgetAction(this); widgetAction->setDefaultWidget(&constants); menu.addAction(widgetAction); QPoint pos(-menu.sizeHint().width()+ui.tbConstants->width(),-menu.sizeHint().height()); menu.exec(ui.tbConstants->mapToGlobal(pos)); } void MatrixFunctionDialog::showFunctions() { QMenu menu; FunctionsWidget functions(&menu); connect(&functions, &FunctionsWidget::functionSelected, this, &MatrixFunctionDialog::insertFunction); connect(&functions, &FunctionsWidget::functionSelected, &menu, &QMenu::close); connect(&functions, &FunctionsWidget::canceled, &menu, &QMenu::close); QWidgetAction* widgetAction = new QWidgetAction(this); widgetAction->setDefaultWidget(&functions); menu.addAction(widgetAction); QPoint pos(-menu.sizeHint().width()+ui.tbFunctions->width(),-menu.sizeHint().height()); menu.exec(ui.tbFunctions->mapToGlobal(pos)); } void MatrixFunctionDialog::insertFunction(const QString& str) { //TODO: not all functions have only one argument ui.teEquation->insertPlainText(str + "(x)"); } void MatrixFunctionDialog::insertConstant(const QString& str) { ui.teEquation->insertPlainText(str); } /* task class for parallel fill (not used) */ class GenerateValueTask : public QRunnable { public: GenerateValueTask(int startCol, int endCol, QVector>& matrixData, double xStart, double yStart, double xStep, double yStep, char* func): m_startCol(startCol), m_endCol(endCol), m_matrixData(matrixData), m_xStart(xStart), m_yStart(yStart), m_xStep(xStep), m_yStep(yStep), m_func(func) { }; void run() { const int rows = m_matrixData[m_startCol].size(); double x = m_xStart; double y = m_yStart; DEBUG("FILL col"<name())); //TODO: data types QVector>* new_data = static_cast>*>(m_matrix->data()); QByteArray funcba = ui.teEquation->toPlainText().toLocal8Bit(); char* func = funcba.data(); // check if rows or cols == 1 double diff = m_matrix->xEnd() - m_matrix->xStart(); double xStep = 0.0; if (m_matrix->columnCount() > 1) xStep = diff/double(m_matrix->columnCount() - 1); diff = m_matrix->yEnd() - m_matrix->yStart(); double yStep = 0.0; if (m_matrix->rowCount() > 1) yStep = diff/double(m_matrix->rowCount() - 1); #ifndef NDEBUG QElapsedTimer timer; timer.start(); #endif //TODO: too slow because every parser thread needs an own symbol_table // idea: use pool->maxThreadCount() symbol tables and reuse them? /* double yStart = m_matrix->yStart(); const int cols = m_matrix->columnCount(); QThreadPool* pool = QThreadPool::globalInstance(); int range = ceil(double(cols)/pool->maxThreadCount()); DEBUG("Starting" << pool->maxThreadCount() << "threads. cols =" << cols << ": range =" << range); for (int i = 0; i < pool->maxThreadCount(); ++i) { const int start = i*range; int end = (i+1)*range; if (end > cols) end = cols; qDebug() << "start/end: " << start << end; const double xStart = m_matrix->xStart() + xStep*start; GenerateValueTask* task = new GenerateValueTask(start, end, new_data, xStart, yStart, xStep, yStep, func); task->setAutoDelete(false); pool->start(task); } pool->waitForDone(); */ double x = 0, y = 0; parser_var vars[] = {{"x", x}, {"y", y}}; for (int col = 0; col < m_matrix->columnCount(); ++col) { vars[0].value = x; for (int row = 0; row < m_matrix->rowCount(); ++row) { vars[1].value = y; (new_data->operator[](col))[row] = parse_with_vars(func, vars, 2); y += yStep; } y = m_matrix->yStart(); x += xStep; } // Timing DEBUG("elapsed time =" << timer.elapsed() << "ms"); m_matrix->setFormula(ui.teEquation->toPlainText()); m_matrix->setData(new_data); m_matrix->endMacro(); RESET_CURSOR; } diff --git a/src/kdefrontend/matrix/MatrixFunctionDialog.h b/src/kdefrontend/matrix/MatrixFunctionDialog.h index 6f32e478e..f6c4b8823 100644 --- a/src/kdefrontend/matrix/MatrixFunctionDialog.h +++ b/src/kdefrontend/matrix/MatrixFunctionDialog.h @@ -1,55 +1,55 @@ /*************************************************************************** File : MatrixFunctionDialog.h Project : LabPlot Description : Dialog for generating matrix values from a mathematical function -------------------------------------------------------------------- Copyright : (C) 2015 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef MATRIXFUNCTIONDIALOG_H #define MATRIXFUNCTIONDIALOG_H #include "ui_matrixfunctionwidget.h" #include class Matrix; class QPushButton; class MatrixFunctionDialog : public QDialog { Q_OBJECT public: - explicit MatrixFunctionDialog(Matrix*, QWidget* parent = 0, Qt::WFlags = 0); + explicit MatrixFunctionDialog(Matrix*, QWidget* parent = 0); private: Ui::MatrixFunctionWidget ui; Matrix* m_matrix; QPushButton* m_okButton; private slots: void generate(); void checkValues(); void showConstants(); void showFunctions(); void insertFunction(const QString&); void insertConstant(const QString&); }; #endif diff --git a/src/kdefrontend/spreadsheet/DropValuesDialog.cpp b/src/kdefrontend/spreadsheet/DropValuesDialog.cpp index a3400bc74..4b5bfb75c 100644 --- a/src/kdefrontend/spreadsheet/DropValuesDialog.cpp +++ b/src/kdefrontend/spreadsheet/DropValuesDialog.cpp @@ -1,346 +1,346 @@ /*************************************************************************** File : DropValuesDialog.cpp Project : LabPlot Description : Dialog for droping and masking values in columns -------------------------------------------------------------------- Copyright : (C) 2015 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "DropValuesDialog.h" #include "backend/core/column/Column.h" #include "backend/lib/macros.h" #include "backend/spreadsheet/Spreadsheet.h" #include #include #include #include #include /*! \class DropValuesDialog \brief Dialog for generating values from a mathematical function. \ingroup kdefrontend */ -DropValuesDialog::DropValuesDialog(Spreadsheet* s, bool mask, QWidget* parent, Qt::WFlags fl) : QDialog(parent, fl), +DropValuesDialog::DropValuesDialog(Spreadsheet* s, bool mask, QWidget* parent) : QDialog(parent), m_spreadsheet(s), m_mask(mask) { setWindowTitle(i18nc("@title:window", "Drop Values")); ui.setupUi(this); setAttribute(Qt::WA_DeleteOnClose); ui.cbOperator->addItem(i18n("Equal To")); ui.cbOperator->addItem(i18n("Between (Including End Points)")); ui.cbOperator->addItem(i18n("Between (Excluding End Points)")); ui.cbOperator->addItem(i18n("Greater Than")); ui.cbOperator->addItem(i18n("Greater Than Or Equal To")); ui.cbOperator->addItem(i18n("Lesser Than")); ui.cbOperator->addItem(i18n("Lesser Than Or Equal To")); ui.leValue1->setValidator( new QDoubleValidator(ui.leValue1) ); ui.leValue2->setValidator( new QDoubleValidator(ui.leValue2) ); QDialogButtonBox* btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); ui.horizontalLayout->addWidget(btnBox); m_okButton = btnBox->button(QDialogButtonBox::Ok); connect(btnBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &DropValuesDialog::close); if (m_mask) { m_okButton->setText(i18n("&Mask")); m_okButton->setToolTip(i18n("Mask values in the specified region")); ui.lMode->setText(i18n("Mask values")); setWindowTitle(i18nc("@title:window", "Mask Values")); } else { m_okButton->setText(i18n("&Drop")); m_okButton->setToolTip(i18n("Drop values in the specified region")); } connect(ui.cbOperator, static_cast(&QComboBox::currentIndexChanged), this, &DropValuesDialog::operatorChanged ); connect(m_okButton, &QPushButton::clicked, this, &DropValuesDialog::okClicked); connect(btnBox, &QDialogButtonBox::accepted, this, &DropValuesDialog::accept); connect(btnBox, &QDialogButtonBox::rejected, this, &DropValuesDialog::reject); resize( QSize(400,0).expandedTo(minimumSize()) ); operatorChanged(0); } void DropValuesDialog::setColumns(QVector columns) { m_columns = columns; } void DropValuesDialog::operatorChanged(int index) const { bool value2 = (index==1) || (index==2); ui.lMin->setVisible(value2); ui.lMax->setVisible(value2); ui.lAnd->setVisible(value2); ui.leValue2->setVisible(value2); } void DropValuesDialog::okClicked() const { if (m_mask) maskValues(); else dropValues(); } //TODO: m_column->setMasked() is slow, we need direct access to the masked-container -> redesign class MaskValuesTask : public QRunnable { public: MaskValuesTask(Column* col, int op, double value1, double value2){ m_column = col; m_operator = op; m_value1 = value1; m_value2 = value2; } void run() { m_column->setSuppressDataChangedSignal(true); bool changed = false; QVector* data = static_cast* >(m_column->data()); //equal to if (m_operator == 0) { for (int i=0; isize(); ++i) { if (data->at(i) == m_value1) { m_column->setMasked(i, true); changed = true; } } } //between (including end points) else if (m_operator == 1) { for (int i=0; isize(); ++i) { if (data->at(i) >= m_value1 && data->at(i) <= m_value2) { m_column->setMasked(i, true); changed = true; } } } //between (excluding end points) else if (m_operator == 2) { for (int i=0; isize(); ++i) { if (data->at(i) > m_value1 && data->at(i) < m_value2) { m_column->setMasked(i, true); changed = true; } } } //greater than else if (m_operator == 3) { for (int i=0; isize(); ++i) { if (data->at(i) > m_value1) { m_column->setMasked(i, true); changed = true; } } } //greater than or equal to else if (m_operator == 4) { for (int i=0; isize(); ++i) { if (data->at(i) >= m_value1) { m_column->setMasked(i, true); changed = true; } } } //lesser than else if (m_operator == 5) { for (int i=0; isize(); ++i) { if (data->at(i) < m_value1) { m_column->setMasked(i, true); changed = true; } } } //lesser than or equal to else if (m_operator == 6) { for (int i=0; isize(); ++i) { if (data->at(i) <= m_value1) { m_column->setMasked(i, true); changed = true; } } } m_column->setSuppressDataChangedSignal(false); if (changed) m_column->setChanged(); } private: Column* m_column; int m_operator; double m_value1; double m_value2; }; class DropValuesTask : public QRunnable { public: DropValuesTask(Column* col, int op, double value1, double value2){ m_column = col; m_operator = op; m_value1 = value1; m_value2 = value2; } void run() { bool changed = false; QVector* data = static_cast* >(m_column->data()); QVector new_data(*data); //equal to if (m_operator == 0) { for (int i=0; i= m_value1 && new_data[i] <= m_value2) { new_data[i] = NAN; changed = true; } } } //between (excluding end points) else if (m_operator == 2) { for (int i=0; i m_value1 && new_data[i] < m_value2) { new_data[i] = NAN; changed = true; } } } //greater than else if (m_operator == 3) { for (int i=0; i m_value1) { new_data[i] = NAN; changed = true; } } } //greater than or equal to else if (m_operator == 4) { for (int i=0; i= m_value1) { new_data[i] = NAN; changed = true; } } } //lesser than else if (m_operator == 5) { for (int i=0; ireplaceValues(0, new_data); } private: Column* m_column; int m_operator; double m_value1; double m_value2; }; void DropValuesDialog::maskValues() const { Q_ASSERT(m_spreadsheet); WAIT_CURSOR; m_spreadsheet->beginMacro(i18n("%1: mask values", m_spreadsheet->name())); const int op = ui.cbOperator->currentIndex(); const double value1 = ui.leValue1->text().toDouble(); const double value2 = ui.leValue2->text().toDouble(); for(Column* col: m_columns) { MaskValuesTask* task = new MaskValuesTask(col, op, value1, value2); task->run(); //TODO: writing to the undo-stack in Column::setMasked() is not tread-safe -> redesign // QThreadPool::globalInstance()->start(task); } //wait until all columns were processed // QThreadPool::globalInstance()->waitForDone(); m_spreadsheet->endMacro(); RESET_CURSOR; } void DropValuesDialog::dropValues() const { Q_ASSERT(m_spreadsheet); WAIT_CURSOR; m_spreadsheet->beginMacro(i18n("%1: drop values", m_spreadsheet->name())); const int op = ui.cbOperator->currentIndex(); const double value1 = ui.leValue1->text().toDouble(); const double value2 = ui.leValue2->text().toDouble(); for(Column* col: m_columns) { DropValuesTask* task = new DropValuesTask(col, op, value1, value2); QThreadPool::globalInstance()->start(task); } //wait until all columns were processed QThreadPool::globalInstance()->waitForDone(); m_spreadsheet->endMacro(); RESET_CURSOR; } diff --git a/src/kdefrontend/spreadsheet/DropValuesDialog.h b/src/kdefrontend/spreadsheet/DropValuesDialog.h index 5ce039276..0e0d8910b 100644 --- a/src/kdefrontend/spreadsheet/DropValuesDialog.h +++ b/src/kdefrontend/spreadsheet/DropValuesDialog.h @@ -1,60 +1,60 @@ /*************************************************************************** File : DropValuesDialog.h Project : LabPlot Description : Dialog for droping and masking values in columns -------------------------------------------------------------------- Copyright : (C) 2015 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef DROPVALUESDIALOG_H #define DROPVALUESDIALOG_H #include "ui_dropvalueswidget.h" #include class Column; class Spreadsheet; class QPushButton; class DropValuesDialog : public QDialog { Q_OBJECT public: - explicit DropValuesDialog(Spreadsheet* s, bool mask = false, QWidget* parent = 0, Qt::WFlags fl = 0); + explicit DropValuesDialog(Spreadsheet* s, bool mask = false, QWidget* parent = 0); void setColumns(QVector); private: Ui::DropValuesWidget ui; QVector m_columns; Spreadsheet* m_spreadsheet; bool m_mask; void dropValues() const; void maskValues() const; QPushButton* m_okButton; private slots: void operatorChanged(int) const; void okClicked() const; }; #endif diff --git a/src/kdefrontend/spreadsheet/EquidistantValuesDialog.cpp b/src/kdefrontend/spreadsheet/EquidistantValuesDialog.cpp index 9976218de..7ef0278be 100644 --- a/src/kdefrontend/spreadsheet/EquidistantValuesDialog.cpp +++ b/src/kdefrontend/spreadsheet/EquidistantValuesDialog.cpp @@ -1,181 +1,181 @@ /*************************************************************************** File : EquidistantValuesDialog.cpp Project : LabPlot Description : Dialog for generating equidistant numbers -------------------------------------------------------------------- Copyright : (C) 2014 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "EquidistantValuesDialog.h" #include "backend/core/column/Column.h" #include "backend/lib/macros.h" #include "backend/spreadsheet/Spreadsheet.h" #include #include #include /*! \class EquidistantValuesDialog \brief Dialog for equidistant values. \ingroup kdefrontend */ -EquidistantValuesDialog::EquidistantValuesDialog(Spreadsheet* s, QWidget* parent, Qt::WFlags fl) : QDialog(parent, fl), m_spreadsheet(s) { +EquidistantValuesDialog::EquidistantValuesDialog(Spreadsheet* s, QWidget* parent) : QDialog(parent), m_spreadsheet(s) { setWindowTitle(i18nc("@title:window", "Equidistant Values")); ui.setupUi(this); setAttribute(Qt::WA_DeleteOnClose); ui.cbType->addItem(i18n("Number")); ui.cbType->addItem(i18n("Increment")); QDialogButtonBox* btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); ui.gridLayout->addWidget(btnBox); m_okButton = btnBox->button(QDialogButtonBox::Ok); connect(btnBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &EquidistantValuesDialog::close); connect(btnBox, &QDialogButtonBox::accepted, this, &EquidistantValuesDialog::accept); connect(btnBox, &QDialogButtonBox::rejected, this, &EquidistantValuesDialog::reject); m_okButton->setText(i18n("&Generate")); m_okButton->setToolTip(i18n("Generate equidistant values")); ui.leFrom->setClearButtonEnabled(true); ui.leTo->setClearButtonEnabled(true); ui.leIncrement->setClearButtonEnabled(true); ui.leNumber->setClearButtonEnabled(true); ui.leFrom->setValidator( new QDoubleValidator(ui.leFrom) ); ui.leTo->setValidator( new QDoubleValidator(ui.leTo) ); ui.leIncrement->setValidator( new QDoubleValidator(ui.leIncrement) ); ui.leNumber->setValidator( new QIntValidator(ui.leNumber) ); ui.leFrom->setText("1"); ui.leTo->setText("100"); ui.leIncrement->setText("1"); connect( ui.cbType, static_cast(&QComboBox::currentIndexChanged), this, &EquidistantValuesDialog::typeChanged); connect( ui.leFrom, &QLineEdit::textChanged, this, &EquidistantValuesDialog::checkValues); connect( ui.leTo, &QLineEdit::textChanged, this, &EquidistantValuesDialog::checkValues); connect( ui.leNumber, &QLineEdit::textChanged, this, &EquidistantValuesDialog::checkValues); connect( ui.leIncrement, &QLineEdit::textChanged, this, &EquidistantValuesDialog::checkValues); connect(m_okButton, &QPushButton::clicked, this, &EquidistantValuesDialog::generate); //generated data the default this->typeChanged(0); resize( QSize(300,0).expandedTo(minimumSize()) ); } void EquidistantValuesDialog::setColumns(const QVector& columns) { m_columns = columns; ui.leNumber->setText( QString::number(m_columns.first()->rowCount()) ); } void EquidistantValuesDialog::typeChanged(int index) { if (index==0) { //fixed number ui.lIncrement->hide(); ui.leIncrement->hide(); ui.lNumber->show(); ui.leNumber->show(); } else { //fixed increment ui.lIncrement->show(); ui.leIncrement->show(); ui.lNumber->hide(); ui.leNumber->hide(); } } void EquidistantValuesDialog::checkValues() { if (ui.leFrom->text().simplified().isEmpty()) { m_okButton->setEnabled(false); return; } if (ui.leTo->text().simplified().isEmpty()) { m_okButton->setEnabled(false); return; } if (ui.cbType->currentIndex() == 0) { if (ui.leNumber->text().simplified().isEmpty() || ui.leNumber->text().simplified().toInt()==0) { m_okButton->setEnabled(false); return; } } else { if (ui.leIncrement->text().simplified().isEmpty() || qFuzzyIsNull(ui.leIncrement->text().simplified().toDouble())) { m_okButton->setEnabled(false); return; } } m_okButton->setEnabled(true); } void EquidistantValuesDialog::generate() { Q_ASSERT(m_spreadsheet); WAIT_CURSOR; m_spreadsheet->beginMacro(i18np("%1: fill column with equidistant numbers", "%1: fill columns with equidistant numbers", m_spreadsheet->name(), m_columns.size())); double start = ui.leFrom->text().toDouble(); double end = ui.leTo->text().toDouble(); int number; double dist; if (ui.cbType->currentIndex()==0) { //fixed number number = ui.leNumber->text().toInt(); if (number!=1) dist = (end - start)/ (number - 1); else dist = 0; } else { //fixed increment dist = ui.leIncrement->text().toDouble(); number = (end-start)/dist + 1; } if (m_spreadsheet->rowCount()setRowCount(number); for (auto* col : m_columns) { col->setSuppressDataChangedSignal(true); if (m_spreadsheet->rowCount()>number) col->clear(); for (int i=0; isetValueAt(i, start + dist*i); } col->setSuppressDataChangedSignal(false); col->setChanged(); } m_spreadsheet->endMacro(); RESET_CURSOR; } diff --git a/src/kdefrontend/spreadsheet/EquidistantValuesDialog.h b/src/kdefrontend/spreadsheet/EquidistantValuesDialog.h index 79743d9b9..36aa54b3e 100644 --- a/src/kdefrontend/spreadsheet/EquidistantValuesDialog.h +++ b/src/kdefrontend/spreadsheet/EquidistantValuesDialog.h @@ -1,57 +1,57 @@ /*************************************************************************** File : EquidistantValuesDialog.h Project : LabPlot Description : Dialog for generating equidistant values -------------------------------------------------------------------- Copyright : (C) 2014 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef EQUIDISTANTVALUESDIALOG_H #define EQUIDISTANTVALUESDIALOG_H #include "ui_equidistantvalueswidget.h" #include class Column; class Spreadsheet; class QPushButton; class EquidistantValuesDialog : public QDialog { Q_OBJECT public: - explicit EquidistantValuesDialog(Spreadsheet* s, QWidget* parent = 0, Qt::WFlags fl = 0); + explicit EquidistantValuesDialog(Spreadsheet* s, QWidget* parent = 0); void setColumns(const QVector&); private: Ui::EquidistantValuesWidget ui; QVector m_columns; Spreadsheet* m_spreadsheet; QPushButton* m_okButton; private slots: void generate(); void typeChanged(int index); void checkValues(); }; #endif diff --git a/src/kdefrontend/spreadsheet/FunctionValuesDialog.cpp b/src/kdefrontend/spreadsheet/FunctionValuesDialog.cpp index a92446e76..2524577ef 100644 --- a/src/kdefrontend/spreadsheet/FunctionValuesDialog.cpp +++ b/src/kdefrontend/spreadsheet/FunctionValuesDialog.cpp @@ -1,367 +1,367 @@ /*************************************************************************** File : FunctionValuesDialog.cpp Project : LabPlot Description : Dialog for generating values from a mathematical function -------------------------------------------------------------------- Copyright : (C) 2014-2015 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "FunctionValuesDialog.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/column/Column.h" #include "backend/core/Project.h" #include "backend/gsl/ExpressionParser.h" #include "backend/lib/macros.h" #include "backend/spreadsheet/Spreadsheet.h" #include "commonfrontend/widgets/TreeViewComboBox.h" #include "kdefrontend/widgets/ConstantsWidget.h" #include "kdefrontend/widgets/FunctionsWidget.h" #include #include #include #include #include #include #include #include /*! \class FunctionValuesDialog \brief Dialog for generating values from a mathematical function. \ingroup kdefrontend */ -FunctionValuesDialog::FunctionValuesDialog(Spreadsheet* s, QWidget* parent, Qt::WFlags fl) : QDialog(parent, fl), m_spreadsheet(s) { +FunctionValuesDialog::FunctionValuesDialog(Spreadsheet* s, QWidget* parent) : QDialog(parent), m_spreadsheet(s) { Q_ASSERT(s != nullptr); setWindowTitle(i18nc("@title:window", "Function Values")); ui.setupUi(this); setAttribute(Qt::WA_DeleteOnClose); ui.tbConstants->setIcon( QIcon::fromTheme("labplot-format-text-symbol") ); ui.tbConstants->setIcon( QIcon::fromTheme("format-text-symbol") ); ui.tbFunctions->setIcon( QIcon::fromTheme("preferences-desktop-font") ); ui.teEquation->setMaximumHeight(QLineEdit().sizeHint().height()*2); ui.teEquation->setFocus(); m_topLevelClasses<<"Folder"<<"Workbook"<<"Spreadsheet"<<"FileDataSource"<<"Column"; m_selectableClasses<<"Column"; // needed for buggy compiler #if __cplusplus < 201103L m_aspectTreeModel = std::auto_ptr(new AspectTreeModel(m_spreadsheet->project())); #else m_aspectTreeModel = std::unique_ptr(new AspectTreeModel(m_spreadsheet->project())); #endif m_aspectTreeModel->setSelectableAspects(m_selectableClasses); m_aspectTreeModel->enableNumericColumnsOnly(true); m_aspectTreeModel->enableNonEmptyNumericColumnsOnly(true); ui.bAddVariable->setIcon(QIcon::fromTheme("list-add")); ui.bAddVariable->setToolTip(i18n("Add new variable")); QDialogButtonBox* btnBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); ui.verticalLayout->addWidget(btnBox); m_okButton = btnBox->button(QDialogButtonBox::Ok); connect(btnBox, &QDialogButtonBox::accepted, this, &FunctionValuesDialog::accept); connect(btnBox, &QDialogButtonBox::rejected, this, &FunctionValuesDialog::reject); m_okButton->setText(i18n("&Generate")); m_okButton->setToolTip(i18n("Generate function values")); connect( ui.bAddVariable, SIGNAL(pressed()), this, SLOT(addVariable()) ); connect( ui.teEquation, SIGNAL(expressionChanged()), this, SLOT(checkValues()) ); connect( ui.tbConstants, SIGNAL(clicked()), this, SLOT(showConstants()) ); connect( ui.tbFunctions, SIGNAL(clicked()), this, SLOT(showFunctions()) ); connect(m_okButton, &QPushButton::clicked, this, &FunctionValuesDialog::generate); //restore saved settings if available KConfigGroup conf(KSharedConfig::openConfig(), "FunctionValuesDialog"); if (conf.exists()) KWindowConfig::restoreWindowSize(windowHandle(), conf); else resize(QSize(300, 0).expandedTo(minimumSize())); } FunctionValuesDialog::~FunctionValuesDialog() { KConfigGroup conf(KSharedConfig::openConfig(), "FunctionValuesDialog"); KWindowConfig::saveWindowSize(windowHandle(), conf); } void FunctionValuesDialog::setColumns(QVector columns) { m_columns = columns; ui.teEquation->setPlainText(m_columns.first()->formula()); const QStringList& variableNames = m_columns.first()->formulaVariableNames(); if (!variableNames.size()) { //no formula was used for this column -> add the first variable "x" addVariable(); m_variableNames[0]->setText("x"); } else { //formula and variables are available const QStringList& columnPathes = m_columns.first()->formulaVariableColumnPathes(); //add all available variables and select the corresponding columns const QVector cols = m_spreadsheet->project()->children("Column", AbstractAspect::Recursive); for (int i = 0; i < variableNames.size(); ++i) { addVariable(); m_variableNames[i]->setText(variableNames.at(i)); for (const auto* aspect : cols) { if (aspect->path() == columnPathes.at(i)) { const AbstractColumn* column = dynamic_cast(aspect); if (column) m_variableDataColumns[i]->setCurrentModelIndex(m_aspectTreeModel->modelIndexOfAspect(column)); else m_variableDataColumns[i]->setCurrentModelIndex(QModelIndex()); break; } } } } } /*! check the user input and enables/disables the Ok-button depending on the correctness of the input */ void FunctionValuesDialog::checkValues() { //check whether the formula syntax is correct if (!ui.teEquation->isValid()) { m_okButton->setEnabled(false); return; } //check whether for the variables where a name was provided also a column was selected. for (int i = 0; i < m_variableDataColumns.size(); ++i) { if (m_variableNames.at(i)->text().simplified().isEmpty()) continue; TreeViewComboBox* cb = m_variableDataColumns.at(i); AbstractAspect* aspect = static_cast(cb->currentModelIndex().internalPointer()); if (!aspect) { m_okButton->setEnabled(false); return; } /* Column* column = dynamic_cast(aspect); DEBUG("row count = " << (static_cast* >(column->data()))->size()); if (!column || column->rowCount() < 1) { m_okButton->setEnabled(false); //Warning: x column is empty return; } */ } m_okButton->setEnabled(true); } void FunctionValuesDialog::showConstants() { QMenu menu; ConstantsWidget constants(&menu); connect(&constants, SIGNAL(constantSelected(QString)), this, SLOT(insertConstant(QString))); connect(&constants, SIGNAL(constantSelected(QString)), &menu, SLOT(close())); connect(&constants, SIGNAL(canceled()), &menu, SLOT(close())); QWidgetAction* widgetAction = new QWidgetAction(this); widgetAction->setDefaultWidget(&constants); menu.addAction(widgetAction); QPoint pos(-menu.sizeHint().width()+ui.tbConstants->width(),-menu.sizeHint().height()); menu.exec(ui.tbConstants->mapToGlobal(pos)); } void FunctionValuesDialog::showFunctions() { QMenu menu; FunctionsWidget functions(&menu); connect(&functions, SIGNAL(functionSelected(QString)), this, SLOT(insertFunction(QString))); connect(&functions, SIGNAL(functionSelected(QString)), &menu, SLOT(close())); connect(&functions, SIGNAL(canceled()), &menu, SLOT(close())); QWidgetAction* widgetAction = new QWidgetAction(this); widgetAction->setDefaultWidget(&functions); menu.addAction(widgetAction); QPoint pos(-menu.sizeHint().width()+ui.tbFunctions->width(),-menu.sizeHint().height()); menu.exec(ui.tbFunctions->mapToGlobal(pos)); } void FunctionValuesDialog::insertFunction(const QString& str) { //TODO: not all functions have only one argument ui.teEquation->insertPlainText(str + "(x)"); } void FunctionValuesDialog::insertConstant(const QString& str) { ui.teEquation->insertPlainText(str); } void FunctionValuesDialog::addVariable() { QGridLayout* layout = dynamic_cast(ui.frameVariables->layout()); int row = m_variableNames.size(); //text field for the variable name QLineEdit* le = new QLineEdit(); le->setMaximumWidth(30); connect(le, SIGNAL(textChanged(QString)), this, SLOT(variableNameChanged())); layout->addWidget(le, row, 0, 1, 1); m_variableNames << le; //label for the "="-sign QLabel* l = new QLabel("="); layout->addWidget(l, row, 1, 1, 1); m_variableLabels << l; //combo box for the data column TreeViewComboBox* cb = new TreeViewComboBox(); cb->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred)); connect( cb, SIGNAL(currentModelIndexChanged(QModelIndex)), this, SLOT(checkValues()) ); layout->addWidget(cb, row, 2, 1, 1); m_variableDataColumns << cb; cb->setTopLevelClasses(m_topLevelClasses); cb->setModel(m_aspectTreeModel.get()); cb->setCurrentModelIndex(m_aspectTreeModel->modelIndexOfAspect(m_spreadsheet->column(0))); //move the add-button to the next row layout->removeWidget(ui.bAddVariable); layout->addWidget(ui.bAddVariable, row+1,3, 1, 1); //add delete-button for the just added variable if (row != 0) { QToolButton* b = new QToolButton(); b->setIcon(QIcon::fromTheme("list-remove")); b->setToolTip(i18n("Delete variable")); layout->addWidget(b, row, 3, 1, 1); m_variableDeleteButtons<setText(i18n("Variables:")); //TODO: adjust the tab-ordering after new widgets were added } void FunctionValuesDialog::deleteVariable() { QObject* ob = QObject::sender(); int index = m_variableDeleteButtons.indexOf(qobject_cast(ob)) ; delete m_variableNames.takeAt(index+1); delete m_variableLabels.takeAt(index+1); delete m_variableDataColumns.takeAt(index+1); delete m_variableDeleteButtons.takeAt(index); variableNameChanged(); checkValues(); //adjust the layout resize( QSize(width(),0).expandedTo(minimumSize()) ); m_variableNames.size() > 1 ? ui.lVariable->setText(i18n("Variables:")) : ui.lVariable->setText(i18n("Variable:")); //TODO: adjust the tab-ordering after some widgets were deleted } void FunctionValuesDialog::variableNameChanged() { QStringList vars; QString text; for (int i = 0; i < m_variableNames.size(); ++i) { QString name = m_variableNames.at(i)->text().simplified(); if (!name.isEmpty()) { vars<name(), m_columns.size())); //determine variable names and the data vectors of the specified columns QStringList variableNames; QStringList columnPathes; QVector*> xVectors; QVector xColumns; int maxRowCount = m_spreadsheet->rowCount(); for (int i = 0; i < m_variableNames.size(); ++i) { variableNames << m_variableNames.at(i)->text().simplified(); AbstractAspect* aspect = static_cast(m_variableDataColumns.at(i)->currentModelIndex().internalPointer()); Q_ASSERT(aspect); Column* column = dynamic_cast(aspect); Q_ASSERT(column); columnPathes << column->path(); xColumns << column; xVectors << static_cast* >(column->data()); if (column->rowCount() > maxRowCount) maxRowCount = column->rowCount(); } //resize the spreadsheet if one of the data vectors from other spreadsheet(s) has more elements then the current spreadsheet. if (m_spreadsheet->rowCount() < maxRowCount) m_spreadsheet->setRowCount(maxRowCount); //create new vector for storing the calculated values //the vectors with the variable data can be smaller then the result vector. So, not all values in the result vector might get initialized. //->"clean" the result vector first QVector new_data(maxRowCount); for (int i = 0; i < new_data.size(); ++i) new_data[i] = NAN; //evaluate the expression for f(x_1, x_2, ...) and write the calculated values into a new vector. ExpressionParser* parser = ExpressionParser::getInstance(); const QString& expression = ui.teEquation->toPlainText(); parser->evaluateCartesian(expression, variableNames, xVectors, &new_data); //set the new values and store the expression, variable names and the used data columns for (auto* col : m_columns) { col->setFormula(expression, variableNames, columnPathes); col->replaceValues(0, new_data); } m_spreadsheet->endMacro(); RESET_CURSOR; } diff --git a/src/kdefrontend/spreadsheet/FunctionValuesDialog.h b/src/kdefrontend/spreadsheet/FunctionValuesDialog.h index 75706cc76..65860f4bb 100644 --- a/src/kdefrontend/spreadsheet/FunctionValuesDialog.h +++ b/src/kdefrontend/spreadsheet/FunctionValuesDialog.h @@ -1,80 +1,80 @@ /*************************************************************************** File : FunctionValuesDialog.h Project : LabPlot Description : Dialog for generating values from a mathematical function -------------------------------------------------------------------- Copyright : (C) 2014-2015 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef FUNCTIONVALUESDIALOG_H #define FUNCTIONVALUESDIALOG_H #include "ui_functionvalueswidget.h" #include #include class Column; class Spreadsheet; class TreeViewComboBox; class AspectTreeModel; class QPushButton; class QLineEdit; class FunctionValuesDialog : public QDialog { Q_OBJECT public: - explicit FunctionValuesDialog(Spreadsheet* s, QWidget* parent = 0, Qt::WFlags fl = 0); + explicit FunctionValuesDialog(Spreadsheet* s, QWidget* parent = 0); ~FunctionValuesDialog(); void setColumns(QVector); private: Ui::FunctionValuesWidget ui; QVector m_columns; Spreadsheet* m_spreadsheet; #if __cplusplus < 201103L std::auto_ptr m_aspectTreeModel; #else std::unique_ptr m_aspectTreeModel; #endif QList m_topLevelClasses; QList m_selectableClasses; QList m_variableNames; QList m_variableLabels; QList m_variableDataColumns; QList m_variableDeleteButtons; QPushButton* m_okButton; private slots: void generate(); void checkValues(); void showConstants(); void showFunctions(); void insertFunction(const QString&); void insertConstant(const QString&); void addVariable(); void deleteVariable(); void variableNameChanged(); }; #endif diff --git a/src/kdefrontend/spreadsheet/PlotDataDialog.cpp b/src/kdefrontend/spreadsheet/PlotDataDialog.cpp index 1ac7ddf4f..07323c1da 100644 --- a/src/kdefrontend/spreadsheet/PlotDataDialog.cpp +++ b/src/kdefrontend/spreadsheet/PlotDataDialog.cpp @@ -1,581 +1,581 @@ /*************************************************************************** File : PlotDataDialog.cpp Project : LabPlot Description : Dialog for generating plots for the spreadsheet data -------------------------------------------------------------------- Copyright : (C) 2017 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "PlotDataDialog.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/Project.h" #include "backend/core/column/Column.h" #include "backend/spreadsheet/Spreadsheet.h" #include "backend/worksheet/plots/cartesian/Axis.h" #include "backend/worksheet/plots/cartesian/XYAnalysisCurve.h" #include "backend/worksheet/plots/cartesian/XYCurve.h" #include "backend/worksheet/plots/cartesian/XYDataReductionCurve.h" #include "backend/worksheet/plots/cartesian/XYDifferentiationCurve.h" #include "backend/worksheet/plots/cartesian/XYIntegrationCurve.h" #include "backend/worksheet/plots/cartesian/XYInterpolationCurve.h" #include "backend/worksheet/plots/cartesian/XYSmoothCurve.h" #include "backend/worksheet/plots/cartesian/XYFitCurve.h" #include "backend/worksheet/plots/cartesian/XYFourierFilterCurve.h" #include "backend/worksheet/plots/cartesian/CartesianPlot.h" #include "backend/worksheet/Worksheet.h" #include "backend/worksheet/TextLabel.h" #include "commonfrontend/spreadsheet/SpreadsheetView.h" #include "commonfrontend/widgets/TreeViewComboBox.h" #include #include #include #include #include #include #include "ui_plotdatawidget.h" /*! \class PlotDataDialog \brief Dialog for generating plots for the spreadsheet data. \ingroup kdefrontend */ -PlotDataDialog::PlotDataDialog(Spreadsheet* s, QWidget* parent, Qt::WFlags fl) : QDialog(parent, fl), +PlotDataDialog::PlotDataDialog(Spreadsheet* s, QWidget* parent) : QDialog(parent), ui(new Ui::PlotDataWidget()), m_spreadsheet(s), m_plotsModel(new AspectTreeModel(m_spreadsheet->project())), m_worksheetsModel(new AspectTreeModel(m_spreadsheet->project())), m_analysisAction(Differentiation), m_analysisMode(false) { setAttribute(Qt::WA_DeleteOnClose); setWindowTitle(i18nc("@title:window", "Plot Spreadsheet Data")); setWindowIcon(QIcon::fromTheme("office-chart-line")); QWidget* mainWidget = new QWidget(this); ui->setupUi(mainWidget); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); m_okButton = buttonBox->button(QDialogButtonBox::Ok); m_okButton->setDefault(true); m_okButton->setToolTip(i18n("Plot the selected data")); m_okButton->setText(i18n("&Plot")); QVBoxLayout* layout = new QVBoxLayout(this); layout->addWidget(mainWidget); layout->addWidget(buttonBox); setLayout(layout); //create combox boxes for the existing plots and worksheets QGridLayout* gridLayout = dynamic_cast(ui->gbPlotPlacement->layout()); cbExistingPlots = new TreeViewComboBox(ui->gbPlotPlacement); cbExistingPlots->setMinimumWidth(250);//TODO: use proper sizeHint in TreeViewComboBox gridLayout->addWidget(cbExistingPlots, 0, 1, 1, 1); cbExistingWorksheets = new TreeViewComboBox(ui->gbPlotPlacement); cbExistingWorksheets->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred)); gridLayout->addWidget(cbExistingWorksheets, 1, 1, 1, 1); QList list; list<<"Folder"<<"Worksheet"<<"CartesianPlot"; cbExistingPlots->setTopLevelClasses(list); list.clear(); list<<"CartesianPlot"; m_plotsModel->setSelectableAspects(list); cbExistingPlots->setModel(m_plotsModel); //select the first available plot, if available auto plots = m_spreadsheet->project()->children(AbstractAspect::Recursive); if (!plots.isEmpty()) { const auto plot = plots.first(); cbExistingPlots->setCurrentModelIndex(m_plotsModel->modelIndexOfAspect(plot)); } list.clear(); list<<"Folder"<<"Worksheet"; cbExistingWorksheets->setTopLevelClasses(list); list.clear(); list<<"Worksheet"; m_worksheetsModel->setSelectableAspects(list); cbExistingWorksheets->setModel(m_worksheetsModel); //select the first available worksheet, if available auto worksheets = m_spreadsheet->project()->children(AbstractAspect::Recursive); if (!worksheets.isEmpty()) { const auto worksheet = worksheets.first(); cbExistingWorksheets->setCurrentModelIndex(m_worksheetsModel->modelIndexOfAspect(worksheet)); } //hide the check box for creation of original data, only shown if analysis curves are to be created ui->chkCreateDataCurve->setVisible(false); //SIGNALs/SLOTs connect(buttonBox, &QDialogButtonBox::accepted, this, [=]() { hide(); plot(); }); connect(buttonBox, &QDialogButtonBox::rejected, this, &PlotDataDialog::reject); connect(buttonBox, &QDialogButtonBox::accepted, this, &PlotDataDialog::accept); connect(ui->rbCurvePlacement1, &QRadioButton::toggled, this, &PlotDataDialog::curvePlacementChanged); connect(ui->rbCurvePlacement2, &QRadioButton::toggled, this, &PlotDataDialog::curvePlacementChanged); connect(ui->rbPlotPlacement1, &QRadioButton::toggled, this, &PlotDataDialog::plotPlacementChanged); connect(ui->rbPlotPlacement2, &QRadioButton::toggled, this, &PlotDataDialog::plotPlacementChanged); connect(ui->rbPlotPlacement3, &QRadioButton::toggled, this, &PlotDataDialog::plotPlacementChanged); connect(cbExistingPlots, &TreeViewComboBox::currentModelIndexChanged, this, &PlotDataDialog::checkOkButton); connect(cbExistingWorksheets, &TreeViewComboBox::currentModelIndexChanged, this, &PlotDataDialog::checkOkButton); QTimer::singleShot(0, this, &PlotDataDialog::loadSettings); } void PlotDataDialog::loadSettings() { //restore saved settings if available QApplication::processEvents(QEventLoop::AllEvents, 0); const KConfigGroup conf(KSharedConfig::openConfig(), "PlotDataDialog"); if (conf.exists()) { KWindowConfig::restoreWindowSize(windowHandle(), conf); int index = conf.readEntry("CurvePlacement", 0); if (index == 2) ui->rbCurvePlacement2->setChecked(true); index = conf.readEntry("PlotPlacement", 0); if (index == 2) ui->rbPlotPlacement2->setChecked(true); if (index == 3) ui->rbPlotPlacement3->setChecked(true); } else resize( QSize(0,0).expandedTo(minimumSize()) ); processColumns(); plotPlacementChanged(); } PlotDataDialog::~PlotDataDialog() { //save current settings KConfigGroup conf(KSharedConfig::openConfig(), "PlotDataDialog"); int index = 0; if (ui->rbCurvePlacement1->isChecked()) index = 1; if (ui->rbCurvePlacement2->isChecked()) index = 2; conf.writeEntry("CurvePlacement", index); if (ui->rbPlotPlacement1->isChecked()) index = 1; if (ui->rbPlotPlacement2->isChecked()) index = 2; if (ui->rbPlotPlacement3->isChecked()) index = 3; conf.writeEntry("PlotPlacement", index); KWindowConfig::saveWindowSize(windowHandle(), conf); delete m_plotsModel; delete m_worksheetsModel; } void PlotDataDialog::setAnalysisAction(AnalysisAction action) { m_analysisAction = action; m_analysisMode = true; ui->chkCreateDataCurve->setVisible(true); } void PlotDataDialog::processColumns() { //columns to plot SpreadsheetView* view = reinterpret_cast(m_spreadsheet->view()); QVector selectedColumns = view->selectedColumns(true); if (!selectedColumns.size()) { //use all spreadsheet columns if no columns are selected //skip error columns for (Column* col : m_spreadsheet->children()) if (col->plotDesignation() == AbstractColumn::X || col->plotDesignation() == AbstractColumn::Y || col->plotDesignation() == AbstractColumn::NoDesignation) m_columns << col; //disable everything if the spreadsheet doesn't have any columns if (!m_columns.size()) { ui->gbData->setEnabled(false); ui->gbCurvePlacement->setEnabled(false); ui->gbPlotPlacement->setEnabled(false); return; } } else { //use selected columns, skip error columns for (Column* col : selectedColumns) if (col->plotDesignation() == AbstractColumn::X || col->plotDesignation() == AbstractColumn::Y || col->plotDesignation() == AbstractColumn::NoDesignation) m_columns << col; } //determine the column names and the name of the first column having "X" as the plot designation QList columnNames; QString xColumnName; for(const Column* column : m_columns) { columnNames << column->name(); if (xColumnName.isEmpty() && column->plotDesignation() == AbstractColumn::X) xColumnName = column->name(); } if (xColumnName.isEmpty()) { //no X-column was selected -> look for the first non-selected X-column left to the first selected column const int index = m_spreadsheet->indexOfChild(selectedColumns.first()) - 1; if (index >= 0) { for (int i = index; i >= 0; --i) { Column* column = m_spreadsheet->column(i); if (column->plotDesignation() == AbstractColumn::X) { xColumnName = column->name(); m_columns.prepend(column); columnNames.prepend(xColumnName); break; } } } } m_columnComboBoxes << ui->cbXColumn; m_columnComboBoxes << ui->cbYColumn; //ui-widget only has one combobox for the y-data -> add additional comboboxes dynamically if required if (m_columns.size()>2) { QGridLayout* gridLayout = dynamic_cast(ui->scrollAreaYColumns->widget()->layout()); for (int i = 2; i < m_columns.size(); ++i) { QLabel* label = new QLabel(i18n("Y-data")); QComboBox* comboBox = new QComboBox(); gridLayout->addWidget(label, i+1, 0, 1, 1); gridLayout->addWidget(comboBox, i+1, 2, 1, 1); m_columnComboBoxes << comboBox; } } else { //two columns provided, only one curve is possible -> hide the curve placement options ui->rbCurvePlacement1->setChecked(true); ui->gbCurvePlacement->hide(); ui->gbPlotPlacement->setTitle(i18n("Add curve to")); } //show all selected/available column names in the data comboboxes for(QComboBox* const comboBox : m_columnComboBoxes) comboBox->addItems(columnNames); if (!xColumnName.isEmpty()) { //show in the X-data combobox the first column having X as the plot designation ui->cbXColumn->setCurrentIndex(ui->cbXColumn->findText(xColumnName)); //for the remaining columns, show the names in the comboboxes for the Y-data //TODO: handle columns with error-designations int yColumnIndex = 1; //the index of the first Y-data comboBox in m_columnComboBoxes for(const QString& name : columnNames) { if (name != xColumnName) { QComboBox* comboBox = m_columnComboBoxes[yColumnIndex]; comboBox->setCurrentIndex(comboBox->findText(name)); yColumnIndex++; } } } else { //no column with "x plot designation" is selected, simply show all columns in the order they were selected. //first selected column will serve as the x-column. int yColumnIndex = 0; for(const QString& name : columnNames) { QComboBox* comboBox = m_columnComboBoxes[yColumnIndex]; comboBox->setCurrentIndex(comboBox->findText(name)); yColumnIndex++; } } } void PlotDataDialog::plot() { DEBUG("PlotDataDialog::plot()"); WAIT_CURSOR; if (ui->rbPlotPlacement1->isChecked()) { //add curves to an existing plot AbstractAspect* aspect = static_cast(cbExistingPlots->currentModelIndex().internalPointer()); CartesianPlot* plot = dynamic_cast(aspect); plot->beginMacro( i18n("Plot data from %1", m_spreadsheet->name()) ); addCurvesToPlot(plot); plot->endMacro(); } else if (ui->rbPlotPlacement2->isChecked()) { //add curves to a new plot in an existing worksheet AbstractAspect* aspect = static_cast(cbExistingWorksheets->currentModelIndex().internalPointer()); Worksheet* worksheet = dynamic_cast(aspect); worksheet->beginMacro( i18n("Plot data from %1", m_spreadsheet->name()) ); if (ui->rbCurvePlacement1->isChecked()) { //all curves in one plot CartesianPlot* plot = new CartesianPlot( i18n("Plot data from %1", m_spreadsheet->name()) ); plot->initDefault(CartesianPlot::FourAxes); //set the axis titles befor we add the plot to the worksheet //set the x-axis names const QString& xColumnName = ui->cbXColumn->currentText(); for (auto axis : plot->children()) { if (axis->orientation() == Axis::AxisHorizontal) { axis->title()->setText(xColumnName); break; } } //if we only have one single y-column to plot, we can set the title of the y-axes if (m_columnComboBoxes.size() == 2) { const QString& yColumnName = m_columnComboBoxes[1]->currentText(); for (auto axis : plot->children()) { if (axis->orientation() == Axis::AxisVertical) { axis->title()->setText(yColumnName); break; } } } worksheet->addChild(plot); addCurvesToPlot(plot); } else { //one plot per curve addCurvesToPlots(worksheet); } worksheet->endMacro(); } else { //add curves to a new plot(s) in a new worksheet AbstractAspect* parent = m_spreadsheet->parentAspect(); parent->beginMacro( i18n("Plot data from %1", m_spreadsheet->name()) ); Worksheet* worksheet = new Worksheet(0, i18n("Plot data from %1", m_spreadsheet->name())); parent->addChild(worksheet); if (ui->rbCurvePlacement1->isChecked()) { //all curves in one plot CartesianPlot* plot = new CartesianPlot( i18n("Plot data from %1", m_spreadsheet->name()) ); plot->initDefault(CartesianPlot::FourAxes); //set the axis titles befor we add the plot to the worksheet //set the x-axis names const QString& xColumnName = ui->cbXColumn->currentText(); for (auto axis : plot->children()) { if (axis->orientation() == Axis::AxisHorizontal) { axis->title()->setText(xColumnName); break; } } //if we only have one single y-column to plot, we can set the title of the y-axes if (m_columnComboBoxes.size() == 2) { const QString& yColumnName = m_columnComboBoxes[1]->currentText(); for (auto axis : plot->children()) { if (axis->orientation() == Axis::AxisVertical) { axis->title()->setText(yColumnName); break; } } } worksheet->addChild(plot); addCurvesToPlot(plot); } else { //one plot per curve addCurvesToPlots(worksheet); } parent->endMacro(); } RESET_CURSOR; } Column* PlotDataDialog::columnFromName(const QString& name) const { for(auto* column : m_columns) { if (column->name() == name) return column; } return 0; } /*! * * for the selected columns in this dialog, creates a curve in the already existing plot \c plot. */ void PlotDataDialog::addCurvesToPlot(CartesianPlot* plot) const { QApplication::processEvents(QEventLoop::AllEvents, 100); Column* xColumn = columnFromName(ui->cbXColumn->currentText()); for (int i = 1; i < m_columnComboBoxes.size(); ++i) { QComboBox* comboBox = m_columnComboBoxes[i]; const QString& name = comboBox->currentText(); Column* yColumn = columnFromName(name); addCurve(name, xColumn, yColumn, plot); } plot->scaleAuto(); } /*! * for the selected columns in this dialog, creates a plot and a curve in the already existing worksheet \c worksheet. */ void PlotDataDialog::addCurvesToPlots(Worksheet* worksheet) const { QApplication::processEvents(QEventLoop::AllEvents, 100); worksheet->setSuppressLayoutUpdate(true); const QString& xColumnName = ui->cbXColumn->currentText(); Column* xColumn = columnFromName(xColumnName); for (int i = 1; i < m_columnComboBoxes.size(); ++i) { QComboBox* comboBox = m_columnComboBoxes[i]; const QString& name = comboBox->currentText(); Column* yColumn = columnFromName(name); CartesianPlot* plot = new CartesianPlot(i18n("Plot %1", name)); plot->initDefault(CartesianPlot::FourAxes); //set the axis names in the new plot bool xSet = false; bool ySet = false; for (auto axis : plot->children()) { if (axis->orientation() == Axis::AxisHorizontal && !xSet) { axis->title()->setText(xColumnName); xSet = true; } else if (axis->orientation() == Axis::AxisVertical && !ySet) { axis->title()->setText(name); ySet = true; } } worksheet->addChild(plot); addCurve(name, xColumn, yColumn, plot); plot->scaleAuto(); } worksheet->setSuppressLayoutUpdate(false); worksheet->updateLayout(); } /*! * helper function that does the actual creation of the curve and adding it as child to the \c plot. */ void PlotDataDialog::addCurve(const QString& name, Column* xColumn, Column* yColumn, CartesianPlot* plot) const { DEBUG("PlotDataDialog::addCurve()"); if (!m_analysisMode) { XYCurve* curve = new XYCurve(name); curve->suppressRetransform(true); curve->setXColumn(xColumn); curve->setYColumn(yColumn); curve->suppressRetransform(false); plot->addChild(curve); } else { bool createDataCurve = ui->chkCreateDataCurve->isChecked(); XYCurve* curve = 0; if (createDataCurve) { curve = new XYCurve(name); curve->suppressRetransform(true); curve->setXColumn(xColumn); curve->setYColumn(yColumn); curve->suppressRetransform(false); plot->addChild(curve); } XYAnalysisCurve* analysisCurve = nullptr; switch (m_analysisAction) { case DataReduction: analysisCurve = new XYDataReductionCurve(i18n("Reduction of '%1'", name)); break; case Differentiation: analysisCurve = new XYDifferentiationCurve(i18n("Derivative of '%1'", name)); break; case Integration: analysisCurve = new XYIntegrationCurve(i18n("Integral of '%1'", name)); break; case Interpolation: analysisCurve = new XYInterpolationCurve(i18n("Interpolation of '%1'", name)); break; case Smoothing: analysisCurve = new XYSmoothCurve(i18n("Smoothing of '%1'", name)); break; case FitLinear: case FitPower: case FitExp1: case FitExp2: case FitInvExp: case FitGauss: case FitCauchyLorentz: case FitTan: case FitTanh: case FitErrFunc: case FitCustom: analysisCurve = new XYFitCurve(i18n("Fit to '%1'", name)); static_cast(analysisCurve)->initFitData(m_analysisAction); static_cast(analysisCurve)->initStartValues(curve); break; case FourierFilter: analysisCurve = new XYFourierFilterCurve(i18n("Fourier Filter of '%1'", name)); break; } if (analysisCurve != nullptr) { analysisCurve->suppressRetransform(true); analysisCurve->setXDataColumn(xColumn); analysisCurve->setYDataColumn(yColumn); analysisCurve->recalculate(); analysisCurve->suppressRetransform(false); plot->addChild(analysisCurve); } } } //################################################################ //########################## Slots ############################### //################################################################ void PlotDataDialog::curvePlacementChanged() { if (ui->rbCurvePlacement1->isChecked()) { ui->rbPlotPlacement1->setEnabled(true); ui->rbPlotPlacement2->setText(i18n("new plot in an existing worksheet")); ui->rbPlotPlacement3->setText(i18n("new plot in a new worksheet")); } else { ui->rbPlotPlacement1->setEnabled(false); if (ui->rbPlotPlacement1->isChecked()) ui->rbPlotPlacement2->setChecked(true); ui->rbPlotPlacement2->setText(i18n("new plots in an existing worksheet")); ui->rbPlotPlacement3->setText(i18n("new plots in a new worksheet")); } } void PlotDataDialog::plotPlacementChanged() { if (ui->rbPlotPlacement1->isChecked()) { cbExistingPlots->setEnabled(true); cbExistingWorksheets->setEnabled(false); } else if (ui->rbPlotPlacement2->isChecked()) { cbExistingPlots->setEnabled(false); cbExistingWorksheets->setEnabled(true); } else { cbExistingPlots->setEnabled(false); cbExistingWorksheets->setEnabled(false); } checkOkButton(); } void PlotDataDialog::checkOkButton() { bool enable = false; QString msg; if (ui->rbPlotPlacement1->isChecked()) { AbstractAspect* aspect = static_cast(cbExistingPlots->currentModelIndex().internalPointer()); enable = (aspect!=NULL); if (!enable) msg = i18n("An already existing plot has to be selected."); } else if (ui->rbPlotPlacement2->isChecked()) { AbstractAspect* aspect = static_cast(cbExistingWorksheets->currentModelIndex().internalPointer()); enable = (aspect!=NULL); if (!enable) msg = i18n("An already existing worksheet has to be selected."); } else enable = true; m_okButton->setEnabled(enable); if (enable) m_okButton->setToolTip(i18n("Close the dialog and plot the data.")); else m_okButton->setToolTip(msg); } diff --git a/src/kdefrontend/spreadsheet/PlotDataDialog.h b/src/kdefrontend/spreadsheet/PlotDataDialog.h index 210e75d9b..5fef40f65 100644 --- a/src/kdefrontend/spreadsheet/PlotDataDialog.h +++ b/src/kdefrontend/spreadsheet/PlotDataDialog.h @@ -1,88 +1,88 @@ /*************************************************************************** File : PlotDataDialog.h Project : LabPlot Description : Dialog for generating plots for the spreadsheet data -------------------------------------------------------------------- Copyright : (C) 2017 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef PLOTDATADIALOG_H #define PLOTDATADIALOG_H namespace Ui { class PlotDataWidget; } #include class QComboBox; class AspectTreeModel; class CartesianPlot; class Column; class Spreadsheet; class TreeViewComboBox; class Worksheet; class PlotDataDialog : public QDialog { Q_OBJECT public: enum AnalysisAction {DataReduction, Differentiation, Integration, Interpolation, Smoothing, FitLinear, FitPower, FitExp1, FitExp2, FitInvExp, FitGauss, FitCauchyLorentz, FitTan, FitTanh, FitErrFunc, FitCustom, FourierFilter}; - explicit PlotDataDialog(Spreadsheet*, QWidget* parent = 0, Qt::WFlags fl = 0); + explicit PlotDataDialog(Spreadsheet*, QWidget* parent = 0); ~PlotDataDialog() override; void setAnalysisAction(AnalysisAction); private: Ui::PlotDataWidget* ui; QPushButton* m_okButton; Spreadsheet* m_spreadsheet; TreeViewComboBox* cbExistingPlots; TreeViewComboBox* cbExistingWorksheets; QVector m_columns; QVector m_columnComboBoxes; AspectTreeModel* m_plotsModel; AspectTreeModel* m_worksheetsModel; AnalysisAction m_analysisAction; bool m_analysisMode; void processColumns(); void addCurvesToPlot(CartesianPlot*) const; void addCurvesToPlots(Worksheet*) const; void addCurve(const QString& name, Column* xColumn, Column* yColumn, CartesianPlot*) const; Column* columnFromName(const QString&) const; protected slots: virtual void checkOkButton(); private slots: void plot(); void curvePlacementChanged(); void plotPlacementChanged(); void loadSettings(); }; #endif diff --git a/src/kdefrontend/spreadsheet/RandomValuesDialog.cpp b/src/kdefrontend/spreadsheet/RandomValuesDialog.cpp index f60922926..9e15dfb69 100644 --- a/src/kdefrontend/spreadsheet/RandomValuesDialog.cpp +++ b/src/kdefrontend/spreadsheet/RandomValuesDialog.cpp @@ -1,729 +1,729 @@ /*************************************************************************** File : RandomValuesDialog.cpp Project : LabPlot Description : Dialog for generating non-uniformly distributed random numbers -------------------------------------------------------------------- Copyright : (C) 2014 by Alexander Semke (alexander.semke@web.de) Copyright : (C) 2016-2018 by Stefan Gerlach (stefan.gerlach@uni.kn) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "RandomValuesDialog.h" #include "backend/core/column/Column.h" #include "backend/lib/macros.h" #include "backend/spreadsheet/Spreadsheet.h" #include #include #include #include #include #include #include #include extern "C" { #include #include "backend/nsl/nsl_sf_stats.h" #include #include } /*! \class RandomValuesDialog \brief Dialog for generating non-uniform random numbers. \ingroup kdefrontend */ -RandomValuesDialog::RandomValuesDialog(Spreadsheet* s, QWidget* parent, Qt::WFlags fl) : QDialog(parent, fl), m_spreadsheet(s) { +RandomValuesDialog::RandomValuesDialog(Spreadsheet* s, QWidget* parent) : QDialog(parent), m_spreadsheet(s) { setWindowTitle(i18nc("@title:window", "Random Values")); QWidget* mainWidget = new QWidget(this); ui.setupUi(mainWidget); QVBoxLayout *layout = new QVBoxLayout(this); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); m_okButton = buttonBox->button(QDialogButtonBox::Ok); m_okButton->setDefault(true); m_okButton->setToolTip(i18n("Generate random values according to the selected distribution")); m_okButton->setText(i18n("&Generate")); connect(buttonBox->button(QDialogButtonBox::Cancel), &QPushButton::clicked, this, &RandomValuesDialog::close); connect(buttonBox, &QDialogButtonBox::accepted, this, &RandomValuesDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &RandomValuesDialog::reject); layout->addWidget(mainWidget); layout->addWidget(buttonBox); setLayout(layout); setAttribute(Qt::WA_DeleteOnClose); for (int i = 0; i < NSL_SF_STATS_DISTRIBUTION_RNG_COUNT; i++) ui.cbDistribution->addItem(i18n(nsl_sf_stats_distribution_name[i]), i); //use white background in the preview label QPalette p; p.setColor(QPalette::Window, Qt::white); ui.lFuncPic->setAutoFillBackground(true); ui.lFuncPic->setPalette(p); ui.leParameter1->setClearButtonEnabled(true); ui.leParameter2->setClearButtonEnabled(true); ui.leParameter3->setClearButtonEnabled(true); ui.leParameter1->setValidator( new QDoubleValidator(ui.leParameter1) ); ui.leParameter2->setValidator( new QDoubleValidator(ui.leParameter2) ); ui.leParameter3->setValidator( new QDoubleValidator(ui.leParameter3) ); connect(ui.cbDistribution, static_cast(&QComboBox::currentIndexChanged), this, &RandomValuesDialog::distributionChanged); connect(ui.leParameter1, &QLineEdit::textChanged, this, &RandomValuesDialog::checkValues); connect(ui.leParameter2, &QLineEdit::textChanged, this, &RandomValuesDialog::checkValues); connect(ui.leParameter3, &QLineEdit::textChanged, this, &RandomValuesDialog::checkValues); connect(buttonBox, &QDialogButtonBox::accepted, this, &RandomValuesDialog::generate); //restore saved settings if available const KConfigGroup conf(KSharedConfig::openConfig(), "RandomValuesDialog"); if (conf.exists()) { ui.cbDistribution->setCurrentIndex(conf.readEntry("Distribution", 0)); this->distributionChanged(ui.cbDistribution->currentIndex()); //if index=0 no signal is emmited above, call this slot directly here ui.leParameter1->setText(conf.readEntry("Parameter1")); ui.leParameter2->setText(conf.readEntry("Parameter2")); ui.leParameter3->setText(conf.readEntry("Parameter3")); KWindowConfig::restoreWindowSize(windowHandle(), conf); } else { //Gaussian distribution as default this->distributionChanged(0); resize( QSize(400,0).expandedTo(minimumSize()) ); } } RandomValuesDialog::~RandomValuesDialog() { //save current settings KConfigGroup conf(KSharedConfig::openConfig(), "RandomValuesDialog"); conf.writeEntry("Distribution", ui.cbDistribution->currentIndex()); conf.writeEntry("Parameter1", ui.leParameter1->text()); conf.writeEntry("Parameter2", ui.leParameter2->text()); conf.writeEntry("Parameter3", ui.leParameter3->text()); KWindowConfig::saveWindowSize(windowHandle(), conf); } void RandomValuesDialog::setColumns(QVector columns) { m_columns = columns; } void RandomValuesDialog::distributionChanged(int index) { nsl_sf_stats_distribution dist = (nsl_sf_stats_distribution)ui.cbDistribution->itemData(index).toInt(); // default settings (used by most distributions) ui.lParameter1->show(); ui.leParameter1->show(); ui.lParameter2->show(); ui.leParameter2->show(); ui.lParameter3->hide(); ui.leParameter3->hide(); ui.lFunc->setText("p(x) ="); switch (dist) { case nsl_sf_stats_gaussian: ui.lParameter1->setText(UTF8_QSTRING("μ =")); ui.lParameter2->setText(UTF8_QSTRING("σ =")); ui.leParameter1->setText("0.0"); ui.leParameter2->setText("1.0"); break; case nsl_sf_stats_gaussian_tail: ui.lParameter3->show(); ui.leParameter3->show(); ui.lParameter1->setText(UTF8_QSTRING("μ =")); ui.lParameter2->setText(UTF8_QSTRING("σ =")); ui.lParameter3->setText("a ="); ui.leParameter1->setText("0.0"); ui.leParameter2->setText("1.0"); ui.leParameter3->setText("0.0"); break; case nsl_sf_stats_exponential: ui.lParameter1->setText(UTF8_QSTRING("λ =")); ui.leParameter1->setText("1.0"); ui.lParameter2->setText(UTF8_QSTRING("μ =")); ui.leParameter2->setText("0.0"); break; case nsl_sf_stats_laplace: ui.lParameter1->setText(UTF8_QSTRING("μ =")); ui.lParameter2->setText(UTF8_QSTRING("σ =")); ui.leParameter1->setText("0.0"); ui.leParameter2->setText("1.0"); break; case nsl_sf_stats_exponential_power: ui.lParameter3->show(); ui.leParameter3->show(); ui.lParameter1->setText(UTF8_QSTRING("μ =")); ui.lParameter2->setText(UTF8_QSTRING("σ =")); ui.lParameter3->setText("b ="); ui.leParameter1->setText("0.0"); ui.leParameter2->setText("1.0"); ui.leParameter3->setText("1.0"); break; case nsl_sf_stats_cauchy_lorentz: ui.lParameter1->setText(UTF8_QSTRING("γ =")); ui.lParameter2->setText(UTF8_QSTRING("μ =")); ui.leParameter1->setText("1.0"); ui.leParameter2->setText("0.0"); break; case nsl_sf_stats_rayleigh: ui.lParameter2->hide(); ui.leParameter2->hide(); ui.lParameter1->setText(UTF8_QSTRING("σ =")); ui.leParameter1->setText("1.0"); break; case nsl_sf_stats_rayleigh_tail: ui.lParameter1->setText(UTF8_QSTRING("μ =")); ui.lParameter2->setText(UTF8_QSTRING("σ =")); ui.leParameter1->setText("0.0"); ui.leParameter2->setText("1.0"); break; case nsl_sf_stats_landau: ui.lParameter1->hide(); ui.leParameter1->hide(); ui.lParameter2->hide(); ui.leParameter2->hide(); break; case nsl_sf_stats_levy_alpha_stable: ui.lParameter1->setText("c ="); ui.lParameter2->setText(UTF8_QSTRING("α =")); ui.leParameter1->setText("1.0"); ui.leParameter2->setText("1.0"); break; case nsl_sf_stats_levy_skew_alpha_stable: ui.lParameter3->show(); ui.leParameter3->show(); ui.lParameter1->setText(UTF8_QSTRING("c =")); ui.lParameter2->setText(UTF8_QSTRING("α =")); ui.lParameter3->setText(UTF8_QSTRING("β =")); ui.leParameter1->setText("1.0"); ui.leParameter2->setText("1.0"); ui.leParameter3->setText("1.0"); break; case nsl_sf_stats_flat: ui.lParameter1->setText("a ="); ui.lParameter2->setText("b ="); ui.leParameter1->setText("0.0"); ui.leParameter2->setText("1.0"); break; case nsl_sf_stats_gamma: ui.lParameter1->setText(UTF8_QSTRING("θ =")); ui.lParameter2->setText("k ="); ui.leParameter1->setText("1.0"); ui.leParameter2->setText("1.0"); break; case nsl_sf_stats_weibull: ui.lParameter3->show(); ui.leParameter3->show(); ui.lParameter1->setText("k ="); ui.lParameter2->setText(UTF8_QSTRING("λ =")); ui.lParameter3->setText(UTF8_QSTRING("μ =")); ui.leParameter1->setText("1.0"); ui.leParameter2->setText("1.0"); ui.leParameter3->setText("1.0"); break; case nsl_sf_stats_beta: ui.lParameter1->setText("a ="); ui.lParameter2->setText("b ="); ui.leParameter1->setText("1.0"); ui.leParameter2->setText("1.0"); break; case nsl_sf_stats_gumbel1: ui.lParameter3->show(); ui.leParameter3->show(); ui.lParameter1->setText(UTF8_QSTRING("σ =")); ui.lParameter2->setText(UTF8_QSTRING("β =")); ui.lParameter3->setText(UTF8_QSTRING("μ =")); ui.leParameter1->setText("1.0"); ui.leParameter2->setText("1.0"); ui.leParameter3->setText("0.0"); break; case nsl_sf_stats_gumbel2: ui.lParameter3->show(); ui.leParameter3->show(); ui.lParameter1->setText("a ="); ui.lParameter2->setText("b ="); ui.lParameter3->setText(UTF8_QSTRING("μ =")); ui.leParameter1->setText("1.0"); ui.leParameter2->setText("1.0"); ui.leParameter3->setText("0.0"); break; case nsl_sf_stats_pareto: ui.lParameter1->setText("a ="); ui.lParameter2->setText("b ="); ui.leParameter1->setText("1.0"); ui.leParameter2->setText("0.0"); break; case nsl_sf_stats_lognormal: ui.lParameter1->setText(UTF8_QSTRING("σ =")); ui.lParameter2->setText(UTF8_QSTRING("μ =")); ui.leParameter1->setText("1.0"); ui.leParameter2->setText("1.0"); break; case nsl_sf_stats_chi_squared: ui.lParameter2->hide(); ui.leParameter2->hide(); ui.lParameter1->setText("n ="); ui.leParameter1->setText("1.0"); break; case nsl_sf_stats_fdist: ui.lParameter1->setText(UTF8_QSTRING("ν₁ =")); ui.lParameter2->setText(UTF8_QSTRING("ν₂ =")); ui.leParameter1->setText("1.0"); ui.leParameter2->setText("1.0"); break; case nsl_sf_stats_tdist: ui.lParameter2->hide(); ui.leParameter2->hide(); ui.lParameter1->setText(UTF8_QSTRING("ν =")); ui.leParameter1->setText("1.0"); break; case nsl_sf_stats_logistic: ui.lParameter1->setText(UTF8_QSTRING("σ =")); ui.lParameter2->setText(UTF8_QSTRING("μ =")); ui.leParameter1->setText("1.0"); ui.leParameter2->setText("0.0"); break; case nsl_sf_stats_poisson: ui.lParameter2->hide(); ui.leParameter2->hide(); ui.lFunc->setText("p(k) ="); ui.lParameter1->setText(UTF8_QSTRING("λ =")); ui.leParameter1->setText("1.0"); break; case nsl_sf_stats_bernoulli: case nsl_sf_stats_geometric: case nsl_sf_stats_logarithmic: ui.lParameter2->hide(); ui.leParameter2->hide(); if (dist == nsl_sf_stats_bernoulli) ui.lFunc->setText(""); else ui.lFunc->setText("p(k) ="); ui.lParameter1->setText("p ="); ui.leParameter1->setText("0.5"); break; case nsl_sf_stats_binomial: case nsl_sf_stats_negative_binomial: case nsl_sf_stats_pascal: ui.lFunc->setText("p(k) ="); ui.lParameter1->setText("p ="); ui.lParameter2->setText("n ="); ui.leParameter1->setText("0.5"); ui.leParameter2->setText("100"); break; case nsl_sf_stats_hypergeometric: ui.lParameter3->show(); ui.leParameter3->show(); ui.lFunc->setText("p(k) ="); ui.lParameter1->setText("n1 ="); ui.lParameter2->setText("n2 ="); ui.lParameter3->setText("t ="); ui.leParameter1->setText("1.0"); ui.leParameter2->setText("2.0"); ui.leParameter3->setText("3.0"); break; case nsl_sf_stats_maxwell_boltzmann: // additional non-GSL distros case nsl_sf_stats_sech: case nsl_sf_stats_levy: case nsl_sf_stats_frechet: break; } QString file = QStandardPaths::locate(QStandardPaths::AppDataLocation, "pics/gsl_distributions/" + QString(nsl_sf_stats_distribution_pic_name[dist]) + ".png"); DEBUG("Distribution pixmap path = " << file.toStdString()); ui.lFuncPic->setPixmap(QPixmap(file)); } void RandomValuesDialog::checkValues() { if (ui.leParameter1->text().simplified().isEmpty()) { m_okButton->setEnabled(false); return; } if (ui.leParameter2->isVisible() && ui.leParameter2->text().simplified().isEmpty()) { m_okButton->setEnabled(false); return; } if (ui.leParameter3->isVisible() && ui.leParameter3->text().simplified().isEmpty()) { m_okButton->setEnabled(false); return; } m_okButton->setEnabled(true); return; } void RandomValuesDialog::generate() { Q_ASSERT(m_spreadsheet); //create a generator chosen by the environment variable GSL_RNG_TYPE gsl_rng_env_setup(); const gsl_rng_type* T = gsl_rng_default; gsl_rng* r = gsl_rng_alloc(T); WAIT_CURSOR; for (auto* col : m_columns) col->setSuppressDataChangedSignal(true); m_spreadsheet->beginMacro(i18np("%1: fill column with non-uniform random numbers", "%1: fill columns with non-uniform random numbers", m_spreadsheet->name(), m_columns.size())); const int index = ui.cbDistribution->currentIndex(); const nsl_sf_stats_distribution dist = (nsl_sf_stats_distribution)ui.cbDistribution->itemData(index).toInt(); DEBUG("random number distribution: " << nsl_sf_stats_distribution_name[dist]); const int rows = m_spreadsheet->rowCount(); QVector new_data(rows); switch (dist) { case nsl_sf_stats_gaussian: { double mu = ui.leParameter1->text().toDouble(); double sigma = ui.leParameter2->text().toDouble(); DEBUG(" mu = " << mu << ", sigma = " << sigma); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_gaussian(r, sigma) + mu; col->replaceValues(0, new_data); } break; } case nsl_sf_stats_gaussian_tail: { double mu = ui.leParameter1->text().toDouble(); double sigma = ui.leParameter2->text().toDouble(); double a = ui.leParameter3->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_gaussian_tail(r, a, sigma) + mu; col->replaceValues(0, new_data); } break; } case nsl_sf_stats_exponential: { double l = ui.leParameter1->text().toDouble(); double mu = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { //GSL uses the inverse for exp. distrib. for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_exponential(r, 1./l) + mu; col->replaceValues(0, new_data); } break; } case nsl_sf_stats_laplace: { double mu = ui.leParameter1->text().toDouble(); double s = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_laplace(r, s) + mu; col->replaceValues(0, new_data); } break; } case nsl_sf_stats_exponential_power: { double mu = ui.leParameter1->text().toDouble(); double a = ui.leParameter2->text().toDouble(); double b = ui.leParameter3->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_exppow(r, a, b) + mu; col->replaceValues(0, new_data); } break; } case nsl_sf_stats_cauchy_lorentz: { double gamma = ui.leParameter1->text().toDouble(); double mu = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_cauchy(r, gamma) + mu; col->replaceValues(0, new_data); } break; } case nsl_sf_stats_rayleigh: { double s = ui.leParameter1->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_rayleigh(r, s); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_rayleigh_tail: { double mu = ui.leParameter1->text().toDouble(); double sigma = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_rayleigh_tail(r, mu, sigma); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_landau: for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_landau(r); col->replaceValues(0, new_data); } break; case nsl_sf_stats_levy_alpha_stable: { double c = ui.leParameter1->text().toDouble(); double alpha = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_levy(r, c, alpha); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_levy_skew_alpha_stable: { double c = ui.leParameter1->text().toDouble(); double alpha = ui.leParameter2->text().toDouble(); double beta = ui.leParameter3->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_levy_skew(r, c, alpha, beta); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_gamma: { double a = ui.leParameter1->text().toDouble(); double b = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_gamma(r, a, b); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_flat: { double a = ui.leParameter1->text().toDouble(); double b = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_flat(r, a, b); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_lognormal: { double s = ui.leParameter1->text().toDouble(); double mu = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_lognormal(r, mu, s); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_chi_squared: { double n = ui.leParameter1->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_chisq(r, n); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_fdist: { double nu1 = ui.leParameter1->text().toDouble(); double nu2 = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_fdist(r, nu1, nu2); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_tdist: { double nu = ui.leParameter1->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_tdist(r, nu); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_beta: { double a = ui.leParameter1->text().toDouble(); double b = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_beta(r, a, b); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_logistic: { double s = ui.leParameter1->text().toDouble(); double mu = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_logistic(r, s) + mu; col->replaceValues(0, new_data); } break; } case nsl_sf_stats_pareto: { double a = ui.leParameter1->text().toDouble(); double b = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_pareto(r, a, b); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_weibull: { double k = ui.leParameter1->text().toDouble(); double l = ui.leParameter2->text().toDouble(); double mu = ui.leParameter3->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_weibull(r, l, k) + mu; col->replaceValues(0, new_data); } break; } case nsl_sf_stats_gumbel1: { double s = ui.leParameter1->text().toDouble(); double b = ui.leParameter2->text().toDouble(); double mu = ui.leParameter3->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_gumbel1(r, 1./s, b) + mu; col->replaceValues(0, new_data); } break; } case nsl_sf_stats_gumbel2: { double a = ui.leParameter1->text().toDouble(); double b = ui.leParameter2->text().toDouble(); double mu = ui.leParameter3->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_gumbel2(r, a, b) + mu; col->replaceValues(0, new_data); } break; } case nsl_sf_stats_poisson: { double l = ui.leParameter1->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_poisson(r, l); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_bernoulli: { double p = ui.leParameter1->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_bernoulli(r, p); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_binomial: { double p = ui.leParameter1->text().toDouble(); double n = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_binomial(r, p, n); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_negative_binomial: { double p = ui.leParameter1->text().toDouble(); double n = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_negative_binomial(r, p, n); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_pascal: { double p = ui.leParameter1->text().toDouble(); double n = ui.leParameter2->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_pascal(r, p, n); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_geometric: { double p = ui.leParameter1->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_geometric(r, p); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_hypergeometric: { double n1 = ui.leParameter1->text().toDouble(); double n2 = ui.leParameter2->text().toDouble(); double t = ui.leParameter3->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_hypergeometric(r, n1, n2, t); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_logarithmic: { double p = ui.leParameter1->text().toDouble(); for (auto* col : m_columns) { for (int i = 0; i < rows; ++i) new_data[i] = gsl_ran_logarithmic(r, p); col->replaceValues(0, new_data); } break; } case nsl_sf_stats_maxwell_boltzmann: // additional non-GSL distros case nsl_sf_stats_sech: case nsl_sf_stats_levy: case nsl_sf_stats_frechet: break; } for (auto* col : m_columns) { col->setSuppressDataChangedSignal(false); col->setChanged(); } m_spreadsheet->endMacro(); RESET_CURSOR; gsl_rng_free(r); } diff --git a/src/kdefrontend/spreadsheet/RandomValuesDialog.h b/src/kdefrontend/spreadsheet/RandomValuesDialog.h index e0546cf10..0d2bda92d 100644 --- a/src/kdefrontend/spreadsheet/RandomValuesDialog.h +++ b/src/kdefrontend/spreadsheet/RandomValuesDialog.h @@ -1,58 +1,58 @@ /*************************************************************************** File : RandomValuesDialog.h Project : LabPlot Description : Dialog for generating uniformly and non-uniformly distributed random numbers -------------------------------------------------------------------- Copyright : (C) 2014 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef RANDOMVALUESDIALOG_H #define RANDOMVALUESDIALOG_H #include #include "ui_randomvalueswidget.h" class Column; class Spreadsheet; class QPushButton; class RandomValuesDialog : public QDialog { Q_OBJECT public: - explicit RandomValuesDialog(Spreadsheet* s, QWidget* parent = 0, Qt::WFlags fl = 0); + explicit RandomValuesDialog(Spreadsheet* s, QWidget* parent = 0); ~RandomValuesDialog(); void setColumns(QVector); private: Ui::RandomValuesWidget ui; QVector m_columns; Spreadsheet* m_spreadsheet; QPushButton* m_okButton; private slots: void generate(); void distributionChanged(int index); void checkValues(); }; #endif diff --git a/src/kdefrontend/spreadsheet/SortDialog.cpp b/src/kdefrontend/spreadsheet/SortDialog.cpp index 042c4d8a3..02bd2362a 100644 --- a/src/kdefrontend/spreadsheet/SortDialog.cpp +++ b/src/kdefrontend/spreadsheet/SortDialog.cpp @@ -1,128 +1,128 @@ /*************************************************************************** File : SortDialog.h Project : LabPlot Description : Sorting options dialog -------------------------------------------------------------------- Copyright : (C) 2011 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "SortDialog.h" #include #include #include #include #include #include #include #include #include /*! \class SortDialog \brief Dialog for sorting the columns in a spreadsheet. \ingroup kdefrontend */ -SortDialog::SortDialog( QWidget* parent, Qt::WFlags fl ) : QDialog( parent, fl ){ +SortDialog::SortDialog( QWidget* parent ) : QDialog( parent ){ setWindowIcon(QIcon::fromTheme("view-sort-ascending")); setWindowTitle(i18nc("@title:window", "Sort Columns")); setSizeGripEnabled(true); setAttribute(Qt::WA_DeleteOnClose); QGroupBox* widget = new QGroupBox(i18n("Options")); QGridLayout* layout = new QGridLayout(widget); layout->setSpacing(4); layout->setContentsMargins(4,4,4,4); layout->addWidget( new QLabel( i18n("Order")), 0, 0 ); m_cbOrdering = new QComboBox(); m_cbOrdering->addItem(QIcon::fromTheme("view-sort-ascending"), i18n("Ascending")); m_cbOrdering->addItem(QIcon::fromTheme("view-sort-descending"), i18n("Descending")); layout->addWidget(m_cbOrdering, 0, 1 ); m_lType = new QLabel(i18n("Sort columns")); layout->addWidget( m_lType, 1, 0 ); m_cbType = new QComboBox(); m_cbType->addItem(i18n("Separately")); m_cbType->addItem(i18n("Together")); layout->addWidget(m_cbType, 1, 1 ); m_cbType->setCurrentIndex(Together); m_lColumns = new QLabel(i18n("Leading column")); layout->addWidget( m_lColumns, 2, 0 ); m_cbColumns = new QComboBox(); layout->addWidget(m_cbColumns, 2, 1); layout->setRowStretch(3, 1); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); buttonBox->button(QDialogButtonBox::Ok)->setText(i18n("Sort")); connect(buttonBox, &QDialogButtonBox::accepted, this, &SortDialog::sortColumns); connect(buttonBox, &QDialogButtonBox::rejected, this, &SortDialog::reject); connect(buttonBox, &QDialogButtonBox::accepted, this, &SortDialog::accept); layout->addWidget(buttonBox); setLayout(layout); connect(m_cbType, SIGNAL(currentIndexChanged(int)), this, SLOT(changeType(int))); this->resize(400,0); } void SortDialog::sortColumns(){ Column* leading; if(m_cbType->currentIndex() == Together) leading = m_columns.at(m_cbColumns->currentIndex()); else leading = 0; emit sort(leading, m_columns, m_cbOrdering->currentIndex() == Ascending ); } void SortDialog::setColumns(QVector columns){ m_columns = columns; for(int i=0; iaddItem( m_columns.at(i)->name() ); m_cbColumns->setCurrentIndex(0); if (m_columns.size() == 1){ m_lType->hide(); m_cbType->hide(); m_lColumns->hide(); m_cbColumns->hide(); } } void SortDialog::changeType(int Type){ if(Type == Together) m_cbColumns->setEnabled(true); else m_cbColumns->setEnabled(false); } diff --git a/src/kdefrontend/spreadsheet/SortDialog.h b/src/kdefrontend/spreadsheet/SortDialog.h index 5cf6530cf..24136bef6 100644 --- a/src/kdefrontend/spreadsheet/SortDialog.h +++ b/src/kdefrontend/spreadsheet/SortDialog.h @@ -1,65 +1,65 @@ /*************************************************************************** File : SortDialog.h Project : LabPlot Description : Sorting options dialog -------------------------------------------------------------------- Copyright : (C) 2011 by Alexander Semke (alexander.semke@web.de) ***************************************************************************/ /*************************************************************************** * * * 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. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef SORTDIALOG_H #define SORTDIALOG_H #include "backend/core/column/Column.h" #include class QPushButton; class QComboBox; class QLabel; class SortDialog : public QDialog { Q_OBJECT public: - explicit SortDialog( QWidget* parent = 0, Qt::WFlags fl = 0 ); + explicit SortDialog( QWidget* parent = 0 ); void setColumns(QVector); enum { Separately=0, Together=1 }; enum { Ascending=0, Descending=1 }; private slots: void sortColumns(); void changeType(int index); signals: void sort(Column*, QVector, bool ascending); private: QVector m_columns; QComboBox* m_cbOrdering; QLabel* m_lType; QComboBox* m_cbType; QLabel* m_lColumns; QComboBox* m_cbColumns; }; #endif