Changeset View
Changeset View
Standalone View
Standalone View
src/backends/R/rsession.cpp
Show All 17 Lines | 1 | /* | |||
---|---|---|---|---|---|
18 | Copyright (C) 2009 Alexander Rieder <alexanderrieder@gmail.com> | 18 | Copyright (C) 2009 Alexander Rieder <alexanderrieder@gmail.com> | ||
19 | Copyright (C) 2018 Alexander Semke <alexander.semke@web.de> | 19 | Copyright (C) 2018 Alexander Semke <alexander.semke@web.de> | ||
20 | */ | 20 | */ | ||
21 | 21 | | |||
22 | #include "rsession.h" | 22 | #include "rsession.h" | ||
23 | #include "rexpression.h" | 23 | #include "rexpression.h" | ||
24 | #include "rcompletionobject.h" | 24 | #include "rcompletionobject.h" | ||
25 | #include "rhighlighter.h" | 25 | #include "rhighlighter.h" | ||
26 | #include "rvariablemodel.h" | ||||
26 | #include <defaultvariablemodel.h> | 27 | #include <defaultvariablemodel.h> | ||
27 | 28 | | |||
28 | #include <QTimer> | 29 | #include <QTimer> | ||
29 | #include <QDebug> | 30 | #include <QDebug> | ||
30 | #include <KProcess> | 31 | #include <KProcess> | ||
31 | 32 | | |||
32 | #ifndef Q_OS_WIN | 33 | #ifndef Q_OS_WIN | ||
33 | #include <signal.h> | 34 | #include <signal.h> | ||
34 | #endif | 35 | #endif | ||
35 | 36 | | |||
36 | RSession::RSession(Cantor::Backend* backend) : Session(backend), m_process(nullptr), m_rServer(nullptr), m_variableModel(new Cantor::DefaultVariableModel(this)) | 37 | RSession::RSession(Cantor::Backend* backend) : Session(backend), | ||
38 | m_process(nullptr), | ||||
39 | m_rServer(nullptr), | ||||
40 | m_variableModel(new RVariableModel(this)), | ||||
41 | m_needUpdate(false) | ||||
37 | { | 42 | { | ||
38 | } | 43 | } | ||
39 | 44 | | |||
40 | RSession::~RSession() | 45 | RSession::~RSession() | ||
41 | { | 46 | { | ||
42 | if (m_process) | 47 | if (m_process) | ||
43 | m_process->terminate(); | 48 | m_process->terminate(); | ||
44 | } | 49 | } | ||
45 | 50 | | |||
46 | void RSession::login() | 51 | void RSession::login() | ||
47 | { | 52 | { | ||
48 | qDebug()<<"login"; | 53 | qDebug()<<"login"; | ||
49 | emit loginStarted(); | 54 | emit loginStarted(); | ||
50 | 55 | | |||
51 | if(m_process) | 56 | if(m_process) | ||
52 | m_process->deleteLater(); | 57 | m_process->deleteLater(); | ||
53 | 58 | | |||
54 | m_process = new QProcess(this); | 59 | m_process = new QProcess(this); | ||
55 | m_process->start(QStandardPaths::findExecutable(QLatin1String("cantor_rserver"))); | 60 | m_process->start(QStandardPaths::findExecutable(QLatin1String("cantor_rserver"))); | ||
61 | | ||||
56 | m_process->waitForStarted(); | 62 | m_process->waitForStarted(); | ||
57 | m_process->waitForReadyRead(); | 63 | m_process->waitForReadyRead(); | ||
58 | qDebug()<<m_process->readAllStandardOutput(); | 64 | qDebug()<<m_process->readAllStandardOutput(); | ||
59 | 65 | | |||
60 | m_rServer = new org::kde::Cantor::R(QString::fromLatin1("org.kde.Cantor.R-%1").arg(m_process->pid()), QLatin1String("/"), QDBusConnection::sessionBus(), this); | 66 | m_rServer = new org::kde::Cantor::R(QString::fromLatin1("org.kde.Cantor.R-%1").arg(m_process->pid()), QLatin1String("/"), QDBusConnection::sessionBus(), this); | ||
61 | 67 | | |||
62 | connect(m_rServer, SIGNAL(statusChanged(int)), this, SLOT(serverChangedStatus(int))); | 68 | connect(m_rServer, SIGNAL(statusChanged(int)), this, SLOT(serverChangedStatus(int))); | ||
63 | connect(m_rServer, SIGNAL(symbolList(QStringList,QStringList,QStringList)),this,SLOT(receiveSymbols(QStringList,QStringList,QStringList))); | | |||
64 | 69 | | |||
65 | changeStatus(Session::Done); | 70 | changeStatus(Session::Done); | ||
66 | emit loginDone(); | 71 | emit loginDone(); | ||
67 | qDebug()<<"login done"; | 72 | qDebug()<<"login done"; | ||
68 | } | 73 | } | ||
69 | 74 | | |||
70 | void RSession::logout() | 75 | void RSession::logout() | ||
71 | { | 76 | { | ||
72 | qDebug()<<"logout"; | 77 | qDebug()<<"logout"; | ||
73 | m_process->terminate(); | 78 | m_process->terminate(); | ||
74 | 79 | | |||
75 | m_variableModel->clearVariables(); | 80 | m_variableModel->clearVariables(); | ||
76 | m_variables.clear(); | 81 | m_variableModel->clearFunctions(); | ||
asemke: why do you need to cast here? | |||||
77 | m_functions.clear(); | | |||
78 | emit symbolsChanged(); | 82 | emit symbolsChanged(); | ||
79 | 83 | | |||
80 | changeStatus(Status::Disable); | 84 | changeStatus(Status::Disable); | ||
81 | } | 85 | } | ||
82 | 86 | | |||
83 | void RSession::interrupt() | 87 | void RSession::interrupt() | ||
84 | { | 88 | { | ||
85 | if(!expressionQueue().isEmpty()) | 89 | if(!expressionQueue().isEmpty()) | ||
Show All 36 Lines | 124 | { | |||
122 | connect(m_rServer,SIGNAL(completionFinished(QString,QStringList)),cmp,SLOT(receiveCompletions(QString,QStringList))); | 126 | connect(m_rServer,SIGNAL(completionFinished(QString,QStringList)),cmp,SLOT(receiveCompletions(QString,QStringList))); | ||
123 | connect(cmp,SIGNAL(requestCompletion(QString)),m_rServer,SLOT(completeCommand(QString))); | 127 | connect(cmp,SIGNAL(requestCompletion(QString)),m_rServer,SLOT(completeCommand(QString))); | ||
124 | return cmp; | 128 | return cmp; | ||
125 | } | 129 | } | ||
126 | 130 | | |||
127 | QSyntaxHighlighter* RSession::syntaxHighlighter(QObject* parent) | 131 | QSyntaxHighlighter* RSession::syntaxHighlighter(QObject* parent) | ||
128 | { | 132 | { | ||
129 | RHighlighter *h=new RHighlighter(parent); | 133 | RHighlighter *h=new RHighlighter(parent); | ||
130 | connect(h,SIGNAL(syntaxRegExps(QVector<QRegExp>&,QVector<QRegExp>&)),this,SLOT(fillSyntaxRegExps(QVector<QRegExp>&,QVector<QRegExp>&))); | 134 | connect(m_variableModel, &Cantor::DefaultVariableModel::variablesAdded, h, &RHighlighter::addUserVariable); | ||
131 | connect(this,SIGNAL(symbolsChanged()),h,SLOT(refreshSyntaxRegExps())); | 135 | connect(m_variableModel, &Cantor::DefaultVariableModel::variablesRemoved, h, &RHighlighter::removeUserVariable); | ||
132 | connect(this,SIGNAL(syntaxRegExpsFilled()), h, SLOT(updateHighlighting())); | 136 | connect(m_variableModel, &Cantor::DefaultVariableModel::functionsAdded, h, &RHighlighter::addUserFunction); | ||
137 | connect(m_variableModel, &Cantor::DefaultVariableModel::functionsRemoved, h, &RHighlighter::removeUserFunction); | ||||
asemke: why do you need to cast here? | |||||
133 | return h; | 138 | return h; | ||
134 | } | 139 | } | ||
135 | 140 | | |||
136 | void RSession::fillSyntaxRegExps(QVector<QRegExp>& v, QVector<QRegExp>& f) | | |||
137 | { | | |||
138 | // WARNING: current implementation as-in-maxima is a performance hit | | |||
139 | // think about grouping expressions together or only fetching needed ones | | |||
140 | v.clear(); f.clear(); | | |||
141 | | ||||
142 | foreach (const QString s, m_variables) | | |||
143 | if (!s.contains(QRegExp(QLatin1String("[^A-Za-z0-9_.]")))) | | |||
144 | v.append(QRegExp(QLatin1String("\\b")+s+QLatin1String("\\b"))); | | |||
145 | foreach (const QString s, m_functions) | | |||
146 | if (!s.contains(QRegExp(QLatin1String("[^A-Za-z0-9_.]")))) | | |||
147 | f.append(QRegExp(QLatin1String("\\b")+s+QLatin1String("\\b"))); | | |||
148 | | ||||
149 | emit syntaxRegExpsFilled(); | | |||
150 | } | | |||
151 | | ||||
152 | void RSession::receiveSymbols(const QStringList& vars, const QStringList& values, const QStringList & funcs) | | |||
153 | { | | |||
154 | m_variables = vars; | | |||
155 | for (int i = 0; i < vars.count(); i++) | | |||
156 | { | | |||
157 | m_variableModel->addVariable(vars[i], values[i]); | | |||
158 | } | | |||
159 | m_functions = funcs; | | |||
160 | | ||||
161 | emit symbolsChanged(); | | |||
162 | } | | |||
163 | | ||||
164 | void RSession::serverChangedStatus(int status) | 141 | void RSession::serverChangedStatus(int status) | ||
165 | { | 142 | { | ||
166 | qDebug()<<"changed status to "<<status; | 143 | qDebug()<<"changed status to "<<status; | ||
167 | if(status==0) | 144 | if(status==0) | ||
168 | { | 145 | { | ||
169 | if(!expressionQueue().isEmpty()) | 146 | if(!expressionQueue().isEmpty()) | ||
170 | { | 147 | { | ||
171 | RExpression* expr = static_cast<RExpression*>(expressionQueue().takeFirst()); | 148 | RExpression* expr = static_cast<RExpression*>(expressionQueue().takeFirst()); | ||
149 | m_needUpdate |= !expr->isInternal(); | ||||
asemke: why do you need to cast here? | |||||
172 | qDebug()<<"done running "<<expr<<" "<<expr->command(); | 150 | qDebug()<<"done running "<<expr<<" "<<expr->command(); | ||
173 | } | 151 | } | ||
174 | 152 | | |||
175 | if(expressionQueue().isEmpty()) | 153 | if(expressionQueue().isEmpty()) | ||
This logic seems to be the (almost) the same for all session classes. Can we move this maybe to Session.cpp? E.g. to Session::statusChanged()? With this we don't need to touch all the session classes now and to add this m_needUpdate variable everywhere. asemke: This logic seems to be the (almost) the same for all session classes. Can we move this maybe to… | |||||
sirgienko: See Session::finishFirstExpression | |||||
154 | if (m_needUpdate) | ||||
155 | { | ||||
156 | m_needUpdate = false; | ||||
157 | m_variableModel->update(); | ||||
158 | } | ||||
159 | else | ||||
176 | changeStatus(Cantor::Session::Done); | 160 | changeStatus(Cantor::Session::Done); | ||
177 | else | 161 | else | ||
178 | runFirstExpression(); | 162 | runFirstExpression(); | ||
179 | } | 163 | } | ||
180 | else | 164 | else | ||
181 | changeStatus(Cantor::Session::Running); | 165 | changeStatus(Cantor::Session::Running); | ||
182 | } | 166 | } | ||
183 | 167 | | |||
Show All 24 Lines | 191 | if(!input.endsWith(QLatin1Char('\n'))) | |||
208 | s+=QLatin1Char('\n'); | 192 | s+=QLatin1Char('\n'); | ||
209 | m_rServer->answerRequest(s); | 193 | m_rServer->answerRequest(s); | ||
210 | } | 194 | } | ||
211 | 195 | | |||
212 | QAbstractItemModel* RSession::variableModel() | 196 | QAbstractItemModel* RSession::variableModel() | ||
213 | { | 197 | { | ||
214 | return m_variableModel; | 198 | return m_variableModel; | ||
215 | } | 199 | } | ||
200 | | ||||
201 | void RSession::updateSymbols(const RVariableModel* model) | ||||
202 | { | ||||
203 | disconnect(m_rServer, SIGNAL(symbolList(QStringList,QStringList,QStringList))); | ||||
204 | connect(m_rServer, SIGNAL(symbolList(QStringList,QStringList,QStringList)), model, SLOT(parseResult(QStringList,QStringList,QStringList))); | ||||
205 | m_rServer->listSymbols(); | ||||
206 | } |
why do you need to cast here?