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) | ||||
37 | { | 40 | { | ||
41 | setVariableModel(new RVariableModel(this)); | ||||
38 | } | 42 | } | ||
39 | 43 | | |||
40 | RSession::~RSession() | 44 | RSession::~RSession() | ||
41 | { | 45 | { | ||
42 | if (m_process) | 46 | if (m_process) | ||
43 | m_process->terminate(); | 47 | m_process->terminate(); | ||
44 | } | 48 | } | ||
45 | 49 | | |||
46 | void RSession::login() | 50 | void RSession::login() | ||
47 | { | 51 | { | ||
48 | qDebug()<<"login"; | 52 | qDebug()<<"login"; | ||
49 | emit loginStarted(); | 53 | emit loginStarted(); | ||
50 | 54 | | |||
51 | if(m_process) | 55 | if(m_process) | ||
52 | m_process->deleteLater(); | 56 | m_process->deleteLater(); | ||
53 | 57 | | |||
54 | m_process = new QProcess(this); | 58 | m_process = new QProcess(this); | ||
55 | m_process->start(QStandardPaths::findExecutable(QLatin1String("cantor_rserver"))); | 59 | m_process->start(QStandardPaths::findExecutable(QLatin1String("cantor_rserver"))); | ||
60 | | ||||
56 | m_process->waitForStarted(); | 61 | m_process->waitForStarted(); | ||
57 | m_process->waitForReadyRead(); | 62 | m_process->waitForReadyRead(); | ||
58 | qDebug()<<m_process->readAllStandardOutput(); | 63 | qDebug()<<m_process->readAllStandardOutput(); | ||
59 | 64 | | |||
60 | m_rServer = new org::kde::Cantor::R(QString::fromLatin1("org.kde.Cantor.R-%1").arg(m_process->pid()), QLatin1String("/"), QDBusConnection::sessionBus(), this); | 65 | m_rServer = new org::kde::Cantor::R(QString::fromLatin1("org.kde.Cantor.R-%1").arg(m_process->pid()), QLatin1String("/"), QDBusConnection::sessionBus(), this); | ||
61 | 66 | | |||
62 | connect(m_rServer, SIGNAL(statusChanged(int)), this, SLOT(serverChangedStatus(int))); | 67 | 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 | 68 | | |||
65 | changeStatus(Session::Done); | 69 | changeStatus(Session::Done); | ||
66 | emit loginDone(); | 70 | emit loginDone(); | ||
67 | qDebug()<<"login done"; | 71 | qDebug()<<"login done"; | ||
68 | } | 72 | } | ||
69 | 73 | | |||
70 | void RSession::logout() | 74 | void RSession::logout() | ||
71 | { | 75 | { | ||
72 | qDebug()<<"logout"; | 76 | qDebug()<<"logout"; | ||
73 | m_process->terminate(); | 77 | m_process->terminate(); | ||
74 | 78 | | |||
75 | m_variableModel->clearVariables(); | 79 | variableModel()->clearVariables(); | ||
76 | m_variables.clear(); | 80 | variableModel()->clearFunctions(); | ||
asemke: why do you need to cast here? | |||||
77 | m_functions.clear(); | | |||
78 | emit symbolsChanged(); | 81 | emit symbolsChanged(); | ||
79 | 82 | | |||
80 | changeStatus(Status::Disable); | 83 | changeStatus(Status::Disable); | ||
81 | } | 84 | } | ||
82 | 85 | | |||
83 | void RSession::interrupt() | 86 | void RSession::interrupt() | ||
84 | { | 87 | { | ||
85 | if(!expressionQueue().isEmpty()) | 88 | if(!expressionQueue().isEmpty()) | ||
Show All 34 Lines | |||||
120 | { | 123 | { | ||
121 | RCompletionObject *cmp=new RCompletionObject(command, index, this); | 124 | RCompletionObject *cmp=new RCompletionObject(command, index, this); | ||
122 | connect(m_rServer,SIGNAL(completionFinished(QString,QStringList)),cmp,SLOT(receiveCompletions(QString,QStringList))); | 125 | connect(m_rServer,SIGNAL(completionFinished(QString,QStringList)),cmp,SLOT(receiveCompletions(QString,QStringList))); | ||
123 | connect(cmp,SIGNAL(requestCompletion(QString)),m_rServer,SLOT(completeCommand(QString))); | 126 | connect(cmp,SIGNAL(requestCompletion(QString)),m_rServer,SLOT(completeCommand(QString))); | ||
124 | return cmp; | 127 | return cmp; | ||
125 | } | 128 | } | ||
126 | 129 | | |||
127 | QSyntaxHighlighter* RSession::syntaxHighlighter(QObject* parent) | 130 | QSyntaxHighlighter* RSession::syntaxHighlighter(QObject* parent) | ||
128 | { | 131 | { | ||
129 | RHighlighter *h=new RHighlighter(parent); | 132 | return new RHighlighter(parent, this); | ||
asemke: why do you need to cast here? | |||||
130 | connect(h,SIGNAL(syntaxRegExps(QVector<QRegExp>&,QVector<QRegExp>&)),this,SLOT(fillSyntaxRegExps(QVector<QRegExp>&,QVector<QRegExp>&))); | | |||
131 | connect(this,SIGNAL(symbolsChanged()),h,SLOT(refreshSyntaxRegExps())); | | |||
132 | connect(this,SIGNAL(syntaxRegExpsFilled()), h, SLOT(updateHighlighting())); | | |||
133 | return h; | | |||
134 | } | | |||
135 | | ||||
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 | } | 133 | } | ||
163 | 134 | | |||
164 | void RSession::serverChangedStatus(int status) | 135 | void RSession::serverChangedStatus(int status) | ||
165 | { | 136 | { | ||
166 | qDebug()<<"changed status to "<<status; | 137 | qDebug()<<"changed status to "<<status; | ||
167 | if(status==0) | 138 | if(status==0) | ||
168 | { | 139 | { | ||
169 | if(!expressionQueue().isEmpty()) | 140 | if(!expressionQueue().isEmpty()) | ||
170 | { | 141 | { | ||
171 | RExpression* expr = static_cast<RExpression*>(expressionQueue().takeFirst()); | 142 | Cantor::Expression* expr = expressionQueue().first(); | ||
asemke: why do you need to cast here? | |||||
172 | qDebug()<<"done running "<<expr<<" "<<expr->command(); | 143 | qDebug()<<"done running "<<expr<<" "<<expr->command(); | ||
173 | } | 144 | } | ||
174 | 145 | finishFirstExpression(); | |||
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 | |||||
175 | if(expressionQueue().isEmpty()) | | |||
176 | changeStatus(Cantor::Session::Done); | | |||
177 | else | | |||
178 | runFirstExpression(); | | |||
179 | } | 146 | } | ||
180 | else | 147 | else | ||
181 | changeStatus(Cantor::Session::Running); | 148 | changeStatus(Cantor::Session::Running); | ||
182 | } | 149 | } | ||
183 | 150 | | |||
184 | void RSession::runFirstExpression() | 151 | void RSession::runFirstExpression() | ||
185 | { | 152 | { | ||
186 | if (expressionQueue().isEmpty()) | 153 | if (expressionQueue().isEmpty()) | ||
Show All 17 Lines | |||||
204 | void RSession::sendInputToServer(const QString& input) | 171 | void RSession::sendInputToServer(const QString& input) | ||
205 | { | 172 | { | ||
206 | QString s=input; | 173 | QString s=input; | ||
207 | if(!input.endsWith(QLatin1Char('\n'))) | 174 | if(!input.endsWith(QLatin1Char('\n'))) | ||
208 | s+=QLatin1Char('\n'); | 175 | s+=QLatin1Char('\n'); | ||
209 | m_rServer->answerRequest(s); | 176 | m_rServer->answerRequest(s); | ||
210 | } | 177 | } | ||
211 | 178 | | |||
212 | QAbstractItemModel* RSession::variableModel() | 179 | void RSession::updateSymbols(const RVariableModel* model) | ||
213 | { | 180 | { | ||
214 | return m_variableModel; | 181 | disconnect(m_rServer, SIGNAL(symbolList(QStringList,QStringList,QStringList))); | ||
182 | connect(m_rServer, SIGNAL(symbolList(QStringList,QStringList,QStringList)), model, SLOT(parseResult(QStringList,QStringList,QStringList))); | ||||
183 | m_rServer->listSymbols(); | ||||
215 | } | 184 | } |
why do you need to cast here?