File indexing completed on 2024-10-06 09:24:56

0001 /*
0002     SPDX-License-Identifier: GPL-2.0-or-later
0003     SPDX-FileCopyrightText: 2009 Alexander Rieder <alexanderrieder@gmail.com>
0004     SPDX-FileCopyrightText: 2018-2022 Alexander Semke <alexander.semke@web.de>
0005 */
0006 
0007 #include "rexpression.h"
0008 
0009 #include "textresult.h"
0010 #include "imageresult.h"
0011 #include "helpresult.h"
0012 #include "epsresult.h"
0013 #include "rsession.h"
0014 
0015 #include <QDebug>
0016 #include <KLocalizedString>
0017 #include <QMimeType>
0018 #include <QMimeDatabase>
0019 #include <QFile>
0020 
0021 RExpression::RExpression( Cantor::Session* session, bool internal ) : Cantor::Expression(session, internal)
0022 {
0023 
0024 }
0025 
0026 void RExpression::evaluate()
0027 {
0028     const auto& cmd = command();
0029 
0030     //check whether we need to interpret the current command as a help command.
0031     //see https://www.r-project.org/help.html for the list of different ways to get help in R.
0032     if(cmd.startsWith(QLatin1Char('?')) || cmd.startsWith(QStringLiteral("help("))
0033         || cmd.startsWith(QStringLiteral("apropos("))
0034         || cmd.startsWith(QStringLiteral("vignette("))
0035         || cmd == QStringLiteral("demos()")
0036         || cmd.startsWith(QStringLiteral("help.search(")) )
0037         setIsHelpRequest(true);
0038 
0039     session()->enqueueExpression(this);
0040 }
0041 
0042 void RExpression::interrupt()
0043 {
0044     qDebug()<<"interrupting command";
0045     setStatus(Cantor::Expression::Interrupted);
0046 }
0047 
0048 void RExpression::parseOutput(const QString& text)
0049 {
0050     //qDebug() << "output text: " << text;
0051     if (!text.trimmed().isEmpty())
0052     {
0053         if(isHelpRequest())
0054             addResult(new Cantor::HelpResult(text));
0055         else
0056             addResult(new Cantor::TextResult(text));
0057     }
0058     setStatus(Cantor::Expression::Done);
0059 }
0060 
0061 void RExpression::parseError(const QString& text)
0062 {
0063     qDebug() << "error text: " << text;
0064     setErrorMessage(text);
0065     setStatus(Cantor::Expression::Error);
0066 }
0067 
0068 void RExpression::addInformation(const QString& information)
0069 {
0070     static_cast<RSession*>(session())->sendInputToServer(information);
0071 }
0072 
0073 void RExpression::showFilesAsResult(const QStringList& files)
0074 {
0075     qDebug()<<"showing files: "<<files;
0076     for (const QString& file : files)
0077     {
0078         QMimeDatabase db;
0079         auto type = db.mimeTypeForUrl(QUrl(file));
0080         qDebug()<<"MimeType: "<<type.name();
0081         if(type.name() == QLatin1String("application/pdf"))
0082         {
0083             setResult(new Cantor::ImageResult(QUrl::fromLocalFile(file)));
0084             setStatus(Cantor::Expression::Done);
0085         }
0086         else
0087             if (type.name().contains(QLatin1String("image")))
0088         {
0089             setResult(new Cantor::ImageResult(QUrl::fromLocalFile(file)));
0090             setStatus(Cantor::Expression::Done);
0091         }
0092         else if(type.inherits(QLatin1String("text/plain"))
0093             || type.inherits(QLatin1String("application/x-extension-html"))
0094             ||type.inherits(QLatin1String("application/octet-stream")) )
0095         {
0096             //Htmls are also plain texts, combining this in one
0097             const bool isHtml = type.inherits(QLatin1String("text/html"))
0098                 || type.inherits(QLatin1String("application/x-extension-html"))
0099                 || type.inherits(QLatin1String("application/octet-stream"));
0100             if(isHtml)
0101                 qDebug()<<"it's a HTML document";
0102             else
0103                 qDebug()<<"it's a plain text";
0104 
0105             QFile f(file);
0106             if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
0107             {
0108                 setResult(new Cantor::TextResult(i18n("Error opening file %1", file)));
0109                 setErrorMessage(i18n("Error opening file %1", file));
0110                 setStatus(Cantor::Expression::Error);
0111             }
0112             QString content=QTextStream(&f).readAll();
0113             if (!isHtml)
0114             {
0115                 //Escape whitespace
0116                 content.replace( QLatin1Char(' '), QLatin1String("&nbsp;"));
0117                 //replace appearing backspaces, as they mess the whole output up
0118                 content.remove(QRegExp(QLatin1String(".\b")));
0119             }
0120             else
0121                 content.remove(QLatin1String("_\b"));
0122 
0123             qDebug()<<"content: "<<content;
0124             if(isHelpRequest())
0125                 setResult(new Cantor::HelpResult(content));
0126             else
0127                 setResult(new Cantor::TextResult(content));
0128             setStatus(Cantor::Expression::Done);
0129         }
0130         else
0131         {
0132             // File has unsupported mime type, but we suspect, that it is text, so we open the file in the script editor
0133             // Even if it's not text, the script editor can deal with it.
0134             setStatus(Cantor::Expression::Done);
0135             const QString& editor = QStandardPaths::findExecutable(QLatin1String("cantor_scripteditor"));
0136             int code = QProcess::execute(editor, QStringList(file));
0137             if (code == -2)
0138                 qDebug() << "failed to open the file " << file << " with the script editor '" << editor << "'";
0139             else if (code == -1)
0140                 qDebug() << "Cantor script editor crashed";
0141         }
0142     }
0143 }