diff options
author | Slávek Banko <slavek.banko@axis.cz> | 2016-04-09 15:59:57 +0200 |
---|---|---|
committer | Slávek Banko <slavek.banko@axis.cz> | 2016-04-09 15:59:57 +0200 |
commit | ee0c9d4bc3e25a409b3127be2876079f69719978 (patch) | |
tree | 04d895b486c04df1fe2e5dedb7cd5705eff06a9b /src/qalculateplotdialog.cpp | |
download | qalculate-tde-ee0c9d4bc3e25a409b3127be2876079f69719978.tar.gz qalculate-tde-ee0c9d4bc3e25a409b3127be2876079f69719978.zip |
Initial import of qalculate-kde 0.9.7
Diffstat (limited to 'src/qalculateplotdialog.cpp')
-rw-r--r-- | src/qalculateplotdialog.cpp | 789 |
1 files changed, 789 insertions, 0 deletions
diff --git a/src/qalculateplotdialog.cpp b/src/qalculateplotdialog.cpp new file mode 100644 index 0000000..e1adbae --- /dev/null +++ b/src/qalculateplotdialog.cpp @@ -0,0 +1,789 @@ +/*************************************************************************** + * Copyright (C) 2005 by Niklas Knutsson * + * nq@altern.org * + * * + * 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., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "qalculateplotdialog.h" +#include "qalculateexpressionedit.h" + +#include <klineedit.h> +#include <kpushbutton.h> +#include <kcombobox.h> +#include <qlabel.h> +#include <klocale.h> +#include <qcheckbox.h> +#include <qradiobutton.h> +#include <qbuttongroup.h> +#include <qspinbox.h> +#include <kmessagebox.h> +#include <qlayout.h> +#include <ktextedit.h> +#include <klistview.h> +#include <kdeversion.h> +#if KDE_VERSION_MAJOR < 4 && KDE_VERSION_MINOR < 2 +#include <qtabwidget.h> +#else +#include <ktabwidget.h> +#endif +#include <kfiledialog.h> +#include <kapplication.h> +#include <kstdguiitem.h> + +extern PlotLegendPlacement default_plot_legend_placement; +extern bool default_plot_display_grid; +extern bool default_plot_full_border; +extern QString default_plot_min; +extern QString default_plot_max; +extern QString default_plot_step; +extern int default_plot_sampling_rate; +extern bool default_plot_use_sampling_rate; +extern bool default_plot_rows; +extern int default_plot_type; +extern PlotStyle default_plot_style; +extern PlotSmoothing default_plot_smoothing; +extern QString default_plot_variable; +extern bool default_plot_color; +extern bool enable_plot_expression_completion; + +extern EvaluationOptions evalops; + +QalculatePlotDialog::QalculatePlotDialog(QWidget *parent, const char *name) : KDialogBase(parent, name, false, i18n("Plot"), User1 | Close | Help, Close, false, KStdGuiItem::save()) { + + actionButton(Close)->setAutoDefault(false); + actionButton(Close)->setDefault(false); + actionButton(User1)->setAutoDefault(false); + actionButton(User1)->setDefault(false); + + actionButton(User1)->setEnabled(false); + +#if KDE_VERSION_MAJOR < 4 && KDE_VERSION_MINOR < 2 + tabs = new QTabWidget(this); +#else + tabs = new KTabWidget(this); +#endif + setMainWidget(tabs); + QWidget *page1 = new QWidget(this); + QWidget *page2 = new QWidget(this); + QWidget *page3 = new QWidget(this); + tabs->addTab(page1, i18n("Data")); + tabs->addTab(page2, i18n("Function Range")); + tabs->addTab(page3, i18n("Appearance")); + QGridLayout *grid = new QGridLayout(page1, 1, 1, spacingHint()); + grid->addWidget(new QLabel(i18n("Title:"), page1), 0, 0); + seriesTitleEdit = new KLineEdit(page1); + grid->addWidget(seriesTitleEdit, 0, 1); + grid->addWidget(new QLabel(i18n("Expression:"), page1), 1, 0); + expressionEdit = new QalculateExpressionEdit(false, page1); + if(!enable_plot_expression_completion) expressionEdit->disableCompletion(); + expressionEdit->updateCompletion(); + grid->addWidget(expressionEdit, 1, 1); + QHBoxLayout *hbox = new QHBoxLayout(0, 0, spacingHint()); + grid->addMultiCellLayout(hbox, 2, 2, 0, 1); + hbox->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); + typeGroup = new QButtonGroup(); + functionButton = new QRadioButton(i18n("Function"), page1); + typeGroup->insert(functionButton, 0); + hbox->addWidget(functionButton); + vectorMatrixButton = new QRadioButton(i18n("Vector/matrix"), page1); + typeGroup->insert(vectorMatrixButton, 1); + hbox->addWidget(vectorMatrixButton); + pairedMatrixButton = new QRadioButton(i18n("Paired matrix"), page1); + typeGroup->insert(pairedMatrixButton, 2); + hbox->addWidget(pairedMatrixButton); + rowsButton = new QCheckBox(i18n("Rows"), page1); + hbox->addWidget(rowsButton); + xVariableLabel = new QLabel(i18n("X variable:"), page1); + grid->addWidget(xVariableLabel, 3, 0); + xVariableEdit = new KLineEdit(page1); + grid->addWidget(xVariableEdit, 3, 1); + grid->addWidget(new QLabel(i18n("Style:"), page1), 4, 0); + styleCombo = new KComboBox(page1); + styleCombo->insertItem(i18n("Line")); + styleCombo->insertItem(i18n("Points")); + styleCombo->insertItem(i18n("Line with points")); + styleCombo->insertItem(i18n("Boxes/bars")); + styleCombo->insertItem(i18n("Histogram")); + styleCombo->insertItem(i18n("Steps")); + styleCombo->insertItem(i18n("Candlesticks")); + styleCombo->insertItem(i18n("Dots")); + grid->addWidget(styleCombo, 4, 1); + grid->addWidget(new QLabel(i18n("Smoothing:"), page1), 5, 0); + smoothingCombo = new KComboBox(page1); + smoothingCombo->insertItem(i18n("None")); + smoothingCombo->insertItem(i18n("Monotonic")); + smoothingCombo->insertItem(i18n("Natural cubic splines")); + smoothingCombo->insertItem(i18n("Bezier")); + smoothingCombo->insertItem(i18n("Bezier (monotonic)")); + grid->addWidget(smoothingCombo, 5, 1); + grid->addWidget(new QLabel(i18n("Y-axis:"), page1), 6, 0); + hbox = new QHBoxLayout(0, 0, spacingHint()); + grid->addLayout(hbox, 6, 1); + QButtonGroup *group = new QButtonGroup(); + primaryButton = new QRadioButton(i18n("Primary"), page1); + group->insert(primaryButton, 0); + hbox->addWidget(primaryButton); + secondaryButton = new QRadioButton(i18n("Secondary"), page1); + group->insert(secondaryButton, 1); + hbox->addWidget(secondaryButton); + hbox->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); + hbox = new QHBoxLayout(0, 0, spacingHint()); + grid->addMultiCellLayout(hbox, 7, 7, 0, 1); + hbox->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); + addButton = new QPushButton(i18n("Add"), page1); + hbox->addWidget(addButton); + modifyButton = new QPushButton(i18n("Modify"), page1); + hbox->addWidget(modifyButton); + removeButton = new QPushButton(i18n("Remove"), page1); + hbox->addWidget(removeButton); + seriesView = new KListView(page1); + seriesView->addColumn(i18n("Title")); + seriesView->addColumn(i18n("Expression")); + seriesView->setRootIsDecorated(false); + seriesView->setItemsRenameable(true); + seriesView->setRenameable(0, true); + seriesView->setRenameable(1, true); + seriesView->setItemsMovable(true); + seriesView->setSorting(-1); + grid->addMultiCellWidget(seriesView, 8, 8, 0, 1); + + grid = new QGridLayout(page2, 1, 1, spacingHint()); + grid->addWidget(new QLabel(i18n("Min:"), page2), 0, 0); + minEdit = new KLineEdit(page2); + grid->addWidget(minEdit, 0, 1); + grid->addWidget(new QLabel(i18n("Max:"), page2), 1, 0); + maxEdit = new KLineEdit(page2); + grid->addWidget(maxEdit, 1, 1); + rangeGroup = new QButtonGroup(); + samplingRateButton = new QRadioButton(i18n("Sampling rate:"), page2); + rangeGroup->insert(samplingRateButton, 0); + grid->addWidget(samplingRateButton, 2, 0); + samplingRateBox = new QSpinBox(1, 10000, 10, page2); + grid->addWidget(samplingRateBox, 2, 1); + stepSizeButton = new QRadioButton(i18n("Step size:"), page2); + rangeGroup->insert(stepSizeButton, 1); + grid->addWidget(stepSizeButton, 3, 0); + stepSizeEdit = new KLineEdit(page2); + grid->addWidget(stepSizeEdit, 3, 1); + hbox = new QHBoxLayout(0, 0, spacingHint()); + grid->addMultiCellLayout(hbox, 4, 4, 0, 1); + hbox->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); + applyRangeButton = new KPushButton(KStdGuiItem::apply(), page2); + hbox->addWidget(applyRangeButton); + grid->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 5, 0); + + grid = new QGridLayout(page3, 1, 1, spacingHint()); + grid->addWidget(new QLabel(i18n("Title:"), page3), 0, 0); + titleEdit = new KLineEdit(page3); + grid->addWidget(titleEdit, 0, 1); + hbox = new QHBoxLayout(0, 0, spacingHint()); + grid->addMultiCellLayout(hbox, 1, 1, 0, 1); + gridButton = new QCheckBox(i18n("Display grid"), page3); + hbox->addWidget(gridButton); + fullBorderButton = new QCheckBox(i18n("Display full border"), page3); + hbox->addWidget(fullBorderButton); + hbox->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); + logXButton = new QCheckBox(i18n("Logarithmic x scale:"), page3); + grid->addWidget(logXButton, 2, 0); + logXBox = new QSpinBox(2, 100, 1, page3); + grid->addWidget(logXBox, 2, 1); + logYButton = new QCheckBox(i18n("Logarithmic y scale:"), page3); + grid->addWidget(logYButton, 3, 0); + logYBox = new QSpinBox(2, 100, 1, page3); + grid->addWidget(logYBox, 3, 1); + grid->addWidget(new QLabel(i18n("X-axis label:"), page3), 4, 0); + xLabelEdit = new KLineEdit(page3); + grid->addWidget(xLabelEdit, 4, 1); + grid->addWidget(new QLabel(i18n("Y-axis label:"), page3), 5, 0); + yLabelEdit = new KLineEdit(page3); + grid->addWidget(yLabelEdit, 5, 1); + grid->addWidget(new QLabel(i18n("Color display:"), page3), 6, 0); + hbox = new QHBoxLayout(0, 0, spacingHint()); + grid->addLayout(hbox, 6, 1); + group = new QButtonGroup(); + colorButton = new QRadioButton(i18n("Color"), page3); + group->insert(colorButton, 0); + hbox->addWidget(colorButton); + monochromeButton = new QRadioButton(i18n("Monochrome"), page3); + group->insert(monochromeButton, 1); + hbox->addWidget(monochromeButton); + hbox->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); + grid->addWidget(new QLabel(i18n("Legend placement:"), page3), 7, 0); + legendPlacementCombo = new KComboBox(page3); + legendPlacementCombo->insertItem(i18n("Hide")); + legendPlacementCombo->insertItem(i18n("Top-left")); + legendPlacementCombo->insertItem(i18n("Top-right")); + legendPlacementCombo->insertItem(i18n("Bottom-left")); + legendPlacementCombo->insertItem(i18n("Bottom-right")); + legendPlacementCombo->insertItem(i18n("Below")); + legendPlacementCombo->insertItem(i18n("Outside")); + grid->addWidget(legendPlacementCombo, 7, 1); + hbox = new QHBoxLayout(0, 0, spacingHint()); + grid->addMultiCellLayout(hbox, 8, 8, 0, 1); + hbox->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum)); + applyAppearanceButton = new KPushButton(KStdGuiItem::apply(), page3); + hbox->addWidget(applyAppearanceButton); + grid->addItem(new QSpacerItem(0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding), 9, 0); + + primaryButton->setChecked(true); + modifyButton->setEnabled(false); + removeButton->setEnabled(false); + gridButton->setChecked(default_plot_display_grid); + fullBorderButton->setChecked(default_plot_full_border); + rowsButton->setChecked(default_plot_rows); + colorButton->setChecked(default_plot_color); + monochromeButton->setChecked(!default_plot_color); + minEdit->setText(default_plot_min); + maxEdit->setText(default_plot_max); + stepSizeEdit->setText(default_plot_step); + xVariableEdit->setText(default_plot_variable); + samplingRateButton->setChecked(default_plot_use_sampling_rate); + samplingRateBox->setEnabled(default_plot_use_sampling_rate); + stepSizeButton->setChecked(!default_plot_use_sampling_rate); + stepSizeEdit->setEnabled(!default_plot_use_sampling_rate); + logXBox->setEnabled(false); + logYBox->setEnabled(false); + switch(default_plot_type) { + case 1: {vectorMatrixButton->setChecked(true); break;} + case 2: {pairedMatrixButton->setChecked(true); break;} + default: {functionButton->setChecked(true);} + } + rowsButton->setEnabled(default_plot_type == 1 || default_plot_type == 2); + xVariableEdit->setEnabled(default_plot_type != 1 && default_plot_type != 2); + xVariableLabel->setEnabled(default_plot_type != 1 && default_plot_type != 2); + switch(default_plot_legend_placement) { + case PLOT_LEGEND_NONE: {legendPlacementCombo->setCurrentItem(0); break;} + case PLOT_LEGEND_TOP_LEFT: {legendPlacementCombo->setCurrentItem(1); break;} + case PLOT_LEGEND_TOP_RIGHT: {legendPlacementCombo->setCurrentItem(2); break;} + case PLOT_LEGEND_BOTTOM_LEFT: {legendPlacementCombo->setCurrentItem(3); break;} + case PLOT_LEGEND_BOTTOM_RIGHT: {legendPlacementCombo->setCurrentItem(4); break;} + case PLOT_LEGEND_BELOW: {legendPlacementCombo->setCurrentItem(5); break;} + case PLOT_LEGEND_OUTSIDE: {legendPlacementCombo->setCurrentItem(6); break;} + } + switch(default_plot_smoothing) { + case PLOT_SMOOTHING_NONE: {smoothingCombo->setCurrentItem(0); break;} + case PLOT_SMOOTHING_UNIQUE: {smoothingCombo->setCurrentItem(1); break;} + case PLOT_SMOOTHING_CSPLINES: {smoothingCombo->setCurrentItem(2); break;} + case PLOT_SMOOTHING_BEZIER: {smoothingCombo->setCurrentItem(3); break;} + case PLOT_SMOOTHING_SBEZIER: {smoothingCombo->setCurrentItem(4); break;} + } + switch(default_plot_style) { + case PLOT_STYLE_LINES: {styleCombo->setCurrentItem(0); break;} + case PLOT_STYLE_POINTS: {styleCombo->setCurrentItem(1); break;} + case PLOT_STYLE_POINTS_LINES: {styleCombo->setCurrentItem(2); break;} + case PLOT_STYLE_BOXES: {styleCombo->setCurrentItem(3); break;} + case PLOT_STYLE_HISTOGRAM: {styleCombo->setCurrentItem(4); break;} + case PLOT_STYLE_STEPS: {styleCombo->setCurrentItem(5); break;} + case PLOT_STYLE_CANDLESTICKS: {styleCombo->setCurrentItem(6); break;} + case PLOT_STYLE_DOTS: {styleCombo->setCurrentItem(7); break;} + } + samplingRateBox->setValue(default_plot_sampling_rate); + + seriesTitleEdit->setFocus(); + + connect(seriesTitleEdit, SIGNAL(returnPressed()), expressionEdit, SLOT(setFocus())); + connect(expressionEdit, SIGNAL(returnPressed()), this, SLOT(expressionActivated())); + connect(typeGroup, SIGNAL(clicked(int)), this, SLOT(typeChanged(int))); + connect(rangeGroup, SIGNAL(clicked(int)), this, SLOT(rangeTypeChanged(int))); + connect(logXButton, SIGNAL(toggled(bool)), logXBox, SLOT(setEnabled(bool))); + connect(logYButton, SIGNAL(toggled(bool)), logYBox, SLOT(setEnabled(bool))); + connect(applyRangeButton, SIGNAL(clicked()), this, SLOT(applyRange())); + connect(applyAppearanceButton, SIGNAL(clicked()), this, SLOT(applyAppearance())); + connect(seriesView, SIGNAL(selectionChanged()), this, SLOT(seriesSelected())); + connect(seriesView, SIGNAL(itemRenamed(QListViewItem*, const QString&, int)), this, SLOT(seriesItemRenamed(QListViewItem*, const QString&, int))); + connect(addButton, SIGNAL(clicked()), this, SLOT(addSeries())); + connect(modifyButton, SIGNAL(clicked()), this, SLOT(modifySeries())); + connect(removeButton, SIGNAL(clicked()), this, SLOT(removeSeries())); + connect(this, SIGNAL(user1Clicked()), this, SLOT(savePlot())); + connect(this, SIGNAL(finished()), this, SLOT(onClosing())); + +} + +QalculatePlotDialog::~QalculatePlotDialog() {} + +void QalculatePlotDialog::slotHelp() { + KApplication::kApplication()->invokeHelp("qalculate-plotting"); +} + +void QalculatePlotDialog::saveMode() { + + enable_plot_expression_completion = expressionEdit->completionEnabled(); + default_plot_display_grid = gridButton->isChecked(); + default_plot_full_border = fullBorderButton->isChecked(); + default_plot_rows = rowsButton->isChecked(); + default_plot_color = colorButton->isChecked(); + default_plot_min = minEdit->text().ascii(); + default_plot_max = maxEdit->text().ascii(); + default_plot_step = stepSizeEdit->text().ascii(); + default_plot_variable = xVariableEdit->text().ascii(); + default_plot_use_sampling_rate = samplingRateButton->isChecked(); + if(vectorMatrixButton->isChecked()) { + default_plot_type = 1; + } else if(pairedMatrixButton->isChecked()) { + default_plot_type = 2; + } else { + default_plot_type = 0; + } + switch(legendPlacementCombo->currentItem()) { + case 0: {default_plot_legend_placement = PLOT_LEGEND_NONE; break;} + case 1: {default_plot_legend_placement = PLOT_LEGEND_TOP_LEFT; break;} + case 2: {default_plot_legend_placement = PLOT_LEGEND_TOP_RIGHT; break;} + case 3: {default_plot_legend_placement = PLOT_LEGEND_BOTTOM_LEFT; break;} + case 4: {default_plot_legend_placement = PLOT_LEGEND_BOTTOM_RIGHT; break;} + case 5: {default_plot_legend_placement = PLOT_LEGEND_BELOW; break;} + case 6: {default_plot_legend_placement = PLOT_LEGEND_OUTSIDE; break;} + } + switch(smoothingCombo->currentItem()) { + case 0: {default_plot_smoothing = PLOT_SMOOTHING_NONE; break;} + case 1: {default_plot_smoothing = PLOT_SMOOTHING_UNIQUE; break;} + case 2: {default_plot_smoothing = PLOT_SMOOTHING_CSPLINES; break;} + case 3: {default_plot_smoothing = PLOT_SMOOTHING_BEZIER; break;} + case 4: {default_plot_smoothing = PLOT_SMOOTHING_SBEZIER; break;} + } + switch(styleCombo->currentItem()) { + case 0: {default_plot_style = PLOT_STYLE_LINES; break;} + case 1: {default_plot_style = PLOT_STYLE_POINTS; break;} + case 2: {default_plot_style = PLOT_STYLE_POINTS_LINES; break;} + case 3: {default_plot_style = PLOT_STYLE_BOXES; break;} + case 4: {default_plot_style = PLOT_STYLE_HISTOGRAM; break;} + case 5: {default_plot_style = PLOT_STYLE_STEPS; break;} + case 6: {default_plot_style = PLOT_STYLE_CANDLESTICKS; break;} + case 7: {default_plot_style = PLOT_STYLE_DOTS; break;} + } + default_plot_sampling_rate = samplingRateBox->value(); +} +void QalculatePlotDialog::onClosing() { + + tabs->setCurrentPage(0); + modifyButton->setEnabled(false); + removeButton->setEnabled(false); + actionButton(User1)->setEnabled(false); + + QListViewItemIterator it(seriesView); + while(it.current()) { + MathStructure *y_vector = itemYVector[it.current()], *x_vector = itemXVector[it.current()]; + if(y_vector) delete y_vector; + if(x_vector) delete x_vector; + ++it; + } + itemStyle.clear(); + itemType.clear(); + itemAxis.clear(); + itemSmoothing.clear(); + itemRows.clear(); + itemXVector.clear(); + itemYVector.clear(); + itemXVariable.clear(); + seriesView->clear(); + expressionEdit->clear(); + seriesTitleEdit->clear(); + + CALCULATOR->closeGnuplot(); + +} +void QalculatePlotDialog::seriesItemRenamed(QListViewItem *i, const QString &str, int col) { + if(!i) return; + if(col == 0) { + updatePlot(); + } else if(col == 1) { + if(str.isEmpty()) { + KMessageBox::error(this, i18n("Empty expression.")); + } + MathStructure *x_vector = itemXVector[i], *y_vector = itemYVector[i]; + if(x_vector) delete x_vector; + if(y_vector) delete y_vector; + x_vector = NULL; + y_vector = NULL; + generatePlotSeries(&x_vector, &y_vector, itemType[i], str.ascii(), itemXVariable[i].ascii()); + itemXVector[i] = x_vector; + itemYVector[i] = y_vector; + updatePlot(); + } + seriesSelected(); +} +void QalculatePlotDialog::seriesSelected() { + QListViewItem *i = seriesView->selectedItem(); + if(i) { + modifyButton->setEnabled(true); + removeButton->setEnabled(true); + expressionEdit->setText(i->text(1)); + seriesTitleEdit->setText(i->text(0)); + xVariableEdit->setText(itemXVariable[i]); + styleCombo->setCurrentItem(itemStyle[i]); + smoothingCombo->setCurrentItem(itemSmoothing[i]); + typeGroup->setButton(itemType[i]); + secondaryButton->setChecked(itemAxis[i] == 2); + primaryButton->setChecked(itemAxis[i] != 2); + rowsButton->setChecked(itemRows[i]); + } else { + modifyButton->setEnabled(false); + removeButton->setEnabled(false); + } +} +void QalculatePlotDialog::rangeTypeChanged(int i) { + stepSizeEdit->setEnabled(i == 1); + samplingRateBox->setEnabled(i == 0); +} + +void QalculatePlotDialog::typeChanged(int i) { + rowsButton->setEnabled(i == 1 || i == 2); + xVariableEdit->setEnabled(i != 1 && i != 2); + xVariableLabel->setEnabled(i != 1 && i != 2); +} +void QalculatePlotDialog::expressionActivated() { + QListViewItem *i = seriesView->selectedItem(); + if(i) { + modifySeries(); + } else { + addSeries(); + } +} +void QalculatePlotDialog::addSeries() { + QString expression = expressionEdit->text(); + if(expression.stripWhiteSpace().isEmpty()) { + expressionEdit->setFocus(); + KMessageBox::error(this, i18n("Empty expression.")); + return; + } + int type = 0, axis = 1; + bool rows = false; + QString title = seriesTitleEdit->text(); + if(vectorMatrixButton->isChecked()) { + type = 1; + } else if(pairedMatrixButton->isChecked()) { + type = 2; + } + QString str_x = xVariableEdit->text().stripWhiteSpace(); + if(str_x.isEmpty() && type == 0) { + xVariableEdit->setFocus(); + KMessageBox::error(this, i18n("Empty x variable.")); + return; + } + expressionEdit->addToHistory(expression); + if(secondaryButton->isChecked()) { + axis = 2; + } + if((type == 1 || type == 2) && title.isEmpty()) { + Variable *v = CALCULATOR->getActiveVariable(expression.ascii()); + if(v) { + title = v->title(false).c_str(); + } + } + MathStructure *x_vector, *y_vector; + generatePlotSeries(&x_vector, &y_vector, type, expression.ascii(), str_x.ascii()); + rows = rowsButton->isChecked(); + QListViewItem *i = new KListViewItem(seriesView, seriesView->lastChild(), title, expression); + itemStyle[i] = styleCombo->currentItem(); + itemSmoothing[i] = smoothingCombo->currentItem(); + itemType[i] = type; + itemAxis[i] = axis; + itemRows[i] = rows; + itemXVector[i] = x_vector; + itemYVector[i] = y_vector; + itemXVariable[i] = str_x; + seriesView->setSelected(i, true); + updatePlot(); +} +void QalculatePlotDialog::modifySeries() { + QListViewItem *i = seriesView->selectedItem(); + if(i) { + QString expression = expressionEdit->text(); + if(expression.stripWhiteSpace().isEmpty()) { + expressionEdit->setFocus(); + KMessageBox::error(this, i18n("Empty expression.")); + return; + } + int type = 0, axis = 1; + QString title = seriesTitleEdit->text(); + if(vectorMatrixButton->isChecked()) { + type = 1; + } else if(pairedMatrixButton->isChecked()) { + type = 2; + } + QString str_x = xVariableEdit->text().stripWhiteSpace(); + if(str_x.isEmpty() && type == 0) { + xVariableEdit->setFocus(); + KMessageBox::error(this, i18n("Empty x variable.")); + return; + } + expressionEdit->addToHistory(expression); + if(secondaryButton->isChecked()) { + axis = 2; + } + if((type == 1 || type == 2) && title.isEmpty()) { + Variable *v = CALCULATOR->getActiveVariable(expression.ascii()); + if(v) { + title = v->title(false).c_str(); + } + } + MathStructure *x_vector = itemXVector[i], *y_vector = itemYVector[i]; + if(x_vector) delete x_vector; + if(y_vector) delete y_vector; + x_vector = NULL; + y_vector = NULL; + generatePlotSeries(&x_vector, &y_vector, type, expression.ascii(), str_x.ascii()); + i->setText(0, title); + i->setText(1, expression); + itemStyle[i] = styleCombo->currentItem(); + itemSmoothing[i] = smoothingCombo->currentItem(); + itemType[i] = type; + itemAxis[i] = axis; + itemRows[i] = rowsButton->isChecked(); + itemXVector[i] = x_vector; + itemYVector[i] = y_vector; + itemXVariable[i] = str_x; + updatePlot(); + } +} +void QalculatePlotDialog::removeSeries() { + QListViewItem *i = seriesView->selectedItem(); + if(i) { + MathStructure *x_vector = itemXVector[i], *y_vector = itemYVector[i]; + if(x_vector) delete x_vector; + if(y_vector) delete y_vector; + itemStyle.erase(i); + itemSmoothing.erase(i); + itemType.erase(i); + itemAxis.erase(i); + itemRows.erase(i); + itemXVector.erase(i); + itemYVector.erase(i); + itemXVariable.erase(i); + delete i; + expressionEdit->clear(); + seriesTitleEdit->clear(); + updatePlot(); + } +} +void QalculatePlotDialog::applyRange() { + QListViewItemIterator it(seriesView); + while(it.current()) { + MathStructure *x_vector = itemXVector[it.current()], *y_vector = itemYVector[it.current()]; + if(y_vector) delete y_vector; + if(x_vector) delete x_vector; + x_vector = NULL; + y_vector = NULL; + generatePlotSeries(&x_vector, &y_vector, itemType[it.current()], it.current()->text(1).ascii(), itemXVariable[it.current()].ascii()); + itemXVector[it.current()] = x_vector; + itemYVector[it.current()] = y_vector; + ++it; + } + updatePlot(); +} +void QalculatePlotDialog::applyAppearance() { + updatePlot(); +} + +bool QalculatePlotDialog::generatePlot(PlotParameters &pp, vector<MathStructure> &y_vectors, vector<MathStructure> &x_vectors, vector<PlotDataParameters*> &pdps) { + QListViewItemIterator it(seriesView); + if(!it.current()) { + return false; + } + while(it.current()) { + int count = 1; + QString title = it.current()->text(0), expression = it.current()->text(1); + int style = itemStyle[it.current()]; + int smoothing = itemSmoothing[it.current()]; + int type = itemType[it.current()]; + int axis = itemAxis[it.current()]; + bool rows = itemRows[it.current()]; + MathStructure *x_vector = itemXVector[it.current()]; + MathStructure *y_vector = itemYVector[it.current()]; + if(type == 1) { + if(y_vector->isMatrix()) { + count = 0; + if(rows) { + for(size_t i = 1; i <= y_vector->rows(); i++) { + y_vectors.push_back(m_undefined); + y_vector->rowToVector(i, y_vectors[y_vectors.size() - 1]); + x_vectors.push_back(m_undefined); + count++; + } + } else { + for(size_t i = 1; i <= y_vector->columns(); i++) { + y_vectors.push_back(m_undefined); + y_vector->columnToVector(i, y_vectors[y_vectors.size() - 1]); + x_vectors.push_back(m_undefined); + count++; + } + } + } else if(y_vector->isVector()) { + y_vectors.push_back(*y_vector); + x_vectors.push_back(m_undefined); + } else { + y_vectors.push_back(*y_vector); + y_vectors[y_vectors.size() - 1].transform(STRUCT_VECTOR); + x_vectors.push_back(m_undefined); + } + } else if(type == 2) { + if(y_vector->isMatrix()) { + count = 0; + if(rows) { + for(size_t i = 1; i <= y_vector->rows(); i += 2) { + y_vectors.push_back(m_undefined); + y_vector->rowToVector(i, y_vectors[y_vectors.size() - 1]); + x_vectors.push_back(m_undefined); + y_vector->rowToVector(i + 1, x_vectors[x_vectors.size() - 1]); + count++; + } + } else { + for(size_t i = 1; i <= y_vector->columns(); i += 2) { + y_vectors.push_back(m_undefined); + y_vector->columnToVector(i, y_vectors[y_vectors.size() - 1]); + x_vectors.push_back(m_undefined); + y_vector->columnToVector(i + 1, x_vectors[x_vectors.size() - 1]); + count++; + } + } + } else if(y_vector->isVector()) { + y_vectors.push_back(*y_vector); + x_vectors.push_back(m_undefined); + } else { + y_vectors.push_back(*y_vector); + y_vectors[y_vectors.size() - 1].transform(STRUCT_VECTOR); + x_vectors.push_back(m_undefined); + } + } else { + y_vectors.push_back(*y_vector); + x_vectors.push_back(*x_vector); + } + for(int i = 0; i < count; i++) { + PlotDataParameters *pdp = new PlotDataParameters(); + pdp->title = title.ascii(); + if(count > 1) { + pdp->title += " :"; + pdp->title += i2s(i + 1); + } + remove_blank_ends(pdp->title); + if(pdp->title.empty()) { + pdp->title = expression.ascii(); + } + switch(smoothing) { + case 0: {pdp->smoothing = PLOT_SMOOTHING_NONE; break;} + case 1: {pdp->smoothing = PLOT_SMOOTHING_UNIQUE; break;} + case 2: {pdp->smoothing = PLOT_SMOOTHING_CSPLINES; break;} + case 3: {pdp->smoothing = PLOT_SMOOTHING_BEZIER; break;} + case 4: {pdp->smoothing = PLOT_SMOOTHING_SBEZIER; break;} + } + switch(style) { + case 0: {pdp->style = PLOT_STYLE_LINES; break;} + case 1: {pdp->style = PLOT_STYLE_POINTS; break;} + case 2: {pdp->style = PLOT_STYLE_POINTS_LINES; break;} + case 3: {pdp->style = PLOT_STYLE_DOTS; break;} + case 4: {pdp->style = PLOT_STYLE_BOXES; break;} + case 5: {pdp->style = PLOT_STYLE_HISTOGRAM; break;} + case 6:{pdp->style = PLOT_STYLE_STEPS; break;} + case 7: {pdp->style = PLOT_STYLE_CANDLESTICKS; break;} + } + pdp->yaxis2 = (axis == 2); + pdps.push_back(pdp); + } + ++it; + } + switch(legendPlacementCombo->currentItem()) { + case 0: {pp.legend_placement = PLOT_LEGEND_NONE; break;} + case 1: {pp.legend_placement = PLOT_LEGEND_TOP_LEFT; break;} + case 2: {pp.legend_placement = PLOT_LEGEND_TOP_RIGHT; break;} + case 3: {pp.legend_placement = PLOT_LEGEND_BOTTOM_LEFT; break;} + case 4: {pp.legend_placement = PLOT_LEGEND_BOTTOM_RIGHT; break;} + case 5: {pp.legend_placement = PLOT_LEGEND_BELOW; break;} + case 6: {pp.legend_placement = PLOT_LEGEND_OUTSIDE; break;} + } + pp.title = titleEdit->text().ascii(); + pp.x_label = xLabelEdit->text().ascii(); + pp.y_label = yLabelEdit->text().ascii(); + pp.grid = gridButton->isChecked(); + pp.x_log = logXButton->isChecked(); + pp.y_log = logYButton->isChecked(); + pp.x_log_base = logXBox->value(); + pp.y_log_base = logYBox->value(); + pp.color = colorButton->isChecked(); + pp.show_all_borders = fullBorderButton->isChecked(); + return true; +} +void QalculatePlotDialog::savePlot() { + QString title = titleEdit->text().ascii(); + if(title.isEmpty()) { + title = "plot.png"; + } else { + title += ".png"; + } + QString filename; + while(true) { + filename = KFileDialog::getSaveFileName(title, "image/png image/svg application/postscript image/x-eps /text/x-tex image/x-xfig", this, i18n("Save Image")); + if(filename.isEmpty()) { + return; + } else { + if(QFile::exists(filename)) { + if(KMessageBox::warningContinueCancel(this, i18n("A file named \"%1\" already exists. Are you sure you want to overwrite it?" ).arg(filename), i18n("Overwrite File?"), i18n( "&Overwrite" )) != KMessageBox::Cancel) { + break; + } + } else { + break; + } + } + } + vector<MathStructure> y_vectors; + vector<MathStructure> x_vectors; + vector<PlotDataParameters*> pdps; + PlotParameters pp; + if(generatePlot(pp, y_vectors, x_vectors, pdps)) { + pp.filename = filename.ascii(); + pp.filetype = PLOT_FILETYPE_AUTO; + CALCULATOR->plotVectors(&pp, y_vectors, x_vectors, pdps); + for(size_t i = 0; i < pdps.size(); i++) { + if(pdps[i]) delete pdps[i]; + } + } +} +void QalculatePlotDialog::updatePlot() { + vector<MathStructure> y_vectors; + vector<MathStructure> x_vectors; + vector<PlotDataParameters*> pdps; + PlotParameters pp; + if(!generatePlot(pp, y_vectors, x_vectors, pdps)) { + CALCULATOR->closeGnuplot(); + actionButton(User1)->setEnabled(false); + return; + } + CALCULATOR->plotVectors(&pp, y_vectors, x_vectors, pdps); + actionButton(User1)->setEnabled(true); + for(size_t i = 0; i < pdps.size(); i++) { + if(pdps[i]) delete pdps[i]; + } +} +void QalculatePlotDialog::generatePlotSeries(MathStructure **x_vector, MathStructure **y_vector, int type, string str, string str_x) { + EvaluationOptions eo; + eo.approximation = APPROXIMATION_APPROXIMATE; + eo.parse_options = evalops.parse_options; + eo.parse_options.read_precision = DONT_READ_PRECISION; + if(type == 1 || type == 2) { + *y_vector = new MathStructure(CALCULATOR->calculate(CALCULATOR->unlocalizeExpression(str, evalops.parse_options), eo)); + *x_vector = NULL; + } else { + MathStructure min(CALCULATOR->calculate(CALCULATOR->unlocalizeExpression(minEdit->text().ascii(), evalops.parse_options), eo)); + MathStructure max(CALCULATOR->calculate(CALCULATOR->unlocalizeExpression(maxEdit->text().ascii(), evalops.parse_options), eo)); + *x_vector = new MathStructure(); + (*x_vector)->clearVector(); + if(stepSizeButton->isChecked()) { + *y_vector = new MathStructure(CALCULATOR->expressionToPlotVector(str, min, max, CALCULATOR->calculate(CALCULATOR->unlocalizeExpression(stepSizeEdit->text().ascii(), evalops.parse_options), eo), *x_vector, str_x, evalops.parse_options)); + } else { + *y_vector = new MathStructure(CALCULATOR->expressionToPlotVector(str, min, max, samplingRateBox->value(), *x_vector, str_x, evalops.parse_options)); + } + } +} + +#include "qalculateplotdialog.moc" |