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

qalculateeditmatrixvectordialog.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 "qalculateeditmatrixvectordialog.h"
#include "qalculate_kde_utils.h"
#include "qalculateeditnamesdialog.h"

#include <qgrid.h>
#include <klineedit.h>
#include <qpushbutton.h>
#include <kcombobox.h>
#include <qlabel.h>
#include <klocale.h>
#include <qvbox.h>
#include <qhbox.h>
#include <qcheckbox.h>
#include <kmessagebox.h>
#include <qspinbox.h>
#include <qlayout.h>
#include <qbuttongroup.h>
#include <qradiobutton.h>
#include <qtable.h>
#include <kapplication.h>

extern PrintOptions printops;
extern tree_struct variable_cats;

QalculateEditMatrixVectorDialog::QalculateEditMatrixVectorDialog(QWidget *parent, const char *name) : KDialogBase(parent, name, true, i18n("Edit Variable"), Ok | Cancel | Help, Ok, true) {

      names_edit_dialog = NULL;
      edited_variable = NULL;

      setMainWidget(new QWidget(this));
      QGridLayout *grid = new QGridLayout(mainWidget(), 1, 1, 0, spacingHint());
      grid->addWidget(new QLabel(i18n("Name:"), mainWidget()), 0, 0);
      nameEdit = new KLineEdit(mainWidget());
      grid->addWidget(nameEdit, 0, 1);
      QHBoxLayout *hbox = new QHBoxLayout(0, 0, spacingHint());
      grid->addMultiCellLayout(hbox, 1, 1, 0, 1);
      namesLabel = new QLabel(mainWidget());
      namesLabel->setAlignment(Qt::AlignRight);
      namesLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
      hbox->addWidget(namesLabel);
      namesButton = new QPushButton(i18n("Names Details"), mainWidget());
      hbox->addWidget(namesButton);
      grid->addWidget(new QLabel(i18n("Category:"), mainWidget()), 2, 0);
      categoryCombo = new KComboBox(mainWidget());
      categoryCombo->setEditable(true);
      grid->addWidget(categoryCombo, 2, 1);
      grid->addWidget(new QLabel(i18n("Descriptive name:"), mainWidget()), 3, 0);
      titleEdit = new KLineEdit(mainWidget());
      grid->addWidget(titleEdit, 3, 1);
      grid->addWidget(new QLabel(i18n("Rows:"), mainWidget()), 4, 0);
      rowsBox = new QSpinBox(1, 1000, 1, mainWidget());
      grid->addWidget(rowsBox, 4, 1);
      grid->addWidget(new QLabel(i18n("Columns:"), mainWidget()), 5, 0);
      columnsBox = new QSpinBox(1, 1000, 1, mainWidget());
      grid->addWidget(columnsBox, 5, 1);
      hbox = new QHBoxLayout(0, 0, spacingHint());
      grid->addMultiCellLayout(hbox, 6, 6, 0, 1);
      elementsLabel = new QLabel(i18n("Elements:"), mainWidget());
      hbox->addWidget(elementsLabel);
      hbox->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum));
      QButtonGroup *group = new QButtonGroup();
      matrixButton = new QRadioButton(i18n("Matrix"), mainWidget());
      group->insert(matrixButton, 0);
      hbox->addWidget(matrixButton);
      vectorButton = new QRadioButton(i18n("Vector"), mainWidget());
      group->insert(vectorButton, 1);
      hbox->addWidget(vectorButton);
      elementsTable = new QTable(mainWidget());
      grid->addMultiCellWidget(elementsTable, 7, 7, 0, 1);

      connect(namesButton, SIGNAL(clicked()), this, SLOT(editNames()));
      connect(nameEdit, SIGNAL(textChanged(const QString&)), this, SLOT(nameChanged(const QString&)));
      connect(rowsBox, SIGNAL(valueChanged(int)), this, SLOT(rowsChanged(int)));
      connect(columnsBox, SIGNAL(valueChanged(int)), this, SLOT(columnsChanged(int)));
      connect(group, SIGNAL(clicked(int)), this, SLOT(typeChanged(int)));

}

