summaryrefslogtreecommitdiffstats
path: root/src/qalculateplotdialog.cpp
diff options
context:
space:
mode:
authorSlávek Banko <slavek.banko@axis.cz>2016-04-09 15:59:57 +0200
committerSlávek Banko <slavek.banko@axis.cz>2016-04-09 15:59:57 +0200
commitee0c9d4bc3e25a409b3127be2876079f69719978 (patch)
tree04d895b486c04df1fe2e5dedb7cd5705eff06a9b /src/qalculateplotdialog.cpp
downloadqalculate-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.cpp789
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"