/*************************************************************************** * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #if KDE_VERSION_MAJOR < 4 && KDE_VERSION_MINOR < 2 #include #else #include #endif #include #include #include extern PlotLegendPlacement default_plot_legend_placement; extern bool default_plot_display_grid; extern bool default_plot_full_border; extern TQString default_plot_min; extern TQString default_plot_max; extern TQString 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 TQString default_plot_variable; extern bool default_plot_color; extern bool enable_plot_expression_completion; extern EvaluationOptions evalops; QalculatePlotDialog::QalculatePlotDialog(TQWidget *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 TQTabWidget(this); #else tabs = new KTabWidget(this); #endif setMainWidget(tabs); TQWidget *page1 = new TQWidget(this); TQWidget *page2 = new TQWidget(this); TQWidget *page3 = new TQWidget(this); tabs->addTab(page1, i18n("Data")); tabs->addTab(page2, i18n("Function Range")); tabs->addTab(page3, i18n("Appearance")); TQGridLayout *grid = new TQGridLayout(page1, 1, 1, spacingHint()); grid->addWidget(new TQLabel(i18n("Title:"), page1), 0, 0); seriesTitleEdit = new KLineEdit(page1); grid->addWidget(seriesTitleEdit, 0, 1); grid->addWidget(new TQLabel(i18n("Expression:"), page1), 1, 0); expressionEdit = new QalculateExpressionEdit(false, page1); if(!enable_plot_expression_completion) expressionEdit->disableCompletion(); expressionEdit->updateCompletion(); grid->addWidget(expressionEdit, 1, 1); TQHBoxLayout *hbox = new TQHBoxLayout(0, 0, spacingHint()); grid->addMultiCellLayout(hbox, 2, 2, 0, 1); hbox->addItem(new TQSpacerItem(0, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum)); typeGroup = new TQButtonGroup(); functionButton = new TQRadioButton(i18n("Function"), page1); typeGroup->insert(functionButton, 0); hbox->addWidget(functionButton); vectorMatrixButton = new TQRadioButton(i18n("Vector/matrix"), page1); typeGroup->insert(vectorMatrixButton, 1); hbox->addWidget(vectorMatrixButton); pairedMatrixButton = new TQRadioButton(i18n("Paired matrix"), page1); typeGroup->insert(pairedMatrixButton, 2); hbox->addWidget(pairedMatrixButton); rowsButton = new TQCheckBox(i18n("Rows"), page1); hbox->addWidget(rowsButton); xVariableLabel = new TQLabel(i18n("X variable:"), page1); grid->addWidget(xVariableLabel, 3, 0); xVariableEdit = new KLineEdit(page1); grid->addWidget(xVariableEdit, 3, 1); grid->addWidget(new TQLabel(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 TQLabel(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 TQLabel(i18n("Y-axis:"), page1), 6, 0); hbox = new TQHBoxLayout(0, 0, spacingHint()); grid->addLayout(hbox, 6, 1); TQButtonGroup *group = new TQButtonGroup(); primaryButton = new TQRadioButton(i18n("Primary"), page1); group->insert(primaryButton, 0); hbox->addWidget(primaryButton); secondaryButton = new TQRadioButton(i18n("Secondary"), page1); group->insert(secondaryButton, 1); hbox->addWidget(secondaryButton); hbox->addItem(new TQSpacerItem(0, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum)); hbox = new TQHBoxLayout(0, 0, spacingHint()); grid->addMultiCellLayout(hbox, 7, 7, 0, 1); hbox->addItem(new TQSpacerItem(0, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum)); addButton = new TQPushButton(i18n("Add"), page1); hbox->addWidget(addButton); modifyButton = new TQPushButton(i18n("Modify"), page1); hbox->addWidget(modifyButton); removeButton = new TQPushButton(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 TQGridLayout(page2, 1, 1, spacingHint()); grid->addWidget(new TQLabel(i18n("Min:"), page2), 0, 0); minEdit = new KLineEdit(page2); grid->addWidget(minEdit, 0, 1); grid->addWidget(new TQLabel(i18n("Max:"), page2), 1, 0); maxEdit = new KLineEdit(page2); grid->addWidget(maxEdit, 1, 1); rangeGroup = new TQButtonGroup(); samplingRateButton = new TQRadioButton(i18n("Sampling rate:"), page2); rangeGroup->insert(samplingRateButton, 0); grid->addWidget(samplingRateButton, 2, 0); samplingRateBox = new TQSpinBox(1, 10000, 10, page2); grid->addWidget(samplingRateBox, 2, 1); stepSizeButton = new TQRadioButton(i18n("Step size:"), page2); rangeGroup->insert(stepSizeButton, 1); grid->addWidget(stepSizeButton, 3, 0); stepSizeEdit = new KLineEdit(page2); grid->addWidget(stepSizeEdit, 3, 1); hbox = new TQHBoxLayout(0, 0, spacingHint()); grid->addMultiCellLayout(hbox, 4, 4, 0, 1); hbox->addItem(new TQSpacerItem(0, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum)); applyRangeButton = new KPushButton(KStdGuiItem::apply(), page2); hbox->addWidget(applyRangeButton); grid->addItem(new TQSpacerItem(0, 0, TQSizePolicy::Minimum, TQSizePolicy::Expanding), 5, 0); grid = new TQGridLayout(page3, 1, 1, spacingHint()); grid->addWidget(new TQLabel(i18n("Title:"), page3), 0, 0); titleEdit = new KLineEdit(page3); grid->addWidget(titleEdit, 0, 1); hbox = new TQHBoxLayout(0, 0, spacingHint()); grid->addMultiCellLayout(hbox, 1, 1, 0, 1); gridButton = new TQCheckBox(i18n("Display grid"), page3); hbox->addWidget(gridButton); fullBorderButton = new TQCheckBox(i18n("Display full border"), page3); hbox->addWidget(fullBorderButton); hbox->addItem(new TQSpacerItem(0, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum)); logXButton = new TQCheckBox(i18n("Logarithmic x scale:"), page3); grid->addWidget(logXButton, 2, 0); logXBox = new TQSpinBox(2, 100, 1, page3); grid->addWidget(logXBox, 2, 1); logYButton = new TQCheckBox(i18n("Logarithmic y scale:"), page3); grid->addWidget(logYButton, 3, 0); logYBox = new TQSpinBox(2, 100, 1, page3); grid->addWidget(logYBox, 3, 1); grid->addWidget(new TQLabel(i18n("X-axis label:"), page3), 4, 0); xLabelEdit = new KLineEdit(page3); grid->addWidget(xLabelEdit, 4, 1); grid->addWidget(new TQLabel(i18n("Y-axis label:"), page3), 5, 0); yLabelEdit = new KLineEdit(page3); grid->addWidget(yLabelEdit, 5, 1); grid->addWidget(new TQLabel(i18n("Color display:"), page3), 6, 0); hbox = new TQHBoxLayout(0, 0, spacingHint()); grid->addLayout(hbox, 6, 1); group = new TQButtonGroup(); colorButton = new TQRadioButton(i18n("Color"), page3); group->insert(colorButton, 0); hbox->addWidget(colorButton); monochromeButton = new TQRadioButton(i18n("Monochrome"), page3); group->insert(monochromeButton, 1); hbox->addWidget(monochromeButton); hbox->addItem(new TQSpacerItem(0, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum)); grid->addWidget(new TQLabel(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 TQHBoxLayout(0, 0, spacingHint()); grid->addMultiCellLayout(hbox, 8, 8, 0, 1); hbox->addItem(new TQSpacerItem(0, 0, TQSizePolicy::Expanding, TQSizePolicy::Minimum)); applyAppearanceButton = new KPushButton(KStdGuiItem::apply(), page3); hbox->addWidget(applyAppearanceButton); grid->addItem(new TQSpacerItem(0, 0, TQSizePolicy::Minimum, TQSizePolicy::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(TQListViewItem*, const TQString&, int)), this, SLOT(seriesItemRenamed(TQListViewItem*, const TQString&, 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); TQListViewItemIterator 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(TQListViewItem *i, const TQString &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() { TQListViewItem *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() { TQListViewItem *i = seriesView->selectedItem(); if(i) { modifySeries(); } else { addSeries(); } } void QalculatePlotDialog::addSeries() { TQString expression = expressionEdit->text(); if(expression.stripWhiteSpace().isEmpty()) { expressionEdit->setFocus(); KMessageBox::error(this, i18n("Empty expression.")); return; } int type = 0, axis = 1; bool rows = false; TQString title = seriesTitleEdit->text(); if(vectorMatrixButton->isChecked()) { type = 1; } else if(pairedMatrixButton->isChecked()) { type = 2; } TQString 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(); TQListViewItem *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() { TQListViewItem *i = seriesView->selectedItem(); if(i) { TQString expression = expressionEdit->text(); if(expression.stripWhiteSpace().isEmpty()) { expressionEdit->setFocus(); KMessageBox::error(this, i18n("Empty expression.")); return; } int type = 0, axis = 1; TQString title = seriesTitleEdit->text(); if(vectorMatrixButton->isChecked()) { type = 1; } else if(pairedMatrixButton->isChecked()) { type = 2; } TQString 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() { TQListViewItem *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() { TQListViewItemIterator 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 &y_vectors, vector &x_vectors, vector &pdps) { TQListViewItemIterator it(seriesView); if(!it.current()) { return false; } while(it.current()) { int count = 1; TQString 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() { TQString title = titleEdit->text().ascii(); if(title.isEmpty()) { title = "plot.png"; } else { title += ".png"; } TQString 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(TQFile::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 y_vectors; vector x_vectors; vector 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 y_vectors; vector x_vectors; vector 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"