Warning, file /education/cantor/src/backends/scilab/scilabsession.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-License-Identifier: GPL-2.0-or-later 0003 SPDX-FileCopyrightText: 2011 Filipe Saraiva <filipe@kde.org> 0004 */ 0005 0006 #include "scilabsession.h" 0007 #include "scilabhighlighter.h" 0008 #include "scilabcompletionobject.h" 0009 0010 #include <defaultvariablemodel.h> 0011 0012 #include <QProcess> 0013 #include <KDirWatch> 0014 0015 #include <QDebug> 0016 #include <QDir> 0017 #include <QFile> 0018 #include <QTextEdit> 0019 #include <QListIterator> 0020 #include <QIODevice> 0021 #include <QByteArray> 0022 0023 #include <settings.h> 0024 0025 #ifndef Q_OS_WIN 0026 #include <signal.h> 0027 #endif 0028 0029 ScilabSession::ScilabSession( Cantor::Backend* backend) : Session(backend), 0030 m_process(nullptr), 0031 m_watch(nullptr), 0032 m_variableModel(new Cantor::DefaultVariableModel(this)) 0033 { 0034 } 0035 0036 ScilabSession::~ScilabSession() 0037 { 0038 if (m_process) 0039 { 0040 m_process->kill(); 0041 m_process->deleteLater(); 0042 m_process = nullptr; 0043 } 0044 } 0045 0046 void ScilabSession::login() 0047 { 0048 qDebug()<<"login"; 0049 if (m_process) 0050 return; 0051 0052 emit loginStarted(); 0053 0054 QStringList args; 0055 0056 args << QLatin1String("-nb"); 0057 0058 m_process = new QProcess(this); 0059 m_process->setArguments(args); 0060 m_process->setProgram(ScilabSettings::self()->path().toLocalFile()); 0061 0062 qDebug() << m_process->program(); 0063 0064 m_process->setProcessChannelMode(QProcess::SeparateChannels); 0065 m_process->start(); 0066 m_process->waitForStarted(); 0067 0068 if(ScilabSettings::integratePlots()){ 0069 0070 qDebug() << "integratePlots"; 0071 0072 QString tempPath = QDir::tempPath(); 0073 0074 QString pathScilabOperations = tempPath; 0075 pathScilabOperations.prepend(QLatin1String("chdir('")); 0076 pathScilabOperations.append(QLatin1String("');\n")); 0077 0078 qDebug() << "Processing command to change chdir in Scilab. Command " << pathScilabOperations.toLocal8Bit(); 0079 0080 m_process->write(pathScilabOperations.toLocal8Bit()); 0081 0082 m_watch = new KDirWatch(this); 0083 m_watch->setObjectName(QLatin1String("ScilabDirWatch")); 0084 0085 m_watch->addDir(tempPath, KDirWatch::WatchFiles); 0086 0087 qDebug() << "addDir " << tempPath << "? " << m_watch->contains(QLatin1String(tempPath.toLocal8Bit())); 0088 0089 QObject::connect(m_watch, &KDirWatch::created, this, &ScilabSession::plotFileChanged); 0090 } 0091 0092 if(!ScilabSettings::self()->autorunScripts().isEmpty()){ 0093 QString autorunScripts = ScilabSettings::self()->autorunScripts().join(QLatin1String("\n")); 0094 m_process->write(autorunScripts.toLocal8Bit()); 0095 } 0096 0097 QObject::connect(m_process, &QProcess::readyReadStandardOutput, this, &ScilabSession::readOutput); 0098 QObject::connect(m_process, &QProcess::readyReadStandardError, this, &ScilabSession::readError); 0099 0100 m_process->readAllStandardOutput(); 0101 m_process->readAllStandardError(); 0102 0103 changeStatus(Cantor::Session::Done); 0104 0105 emit loginDone(); 0106 } 0107 0108 void ScilabSession::logout() 0109 { 0110 qDebug()<<"logout"; 0111 0112 if(!m_process) 0113 return; 0114 0115 disconnect(m_process, nullptr, this, nullptr); 0116 0117 if(status() == Cantor::Session::Running) 0118 interrupt(); 0119 0120 m_process->write("exit\n"); 0121 0122 if(!m_process->waitForFinished(1000)) 0123 m_process->kill(); 0124 m_process->deleteLater(); 0125 m_process = nullptr; 0126 0127 QDir removePlotFigures; 0128 QListIterator<QString> i(m_listPlotName); 0129 0130 while(i.hasNext()){ 0131 removePlotFigures.remove(QLatin1String(i.next().toLocal8Bit().constData())); 0132 } 0133 0134 Session::logout(); 0135 } 0136 0137 void ScilabSession::interrupt() 0138 { 0139 if(!expressionQueue().isEmpty()) 0140 { 0141 qDebug()<<"interrupting " << expressionQueue().first()->command(); 0142 if(m_process && m_process->state() != QProcess::NotRunning) 0143 { 0144 #ifndef Q_OS_WIN 0145 const int pid = m_process->processId(); 0146 kill(pid, SIGINT); 0147 #else 0148 ; //TODO: interrupt the process on windows 0149 #endif 0150 } 0151 foreach (Cantor::Expression* expression, expressionQueue()) 0152 expression->setStatus(Cantor::Expression::Interrupted); 0153 expressionQueue().clear(); 0154 0155 // Cleanup inner state and call octave prompt printing 0156 // If we move this code for interruption to Session, we need add function for 0157 // cleaning before setting Done status 0158 m_output.clear(); 0159 m_process->write("\n"); 0160 0161 qDebug()<<"done interrupting"; 0162 } 0163 0164 changeStatus(Cantor::Session::Done); 0165 } 0166 0167 Cantor::Expression* ScilabSession::evaluateExpression(const QString& cmd, Cantor::Expression::FinishingBehavior behave, bool internal) 0168 { 0169 qDebug() << "evaluating: " << cmd; 0170 ScilabExpression* expr = new ScilabExpression(this, internal); 0171 0172 expr->setFinishingBehavior(behave); 0173 expr->setCommand(cmd); 0174 expr->evaluate(); 0175 0176 return expr; 0177 } 0178 0179 void ScilabSession::runFirstExpression() 0180 { 0181 qDebug() <<"call runFirstExpression"; 0182 qDebug() << "m_process: " << m_process; 0183 qDebug() << "status: " << (status() == Cantor::Session::Running ? "Running" : "Done"); 0184 0185 if (!m_process) 0186 return; 0187 0188 qDebug()<<"running next expression"; 0189 0190 if(!expressionQueue().isEmpty()) 0191 { 0192 auto* expr = expressionQueue().first(); 0193 0194 QString command; 0195 command.prepend(QLatin1String("\nprintf('begin-cantor-scilab-command-processing')\n")); 0196 command += expr->command(); 0197 command += QLatin1String("\nprintf('terminated-cantor-scilab-command-processing')\n"); 0198 0199 connect(expr, &Cantor::Expression::statusChanged, this, &ScilabSession::currentExpressionStatusChanged); 0200 expr->setStatus(Cantor::Expression::Computing); 0201 0202 qDebug() << "Writing command to process" << command; 0203 0204 m_process->write(command.toLocal8Bit()); 0205 } 0206 } 0207 0208 void ScilabSession::readError() 0209 { 0210 qDebug() << "readError"; 0211 0212 QString error = QLatin1String(m_process->readAllStandardError()); 0213 0214 qDebug() << "error: " << error; 0215 if (!expressionQueue().isEmpty()) 0216 expressionQueue().first()->parseError(error); 0217 } 0218 0219 void ScilabSession::readOutput() 0220 { 0221 qDebug() << "readOutput"; 0222 0223 while(m_process->bytesAvailable() > 0) 0224 m_output.append(QString::fromLocal8Bit(m_process->readLine())); 0225 0226 qDebug() << "output.isNull? " << m_output.isNull(); 0227 qDebug() << "output: " << m_output; 0228 0229 if(status() != Running || m_output.isNull()) 0230 return; 0231 0232 if(m_output.contains(QLatin1String("begin-cantor-scilab-command-processing")) && 0233 m_output.contains(QLatin1String("terminated-cantor-scilab-command-processing"))){ 0234 0235 m_output.remove(QLatin1String("begin-cantor-scilab-command-processing")); 0236 m_output.remove(QLatin1String("terminated-cantor-scilab-command-processing")); 0237 0238 expressionQueue().first()->parseOutput(m_output); 0239 0240 m_output.clear(); 0241 } 0242 } 0243 0244 void ScilabSession::plotFileChanged(const QString& filename) 0245 { 0246 qDebug() << "plotFileChanged filename:" << filename; 0247 0248 if (!expressionQueue().isEmpty() && (filename.contains(QLatin1String("cantor-export-scilab-figure")))){ 0249 qDebug() << "Calling parsePlotFile"; 0250 static_cast<ScilabExpression*>(expressionQueue().first())->parsePlotFile(filename); 0251 0252 m_listPlotName.append(filename); 0253 } 0254 } 0255 0256 //TODO: unify with the funcion in the base class 0257 void ScilabSession::currentExpressionStatusChanged(Cantor::Expression::Status status) 0258 { 0259 qDebug() << "currentExpressionStatusChanged: " << status; 0260 0261 switch (status){ 0262 case Cantor::Expression::Computing: 0263 case Cantor::Expression::Interrupted: 0264 case Cantor::Expression::Queued: 0265 break; 0266 0267 case Cantor::Expression::Done: 0268 case Cantor::Expression::Error: 0269 expressionQueue().removeFirst(); 0270 0271 if (expressionQueue().isEmpty()) 0272 changeStatus(Done); 0273 else 0274 runFirstExpression(); 0275 0276 break; 0277 } 0278 } 0279 0280 QSyntaxHighlighter* ScilabSession::syntaxHighlighter(QObject* parent) 0281 { 0282 0283 ScilabHighlighter *highlighter = new ScilabHighlighter(parent, this); 0284 0285 return highlighter; 0286 } 0287 0288 Cantor::CompletionObject* ScilabSession::completionFor(const QString& command, int index) 0289 { 0290 return new ScilabCompletionObject(command, index, this); 0291 } 0292 0293 Cantor::DefaultVariableModel* ScilabSession::variableModel() const 0294 { 0295 return m_variableModel; 0296 } 0297