QalculateEditMatrixVectorDialog::~QalculateEditMatrixVectorDialog() {}

void QalculateEditMatrixVectorDialog::slotHelp() {
      KApplication::kApplication()->invokeHelp("qalculate-vectors-matrices");
}

void QalculateEditMatrixVectorDialog::typeChanged(int i) {
      if(i == 0) {
            elementsLabel->setText(i18n("Elements:"));
            bool b = true;
            for(int index_r = elementsTable->numRows() - 1; index_r >= 0 && b; index_r--) {
                  for(int index_c = elementsTable->numCols() - 1; index_c >= 0; index_c--) {
                        if(elementsTable->text(index_r, index_c).isEmpty()) {
                              elementsTable->setText(index_r, index_c, "0");
                        } else {
                              b = false;
                              break;
                        }
                  }
            }
      } else {
            elementsLabel->setText(i18n("Components (in horizontal order):"));
      }
}
void QalculateEditMatrixVectorDialog::rowsChanged(int i) {
      int r = elementsTable->numRows();
      elementsTable->setNumRows(i);
      if(matrixButton->isChecked()) {
            for(int index_r = r; index_r < i; index_r++) {
                  for(int index_c = 0; index_c < elementsTable->numCols(); index_c++) {
                        elementsTable->setText(index_r, index_c, "0");
                  }
            }
      }
}
void QalculateEditMatrixVectorDialog::columnsChanged(int i) {
      int c = elementsTable->numCols();
      elementsTable->setNumCols(i);
      if(matrixButton->isChecked()) {
            for(int index_r = 0; index_r < elementsTable->numRows(); index_r++) {
                  for(int index_c = c; index_c < i; index_c++) {
                        elementsTable->setText(index_r, index_c, "0");
                  }
            }
      }
}

KnownVariable *QalculateEditMatrixVectorDialog::newVector(QString category) {
      return editVariable(category, NULL, NULL, false, true);
}
KnownVariable *QalculateEditMatrixVectorDialog::newMatrix(QString category) {
      return editVariable(category, NULL, NULL, false, false);
}

void QalculateEditMatrixVectorDialog::slotOk() {
      string str = nameEdit->text().ascii();
      remove_blank_ends(str);
      if(str.empty() && (!names_edit_dialog || names_edit_dialog->isEmpty())) {
            //no name -- open dialog again
            KMessageBox::error(this, i18n("Empty name field"));
            return;
      }
      //variable with the same name exists -- overwrite or open dialog again
      if((!edited_variable || !edited_variable->hasName(str)) && (!names_edit_dialog || names_edit_dialog->isEmpty()) && CALCULATOR->variableNameTaken(str, edited_variable) && KMessageBox::questionYesNo(this, i18n("An unit or variable with the same name already exists.\nDo you want to overwrite it?")) == KMessageBox::No) {
            return;
      }
      KnownVariable *v = edited_variable;
      if(!v) {
            //no need to create a new variable when a variable with the same name exists
            Variable *var = CALCULATOR->getActiveVariable(str);
            if(var && var->isLocal() && var->isKnown()) v = (KnownVariable*) var;
      }
      MathStructure mstruct_new;
      if(!init_value) {
            int r = rowsBox->value();
            int c = columnsBox->value();
            if(vectorButton->isChecked()) {
                  mstruct_new.clearVector();
                  string str2;
                  for(int index_r = 0; index_r < r; index_r++) {
                        for(int index_c = 0; index_c < c; index_c++) {
                              if(!elementsTable->text(index_r, index_c).isEmpty()) {
                                    str2 = elementsTable->text(index_r, index_c).ascii();
                                    remove_blank_ends(str2);
                                    if(!str2.empty()) {
                                          mstruct_new.addComponent(CALCULATOR->calculate(CALCULATOR->unlocalizeExpression(str2)));
                                    }
                              }
                        }
                  }
            } else {
                  mstruct_new.clearMatrix();
                  mstruct_new.resizeMatrix(r, c, m_undefined);
                  for(int index_r = 0; index_r < r; index_r++) {
                        for(int index_c = 0; index_c < c; index_c++) {
                              if(elementsTable->text(index_r, index_c).isEmpty()) mstruct_new.setElement(m_zero, index_r + 1, index_c + 1);
                              else mstruct_new.setElement(CALCULATOR->calculate(CALCULATOR->unlocalizeExpression(elementsTable->text(index_r, index_c).ascii())), index_r + 1, index_c + 1);
                        }
                  }
            }                             
      }
      bool add_var = false;
      if(v) {
            //update existing variable
            v->setLocal(true);
            if(!v->isBuiltin()) {
                  if(init_value) {
                        v->set(*init_value);
                  } else {
                        v->set(mstruct_new);
                  }
            }
      } else {
            //new variable
            if(force_init_value && init_value) {
                  //forced value
                  v = new KnownVariable("", "", *init_value, "", true);
            } else {
                  v = new KnownVariable("", "", mstruct_new, "", true);
            }
            add_var = true;
      }
      v->setCategory(categoryCombo->lineEdit()->text().ascii());
      v->setTitle(titleEdit->text().ascii());
      if(!v->isBuiltin()) {
            if(names_edit_dialog) {
                  names_edit_dialog->saveNames(v, str.c_str());
            } else {
                  if(v->countNames() == 0) {
                        ExpressionName ename(str);
                        ename.reference = true;
                        v->setName(ename, 1);
                  } else {
                        v->setName(str, 1);
                  }
            }
      }
      if(add_var) {
            CALCULATOR->addVariable(v);
      }
      edited_variable = v;
      accept();
}

