diff options
Diffstat (limited to 'src/qalculateeditmatrixvectordialog.cpp')
-rw-r--r-- | src/qalculateeditmatrixvectordialog.cpp | 491 |
1 files changed, 491 insertions, 0 deletions
diff --git a/src/qalculateeditmatrixvectordialog.cpp b/src/qalculateeditmatrixvectordialog.cpp new file mode 100644 index 0000000..1dccb03 --- /dev/null +++ b/src/qalculateeditmatrixvectordialog.cpp @@ -0,0 +1,491 @@ +/*************************************************************************** + * 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 EvaluationOptions evalops; +extern tree_struct variable_cats; + +class QalculateEditMatrixVectorTableItem : public QTableItem { + + public: + + QalculateEditMatrixVectorTableItem(QTable *table); + QalculateEditMatrixVectorTableItem(QTable *table, const QString & text); + + int alignment() const; + +}; + +class QalculateEditMatrixTable : public QTable { + + public: + + QalculateEditMatrixTable(QWidget *parent = 0, const char *name = 0) : QTable(parent, name) {} + QalculateEditMatrixTable(int numRows, int numCols, QWidget *parent = 0, const char *name = 0) : QTable(numRows, numCols, parent, name) {} + + QWidget *beginEdit(int row, int col, bool replace) { + QWidget *w = QTable::beginEdit(row, col, replace); + ((QLineEdit*) w)->selectAll(); + return w; + } + +}; + +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); + 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); + elementsLabel = new QLabel(i18n("Elements:"), mainWidget()); + grid->addMultiCellWidget(elementsLabel, 7, 7, 0, 1); + elementsTable = new QalculateEditMatrixTable(0, 0, mainWidget()); + grid->addMultiCellWidget(elementsTable, 8, 8, 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("Elements (in horizontal order):")); + } +} +void QalculateEditMatrixVectorDialog::rowsChanged(int i) { + int r = elementsTable->numRows(); + elementsTable->setNumRows(i); + bool b = matrixButton->isChecked(); + for(int index_r = r; index_r < i; index_r++) { + for(int index_c = 0; index_c < elementsTable->numCols(); index_c++) { + if(b) elementsTable->setItem(index_r, index_c, new QalculateEditMatrixVectorTableItem(elementsTable, "0")); + else elementsTable->setItem(index_r, index_c, new QalculateEditMatrixVectorTableItem(elementsTable)); + } + } +} +void QalculateEditMatrixVectorDialog::columnsChanged(int i) { + int c = elementsTable->numCols(); + elementsTable->setNumCols(i); + bool b = matrixButton->isChecked(); + for(int index_r = 0; index_r < elementsTable->numRows(); index_r++) { + for(int index_c = c; index_c < i; index_c++) { + if(b) elementsTable->setItem(index_r, index_c, new QalculateEditMatrixVectorTableItem(elementsTable, "0")); + else elementsTable->setItem(index_r, index_c, new QalculateEditMatrixVectorTableItem(elementsTable)); + } + } +} + +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 + nameEdit->setFocus(); + 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) { + nameEdit->setFocus(); + 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.addChild(CALCULATOR->calculate(CALCULATOR->unlocalizeExpression(str2, evalops.parse_options))); + } + } + } + } + } 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(), evalops.parse_options)), 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); + elementsLabel->setText(i18n("Elements (in horizontal order):")); + } else { + matrixButton->setChecked(true); + elementsLabel->setText(i18n("Elements:")); + } + + 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->countChildren(); + c = (int) ::sqrt(r) + 4; + if(r % c > 0) { + r = r / c + 1; + } else { + r = r / c; + } + } else { + c = 4; + r = 4; + } + } + + rowsBox->setValue(r); + columnsBox->setValue(c); + elementsTable->setNumRows(r); + elementsTable->setNumCols(c); + + int timeout; + if(force_value) timeout = 3000 / (r * c); + else timeout = 3000; + 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->countChildren()) { + elementsTable->setText(index_r, index_c, old_vctr->getChild(index_r * c + index_c + 1)->print(po).c_str()); + } else { + elementsTable->setText(index_r, index_c, ""); + } + } else { + if(v) { + elementsTable->setText(index_r, index_c, v->get().getElement(index_r + 1, index_c + 1)->print(po).c_str()); + } else if(initial_value) { + elementsTable->setText(index_r, index_c, initial_value->getElement(index_r + 1, index_c + 1)->print(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); + } +} + +#if QT_VERSION >= 0x030200 +QalculateEditMatrixVectorTableItem::QalculateEditMatrixVectorTableItem(QTable *table) : QTableItem(table, QTableItem::OnTyping) {} +#else +QalculateEditMatrixVectorTableItem::QalculateEditMatrixVectorTableItem(QTable *table) : QTableItem(table, QTableItem::OnTyping, QString::null) {} +#endif +QalculateEditMatrixVectorTableItem::QalculateEditMatrixVectorTableItem(QTable *table, const QString & text) : QTableItem(table, QTableItem::OnTyping, text) {} + +int QalculateEditMatrixVectorTableItem::alignment() const {return Qt::AlignRight;} + +#include "qalculateeditmatrixvectordialog.moc" + |