/** Parse the expression in m_ExpressionText * and calculate result. * Return the result as a double. * If quiet ist true, no signals will be emitted and m_Expressiontext will not be modified. * If quiet is false, Log will be updated and m_Expressiontext will be set to the result of the calculation. * A logTextChanged and an expressionTextChanged signal will be emitted. */ double Calculator::parseExpression(bool quiet) { QStringList expressionParts = m_ExpressionParts; //work on a copy, keep the original int partCount = expressionParts.size(); double result = 0.0; try{ //Parse the expression while(partCount > 1) { parseSubexpression(expressionParts); partCount = expressionParts.size(); } if(expressionParts.size() == 0) throw ExExpressionError(tr("Expression could not be evaluated.")); if( ! quiet) { m_ExpressionText = m_ExpressionParts.join("") + ( "= " + expressionParts[0]); //Log the expression and its result m_LogText += m_ExpressionText + "\n"; emit logTextChanged(m_LogText); //replace the expression with its result m_ExpressionParts.clear(); m_ExpressionParts.append(expressionParts[0]); m_ExpressionText = expressionParts[0]; emit expressionTextChanged(m_ExpressionText); result = m_ExpressionText.toDouble(); } else //keep m_ExpressionParts and m_Expressiontext as they are { if(isVariable(expressionParts[0])) result = getVariableValue(expressionParts[0]); else result = expressionParts[0].toDouble(); } } catch(ExExpressionError & e) { qDebug("Calculator::parseExpression caught ExExpressionError: %s", e.what()); if(quiet) throw e; else emit errorMessage(tr("Error"), e.what()); } catch(std::exception &e) { qDebug("Calculator::parseExpression caught std::exception: %s", e.what()); if(quiet) throw e; else emit errorMessage(tr("Error"), e.what()); } catch(...) { qDebug("Calculator::parseExpression caught unknown exception."); if(quiet) throw std::exception(); else emit errorMessage(tr("Error"),"Calculator::parseExpression caught unknown exception."); } return result; }
void FilterExpressionsPreferencesFrame::on_expressionTreeWidget_itemActivated(QTreeWidgetItem *item, int column) { if (!item || cur_line_edit_) return; QWidget *editor = NULL; cur_column_ = column; switch (column) { case label_col_: { cur_line_edit_ = new QLineEdit(); cur_column_ = column; saved_col_string_ = item->text(label_col_); connect(cur_line_edit_, SIGNAL(editingFinished()), this, SLOT(labelEditingFinished())); editor = cur_line_edit_; break; } case expression_col_: { SyntaxLineEdit *syntax_edit = new SyntaxLineEdit(); saved_col_string_ = item->text(expression_col_); connect(syntax_edit, SIGNAL(textChanged(QString)), this, SLOT(expressionTextChanged(QString))); connect(syntax_edit, SIGNAL(editingFinished()), this, SLOT(expressionEditingFinished())); editor = cur_line_edit_ = syntax_edit; break; } default: return; } if (cur_line_edit_) { cur_line_edit_->setText(saved_col_string_); cur_line_edit_->selectAll(); connect(cur_line_edit_, SIGNAL(destroyed()), this, SLOT(lineEditDestroyed())); } if (editor) { QFrame *edit_frame = new QFrame(); QHBoxLayout *hb = new QHBoxLayout(); QSpacerItem *spacer = new QSpacerItem(5, 10); hb->addWidget(editor, 0); hb->addSpacerItem(spacer); hb->setStretch(1, 1); hb->setContentsMargins(0, 0, 0, 0); edit_frame->setLineWidth(0); edit_frame->setFrameStyle(QFrame::NoFrame); // The documentation suggests setting autoFillbackground. That looks silly // so we clear the item text instead. item->setText(cur_column_, ""); edit_frame->setLayout(hb); ui->expressionTreeWidget->setItemWidget(item, cur_column_, edit_frame); editor->setFocus(); } }
/** Deletes expresssion text. Deletes Log, when expression is empty. */ void Calculator::clearAll() { if(m_ExpressionText.isEmpty()) { m_LogText = ""; emit logTextChanged(m_LogText); } m_ExpressionParts.clear(); m_ExpressionText = ""; emit expressionTextChanged(m_ExpressionText); }
/** Deletes last character. */ void Calculator::clearLast() { if(m_ExpressionParts.size() == 0) return; m_ExpressionParts.removeLast(); if(m_ExpressionParts.size() > 0 && isFunction(m_ExpressionParts.last())) //remove ( and function name m_ExpressionParts.removeLast(); m_ExpressionText = m_ExpressionParts.join(""); emit expressionTextChanged(m_ExpressionText); }
Calculator::Calculator(QObject *parent) : QObject(parent) { m_NextAngleMode = m_TextRad; m_AngleMode = m_TextDeg; m_x = 0.0; //whatever it may be good for. Does not affect GUI, if GUI is not yet ready emit logTextChanged(m_LogText); emit expressionTextChanged(m_ExpressionText); emit angleModeChanged(m_AngleMode, m_NextAngleMode); connect(&plotter, SIGNAL(plotSetupChanged(QString)), this, SLOT(slot_Plotter_plotSetupChanged(QString))); connect(&plotter, SIGNAL(yValueRequest(double,double*)), this, SLOT(slot_Plotter_yValueRequest(double,double*))); }
/** Append text to Expression. Overwrites a trailing operator with the new one, if a sequence of * two operators is input. * Recognizes and executes C, AC and = commands. */ void Calculator::addToExpressionText(const QString & buttonText) { QString text = buttonText; try{ if(text == "C") clearLast(); else if(text == "AC") clearAll(); else if(text == "+/-") changeSign(); else if(text == m_TextRad) setAngleMode(text); else if(text == m_TextDeg) setAngleMode(text); else if(text == "=") { if(isPlotExpression()) createPlot(); else parseExpression(); } else if(text=="x") addVariable(text); else if(text.startsWith("Plot")) plotter.processPlotCommand(text); else{ //we have a digit, operator or function //no clear or evaluate command if(text == "x^y") //convert to operator text = "^"; if(isNumber(text)){ //No parenthesis, we have a digit or a decimal separator addDigit(text); emit guiStateSuggested(STATE_STANDARD); //return to std page, if on Fn Page for entering E } else if(isOperator(text)) //operator or digit { addOperator(text); } else if(isParenthesis(text)) //we have a parenthesis { addParenthesis(text); } else if(isFunction(text)) //we have a function { addFunctionCall(text); } else if(isVariable(text)) //we have a variable { addVariable(text); } else throw ExExpressionError(tr("Unknown command:") + text); } //end digit operator or function m_ExpressionText = m_ExpressionParts.join(""); if(isPlotExpression()) emit expressionTextChanged("y=" + m_ExpressionText); else emit expressionTextChanged(m_ExpressionText); } //end try catch(ExExpressionError e) { emit guiStateSuggested(STATE_STANDARD); emit errorMessage(tr("Input Error"),e.what()); } catch(std::exception e) { emit guiStateSuggested(STATE_STANDARD); emit errorMessage(tr("Unknown Input Error"),e.what()); } }