KnownVariable *QalculateEditMatrixVectorDialog::editVariable(QString category, KnownVariable *v, MathStructure *initial_value, bool force_value, bool create_vector) {

      nameEdit->setFocus();

      if((v && !v->get().isVector()) || (initial_value && !initial_value->isVector())) {
            return NULL;
      }

      if(names_edit_dialog) {
            delete names_edit_dialog;
            names_edit_dialog = NULL;
      }
      edited_variable = v;

      if(initial_value) {
            create_vector = !initial_value->isMatrix();
      } else if(v) {
            create_vector = !v->get().isMatrix();
      }
      if(create_vector) {
            vectorButton->setChecked(true);
      } else {
            matrixButton->setChecked(true);
      }

      if(create_vector) {
            if(v) {
                  if(v->isLocal())
                        setCaption(i18n("Edit Vector"));
                  else
                        setCaption(i18n("Edit Vector (global)"));
            } else {
                  setCaption(i18n("New Vector"));
            }
      } else {
            if(v) {
                  if(v->isLocal())
                        setCaption(i18n("Edit Matrix"));
                  else
                        setCaption(i18n("Edit Matrix (global)"));
            } else {
                  setCaption(i18n("New Matrix"));
            }
      }

      actionButton(Ok)->setEnabled(true);

      namesLabel->setText("");

      //QStringList cats;
      QString catstr;
      categoryCombo->clear();
      tree_struct *item, *item2;
      variable_cats.it = variable_cats.items.begin();
      if(variable_cats.it != variable_cats.items.end()) {
            item = &*variable_cats.it;
            ++variable_cats.it;
            item->it = item->items.begin();
      } else {
            item = NULL;
      }

      catstr = "";
      while(item) {
            if(!catstr.isEmpty()) catstr += "/";
            catstr += item->item.c_str();
            categoryCombo->insertItem(catstr);
            while(item && item->it == item->items.end()) {
                  int str_i = catstr.findRev("/");
                  if(str_i < 0) {
                        catstr = "";
                  } else {
                        catstr.truncate(str_i);
                  }
                  item = item->parent;
            }
            if(item) {
                  item2 = &*item->it;
                  ++item->it;
                  item = item2;
                  item->it = item->items.begin();     
            }
      }

      int r = 4, c = 4;
      const MathStructure *old_vctr = NULL;
      if(v) {
            if(create_vector) {
                  old_vctr = &v->get();
            } else {
                  c = v->get().columns();
                  r = v->get().rows();
            }
            set_name_label_and_entry(v, nameEdit, namesLabel);
            nameEdit->setReadOnly(v->isBuiltin());
            rowsBox->setEnabled(!v->isBuiltin());
            columnsBox->setEnabled(!v->isBuiltin());
            matrixButton->setEnabled(!v->isBuiltin());
            vectorButton->setEnabled(!v->isBuiltin());
            elementsTable->setReadOnly(v->isBuiltin());
            categoryCombo->lineEdit()->setText(v->category().c_str());
            titleEdit->setText(v->title(false).c_str());
      } else {
            nameEdit->setReadOnly(false);
            rowsBox->setEnabled(true);
            columnsBox->setEnabled(true);
            matrixButton->setEnabled(true);
            vectorButton->setEnabled(true);
            elementsTable->setReadOnly(false);

            //fill in default values
            nameEdit->setText(CALCULATOR->getName().c_str());
            namesLabel->setText("");
            categoryCombo->lineEdit()->setText(category);
            titleEdit->setText("");
            if(force_value) {
                  if(create_vector) {
                        old_vctr = initial_value;
                  } else {
                        c = initial_value->columns();
                        r = initial_value->rows();
                  }
                  rowsBox->setEnabled(false);
                  columnsBox->setEnabled(false);
                  matrixButton->setEnabled(false);
                  vectorButton->setEnabled(false);
                  elementsTable->setReadOnly(true);
            }
      }

      if(create_vector) {
            if(old_vctr) {
                  r = old_vctr->components();
                  c = (int) ::sqrt(r) + 4;
                  if(r % c > 0) {
                        r = r / c + 1;
                  } else {
                        r = r / c;
                  }
            } else {
                  c = 8;
                  r = 3;
            }
      }

      rowsBox->setValue(r);
      columnsBox->setValue(c);
      elementsTable->setNumRows(r);
      elementsTable->setNumCols(c);

      int timeout;
      if(force_value) timeout = 3000000 / (r * c);
      else timeout = 3000000;
      PrintOptions po;
      po.number_fraction_format = FRACTION_DECIMAL_EXACT;
      for(int index_r = 0; index_r < r; index_r++) {
            for(int index_c = 0; index_c < c; index_c++) {
                  if(create_vector) {
                        if(old_vctr && index_r * c + index_c < (int) old_vctr->components()) {
                              elementsTable->setText(index_r, index_c, CALCULATOR->printMathStructureTimeOut(*old_vctr->getComponent(index_r * c + index_c + 1), timeout, po).c_str());
                        } else {
                              elementsTable->setText(index_r, index_c, "");
                        }
                  } else {
                        if(v) {
                              elementsTable->setText(index_r, index_c, CALCULATOR->printMathStructureTimeOut(*v->get().getElement(index_r + 1, index_c + 1), timeout, po).c_str());
                        } else if(initial_value) {
                              elementsTable->setText(index_r, index_c, CALCULATOR->printMathStructureTimeOut(*initial_value->getElement(index_r + 1, index_c + 1), timeout, po).c_str());
                        } else {
                              elementsTable->setText(index_r, index_c, "0");
                        }
                  }
            }
      }

      init_value = initial_value;
      force_init_value = force_value;

      if(exec() == QDialog::Accepted) {
            v = edited_variable;
            edited_variable = NULL;
            return v;
      }

      edited_variable = NULL;
      return NULL;
}

void QalculateEditMatrixVectorDialog::editNames() {
      if(!names_edit_dialog) {
            names_edit_dialog = new QalculateEditNamesDialog(TYPE_VARIABLE, this);
            names_edit_dialog->setNames(edited_variable, nameEdit->text(), false);
      } else {
            names_edit_dialog->setNames(edited_variable, nameEdit->text(), true);
      }
      names_edit_dialog->exec();
      names_edit_dialog->setNamesLE(nameEdit, namesLabel);
}

void QalculateEditMatrixVectorDialog::nameChanged(const QString &name) {
      if(name.isNull()) return;
      if(!CALCULATOR->variableNameIsValid(name.ascii())) {
            nameEdit->blockSignals(true);
            nameEdit->setText(CALCULATOR->convertToValidVariableName(name.ascii()).c_str());
            nameEdit->blockSignals(false);
      }
}

#include "qalculateeditmatrixvectordialog.moc"


Generated by  Doxygen 1.6.0   Back to index