Logo Search packages:      
Sourcecode: qalculate-kde version File versions  Download package

qalculateplotdialog.cpp

/***************************************************************************
 *   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()) {
            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) {
            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()) {
                  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) {
                  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(plot_parameters &pp, vector<MathStructure> &y_vectors, vector<MathStructure> &x_vectors, vector<plot_data_parameters*> &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++) {
                  plot_data_parameters *pdp = new plot_data_parameters();
                  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<plot_data_parameters*> pdps;
      plot_parameters 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<plot_data_parameters*> pdps;
      plot_parameters 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;
      if(type == 1 || type == 2) {
            *y_vector = new MathStructure(CALCULATOR->calculate(CALCULATOR->unlocalizeExpression(str), eo));
            *x_vector = NULL;
      } else {
            MathStructure min(CALCULATOR->calculate(CALCULATOR->unlocalizeExpression(minEdit->text().ascii()), eo));
            MathStructure max(CALCULATOR->calculate(CALCULATOR->unlocalizeExpression(maxEdit->text().ascii()), 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()), 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"

Generated by  Doxygen 1.6.0   Back to index