Changeset View
Standalone View
src/backends/qalculate/qalculatesession.cpp
1 | /************************************************************************************ | 1 | /************************************************************************************ | ||
---|---|---|---|---|---|
2 | * Copyright (C) 2009 by Milian Wolff <mail@milianw.de> * | 2 | * Copyright (C) 2009 by Milian Wolff <mail@milianw.de> * | ||
3 | * Copyright (C) 2011 by Matteo Agostinelli <agostinelli@gmail.com> * | 3 | * Copyright (C) 2011 by Matteo Agostinelli <agostinelli@gmail.com> * | ||
4 | * Copyright (C) 2017 by Rishabh Gupta <rishabh9511@gmail.com> * | ||||
4 | * * | 5 | * * | ||
5 | * This program is free software; you can redistribute it and/or * | 6 | * This program is free software; you can redistribute it and/or * | ||
6 | * modify it under the terms of the GNU General Public License * | 7 | * modify it under the terms of the GNU General Public License * | ||
Context not available. | |||||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * | 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * | ||
18 | *************************************************************************************/ | 19 | *************************************************************************************/ | ||
19 | 20 | | |||
20 | #include "settings.h" | | |||
21 | | ||||
22 | #include "qalculatesession.h" | 21 | #include "qalculatesession.h" | ||
23 | #include "qalculateexpression.h" | | |||
24 | #include "qalculatecompletionobject.h" | | |||
25 | #include "qalculatehighlighter.h" | | |||
26 | #include "defaultvariablemodel.h" | | |||
27 | | ||||
28 | #include <QTextEdit> | | |||
29 | | ||||
30 | #include <libqalculate/Calculator.h> | | |||
31 | #include <libqalculate/ExpressionItem.h> | | |||
32 | #include <libqalculate/Unit.h> | | |||
33 | #include <libqalculate/Prefix.h> | | |||
34 | #include <libqalculate/Variable.h> | | |||
35 | #include <libqalculate/Function.h> | | |||
36 | 22 | | |||
37 | #include "qalculatesyntaxhelpobject.h" | 23 | #include <QDebug> | ||
24 | #include <QProcess> | ||||
25 | #include <QStandardPaths> | ||||
38 | 26 | | |||
39 | QalculateSession::QalculateSession( Cantor::Backend* backend) | 27 | QalculateSession::QalculateSession( Cantor::Backend* backend) | ||
40 | : Session(backend), | 28 | : Session(backend), m_process(0),m_currentExpression(0) | ||
41 | m_variableModel(new Cantor::DefaultVariableModel(this)) | | |||
42 | { | 29 | { | ||
43 | if ( !CALCULATOR ) { | | |||
44 | new Calculator(); | | |||
45 | CALCULATOR->loadGlobalDefinitions(); | | |||
46 | CALCULATOR->loadLocalDefinitions(); | | |||
47 | CALCULATOR->loadExchangeRates(); | | |||
48 | } | | |||
49 | // from qalc.cc in libqalculate | | |||
50 | std::string ansName = "ans"; | | |||
51 | // m_undefined is not a variable in this class, but is defined in | | |||
52 | // libqalculate/includes.h | | |||
53 | m_ansVariables.append(static_cast<KnownVariable*>(CALCULATOR->addVariable(new KnownVariable("Temporary", ansName, m_undefined, "Last Answer", false)))); | | |||
54 | m_ansVariables[0]->addName("answer"); | | |||
55 | m_ansVariables[0]->addName(ansName + "1"); | | |||
56 | m_ansVariables.append(static_cast<KnownVariable*>(CALCULATOR->addVariable(new KnownVariable("Temporary", ansName+"2", m_undefined, "Answer 2", false)))); | | |||
57 | m_ansVariables.append(static_cast<KnownVariable*>(CALCULATOR->addVariable(new KnownVariable("Temporary", ansName+"3", m_undefined, "Answer 3", false)))); | | |||
58 | m_ansVariables.append(static_cast<KnownVariable*>(CALCULATOR->addVariable(new KnownVariable("Temporary", ansName+"4", m_undefined, "Answer 4", false)))); | | |||
59 | m_ansVariables.append(static_cast<KnownVariable*>(CALCULATOR->addVariable(new KnownVariable("Temporary", ansName+"5", m_undefined, "Answer 5", false)))); | | |||
60 | } | 30 | } | ||
61 | 31 | | |||
62 | QalculateSession::~QalculateSession() | 32 | QalculateSession::~QalculateSession() | ||
63 | { | 33 | { | ||
64 | CALCULATOR->abort(); | | |||
65 | } | 34 | } | ||
66 | 35 | | |||
67 | void QalculateSession::login() | 36 | void QalculateSession::login() | ||
68 | { | 37 | { | ||
69 | if(!QalculateSettings::autorunScripts().isEmpty()){ | 38 | m_process = new QProcess(this); | ||
70 | QString autorunScripts = QalculateSettings::self()->autorunScripts().join(QLatin1String("\n")); | | |||
71 | 39 | | |||
72 | evaluateExpression(autorunScripts, QalculateExpression::DeleteOnFinish); | 40 | m_process->setProgram(QStandardPaths::findExecutable(QLatin1String("qalc"))); | ||
73 | } | 41 | m_process->setProcessChannelMode(QProcess::SeparateChannels); | ||
74 | 42 | | |||
75 | changeStatus(Cantor::Session::Done); | 43 | QObject::connect(m_process, SIGNAL(readyReadStandardOutput()), this, SLOT(readOutput())); | ||
76 | emit ready(); | 44 | QObject::connect(m_process, SIGNAL(readyReadStandardError()), this, SLOT(readError())); | ||
77 | } | 45 | QObject::connect(m_process, SIGNAL(started()), this, SLOT(processStarted())); | ||
46 | | ||||
47 | m_process->start(); | ||||
78 | 48 | | |||
79 | void QalculateSession::logout() | | |||
80 | { | | |||
81 | } | 49 | } | ||
82 | 50 | | |||
83 | void QalculateSession::interrupt() | 51 | void QalculateSession::processStarted() | ||
84 | { | 52 | { | ||
85 | changeStatus(Cantor::Session::Done); | 53 | qDebug() << m_process->program() << " pid: " << m_process->processId() << " started successfully"; | ||
54 | emit ready(); | ||||
86 | } | 55 | } | ||
87 | 56 | | |||
88 | Cantor::Expression* QalculateSession::evaluateExpression(const QString& cmd, Cantor::Expression::FinishingBehavior behave) | 57 | void QalculateSession::readOutput() | ||
89 | { | 58 | { | ||
90 | QalculateExpression* expr = new QalculateExpression(this); | | |||
91 | expr->setFinishingBehavior(behave); | | |||
92 | 59 | | |||
93 | changeStatus(Cantor::Session::Running); | 60 | while(m_process->bytesAvailable() > 0){ | ||
94 | expr->setCommand(cmd); | 61 | m_output.append(QString::fromLocal8Bit(m_process->readLine())); | ||
95 | expr->evaluate(); | 62 | } | ||
96 | changeStatus(Cantor::Session::Done); | 63 | | ||
64 | qDebug() << m_output; | ||||
65 | // qalc always sends ">" after returning result. With this we will know that QProcess has returned all the output and therefore we can start parsing it | ||||
66 | if(m_currentExpression and !m_output.isEmpty() and m_output.trimmed().endsWith(QLatin1String(">"))) | ||||
67 | { | ||||
68 | qDebug() << "output to be sent for parsing: " << m_output << endl; | ||||
69 | m_currentExpression->parseOutput(m_output); | ||||
70 | m_output.clear(); | ||||
71 | } | ||||
97 | 72 | | |||
98 | return expr; | | |||
99 | } | 73 | } | ||
100 | 74 | | |||
101 | Cantor::CompletionObject* QalculateSession::completionFor(const QString& command, int index) | 75 | void QalculateSession::readError() | ||
102 | { | 76 | { | ||
103 | return new QalculateCompletionObject(command, index, this); | 77 | qDebug() << m_process->readAllStandardError(); | ||
104 | } | 78 | } | ||
79 | void QalculateSession::interrupt() | ||||
80 | {} | ||||
105 | 81 | | |||
106 | Cantor::SyntaxHelpObject* QalculateSession::syntaxHelpFor(const QString& cmd) | 82 | Cantor::Expression* QalculateSession::evaluateExpression(const QString& command, Cantor::Expression::FinishingBehavior finishingBehavior) | ||
107 | { | 83 | { | ||
108 | return new QalculateSyntaxHelpObject(cmd, this); | 84 | /* | ||
85 | beginning to evaluate expression | ||||
86 | set the state of session to running | ||||
87 | */ | ||||
88 | changeStatus(Cantor::Session::Status::Running); | ||||
89 | | ||||
90 | QalculateExpression* expression = new QalculateExpression(this); | ||||
91 | expression->setCommand(command); | ||||
92 | expression->evaluate(); | ||||
93 | | ||||
94 | return expression; | ||||
109 | } | 95 | } | ||
110 | 96 | | |||
111 | QSyntaxHighlighter* QalculateSession::syntaxHighlighter(QObject* parent) | 97 | void QalculateSession::runExpression(QalculateExpression* expr) | ||
112 | { | 98 | { | ||
113 | return new QalculateHighlighter(parent); | 99 | qDebug() << "processing " << expr->command().toLocal8Bit(); | ||
100 | m_currentExpression = expr; | ||||
101 | connect(m_currentExpression, SIGNAL(statusChanged(Cantor::Expression::Status)), this, SLOT(currentExpressionStatusChanged(Cantor::Expression::Status))); | ||||
102 | QString finalCmd; | ||||
103 | finalCmd = expr->command(); | ||||
104 | finalCmd += QLatin1String("\n"); | ||||
105 | qDebug() << "Final Command" << finalCmd << endl; | ||||
106 | m_process->write(finalCmd.toLocal8Bit()); | ||||
114 | } | 107 | } | ||
115 | 108 | | |||
116 | void QalculateSession::setLastResult(MathStructure result) | 109 | void QalculateSession::currentExpressionStatusChanged(Cantor::Expression::Status status) | ||
117 | { | 110 | { | ||
118 | for (int i = m_ansVariables.size()-1; i >0 ; --i) { | 111 | qDebug() << "currentExpressionStatusChanged: " << status; | ||
119 | m_ansVariables[i]->set(m_ansVariables[i-1]->get()); | 112 | | ||
113 | switch (status){ | ||||
114 | case Cantor::Expression::Computing: | ||||
115 | break; | ||||
116 | | ||||
117 | case Cantor::Expression::Interrupted: | ||||
118 | break; | ||||
119 | | ||||
120 | case Cantor::Expression::Done: | ||||
121 | case Cantor::Expression::Error: | ||||
122 | changeStatus(Done); | ||||
123 | break; | ||||
120 | } | 124 | } | ||
121 | m_ansVariables[0]->set(result); | | |||
122 | } | 125 | } | ||
123 | 126 | void QalculateSession::logout() | |||
124 | QAbstractItemModel* QalculateSession::variableModel() | | |||
125 | { | 127 | { | ||
126 | return m_variableModel; | 128 | qDebug() << "quit process" << m_process->processId(); | ||
129 | m_process->write("quit\n"); | ||||
127 | } | 130 | } | ||
Context not available. | |||||
chinmoyr: comment out? | |||||
chinmoyr: this and also others following this. | |||||
chinmoyr: const QString | |||||
chinmoyr: comment out. | |||||
IF cantor uses Qt5 then why not switch to QRegularExpression? IIRC it provides some improvements over QRegExp. chinmoyr: IF cantor uses Qt5 then why not switch to QRegularExpression? IIRC it provides some… | |||||
Thanks for pointing out . rishabhg: Thanks for pointing out .
QRegexp is being used through cantor. It will be ported to… | |||||
chinmoyr: I think `return currentCmd.clear()` also does the same thing | |||||
rishabhg: Yes. I don't know why I did this | |||||
chinmoyr: Use `QStringLiteral("...").arg(...)` instead. | |||||
Correct. QStringLiteral is less expensive as pointed out here rishabhg: Correct. QStringLiteral is less expensive as pointed out [[ https://woboq. | |||||
chinmoyr: Use QStringLiteral | |||||
Do something like this currentCmd = QStringLiteral(...).arg(...); return currentCmd; chinmoyr: Do something like this
```currentCmd = QStringLiteral(...).arg(...);
return currentCmd;```
| |||||
chinmoyr: Use currentCmd + QStringLiteral combination. | |||||
chinmoyr: `return QString();`, though both are same. | |||||
No they both are not same. rishabhg: No they both are not same.
The docs provide good info on both [[ http://doc.qt.io/qt-5/qstring. | |||||
Unfortunately we are not able to use or or and expressions yet, so change it to old logic operators syntax. In addition, could you provide parentheses for this verification? It is really bad to read (and it is creating an error message during building). filipesaraiva: Unfortunately we are not able to use `or` or `and` expressions yet, so change it to old logic… | |||||
I have changed the logic here a bit and have tried to improve the overall readability. There were no build errors on my side. Please check if the new code works fine on your system rishabhg: I have changed the logic here a bit and have tried to improve the overall readability.
There… |
comment out?