[education/cantor] src/backends: Tag backend plot outputs
Alexander Semke <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit ff5f71dd3912c31be076553cf0f4f9bbd63055ca by Alexander Semke, on behalf of Nanhao Lv.
Committed on 26/07/2026 at 19:50.
Pushed by asemke into branch 'master'.
Tag backend plot outputs
M +6 -2 src/backends/R/rexpression.cpp
M +3 -1 src/backends/julia/juliaexpression.cpp
M +63 -9 src/backends/maxima/maximaexpression.cpp
M +5 -0 src/backends/maxima/maximaexpression.h
M +1 -0 src/backends/octave/octaveexpression.cpp
M +2 -0 src/backends/python/pythonexpression.cpp
M +3 -1 src/backends/qalculate/qalculateexpression.cpp
M +6 -2 src/backends/sage/sageexpression.cpp
M +3 -1 src/backends/scilab/scilabexpression.cpp
https://invent.kde.org/education/cantor/-/commit/ff5f71dd3912c31be076553cf0f4f9bbd63055ca
diff --git a/src/backends/R/rexpression.cpp b/src/backends/R/rexpression.cpp
index 426feefb..4c194683 100644
--- a/src/backends/R/rexpression.cpp
+++ b/src/backends/R/rexpression.cpp
@@ -73,13 +73,17 @@ void RExpression::showFilesAsResult(const QStringList& files)
qDebug()<<"MimeType: "<<type.name();
if(type.name() == QLatin1String("application/pdf"))
{
- setResult(new Cantor::ImageResult(QUrl::fromLocalFile(file)));
+ auto* result = new Cantor::ImageResult(QUrl::fromLocalFile(file));
+ result->setRole(Cantor::Result::Role::Plot);
+ setResult(result);
setStatus(Cantor::Expression::Done);
}
else
if (type.name().contains(QLatin1String("image")))
{
- setResult(new Cantor::ImageResult(QUrl::fromLocalFile(file)));
+ auto* result = new Cantor::ImageResult(QUrl::fromLocalFile(file));
+ result->setRole(Cantor::Result::Role::Plot);
+ setResult(result);
setStatus(Cantor::Expression::Done);
}
else if(type.inherits(QLatin1String("text/plain"))
diff --git a/src/backends/julia/juliaexpression.cpp b/src/backends/julia/juliaexpression.cpp
index 6d0bf915..374ebc1b 100644
--- a/src/backends/julia/juliaexpression.cpp
+++ b/src/backends/julia/juliaexpression.cpp
@@ -69,7 +69,9 @@ void JuliaExpression::finalize(const QString& output, const QString& error, bool
} else {
if (!m_plot_filename.isEmpty() && QFileInfo(m_plot_filename).exists()) {
// If we have plot in result, show it
- setResult(new Cantor::ImageResult(QUrl::fromLocalFile(m_plot_filename)));
+ auto* result = new Cantor::ImageResult(QUrl::fromLocalFile(m_plot_filename));
+ result->setRole(Cantor::Result::Role::Plot);
+ setResult(result);
} else {
if (!output.isEmpty())
setResult(new Cantor::TextResult(output));
diff --git a/src/backends/maxima/maximaexpression.cpp b/src/backends/maxima/maximaexpression.cpp
index 86e6c0d9..47053239 100644
--- a/src/backends/maxima/maximaexpression.cpp
+++ b/src/backends/maxima/maximaexpression.cpp
@@ -17,6 +17,8 @@
#include <QApplication>
#include <QDebug>
#include <QDir>
+#include <QFileInfo>
+#include <QImage>
#include <QRegularExpression>
#include <QScreen>
#include <QTemporaryFile>
@@ -46,6 +48,9 @@ void MaximaExpression::evaluate()
m_isPlot = false;
m_plotResult = nullptr;
m_plotResultIndex = -1;
+ m_plotResultLoadScheduled = false;
+ m_plotFileLastSize = -1;
+ m_plotResultLoadAttempts = 0;
}
QString cmd = command();
@@ -434,7 +439,10 @@ void MaximaExpression::parseResult(const QString& resultContent)
if (m_plotResult)
result = m_plotResult;
else
+ {
+ schedulePlotResultLoad();
result = new Cantor::TextResult(i18n("Waiting for the plot result"));
+ }
}
else
result = new Cantor::TextResult(textContent);
@@ -544,17 +552,63 @@ void MaximaExpression::addInformation(const QString& information)
void MaximaExpression::imageChanged()
{
- if(m_tempFile->size()>0)
- {
- m_plotResult = new Cantor::ImageResult( QUrl::fromLocalFile(m_tempFile->fileName()) );
+ schedulePlotResultLoad();
+}
+
+void MaximaExpression::schedulePlotResultLoad()
+{
+ if (m_plotResult || m_plotResultLoadScheduled)
+ return;
+
+ m_plotResultLoadScheduled = true;
+ QTimer::singleShot(100, this, &MaximaExpression::loadPlotResult);
+}
+
+void MaximaExpression::loadPlotResult()
+{
+ m_plotResultLoadScheduled = false;
+
+ if (!m_tempFile || m_plotResult)
+ return;
- // Check, that we already parse maxima output for this plot, and if not, keep it up to this moment
- // If it's true, replace text info result by real plot and set status as Done
- if (m_plotResultIndex != -1)
+ const QFileInfo plotFileInfo(m_tempFile->fileName());
+ if (!plotFileInfo.exists() || plotFileInfo.size() <= 0)
+ {
+ if (m_plotResultLoadAttempts < 10)
{
- replaceResult(m_plotResultIndex, m_plotResult);
- if (status() != Cantor::Expression::Error)
- setStatus(Cantor::Expression::Done);
+ ++m_plotResultLoadAttempts;
+ schedulePlotResultLoad();
}
+ else if (m_plotResultIndex != -1 && status() == Cantor::Expression::Computing)
+ setStatus(Cantor::Expression::Done);
+
+ return;
+ }
+
+ // QFileSystemWatcher can notify before gnuplot finishes writing.
+ if (plotFileInfo.size() != m_plotFileLastSize)
+ {
+ m_plotFileLastSize = plotFileInfo.size();
+ schedulePlotResultLoad();
+ return;
+ }
+
+ auto* plotResult = new Cantor::ImageResult(QUrl::fromLocalFile(m_tempFile->fileName()));
+ if (plotResult->data().value<QImage>().isNull() && m_plotResultLoadAttempts < 10)
+ {
+ delete plotResult;
+ ++m_plotResultLoadAttempts;
+ schedulePlotResultLoad();
+ return;
+ }
+
+ m_plotResult = plotResult;
+ m_plotResult->setRole(Cantor::Result::Role::Plot);
+
+ if (m_plotResultIndex != -1)
+ {
+ replaceResult(m_plotResultIndex, m_plotResult);
+ if (status() == Cantor::Expression::Computing)
+ setStatus(Cantor::Expression::Done);
}
}
diff --git a/src/backends/maxima/maximaexpression.h b/src/backends/maxima/maximaexpression.h
index 3d3ac647..e7121442 100644
--- a/src/backends/maxima/maximaexpression.h
+++ b/src/backends/maxima/maximaexpression.h
@@ -35,9 +35,11 @@ public:
private Q_SLOTS:
void imageChanged();
+ void loadPlotResult();
private:
void parseResult(const QString&);
+ void schedulePlotResultLoad();
QTemporaryFile* m_tempFile = nullptr;
QFileSystemWatcher m_fileWatch;
@@ -47,6 +49,9 @@ private:
bool m_isDraw = false;
Cantor::Result* m_plotResult = nullptr;
int m_plotResultIndex = -1;
+ bool m_plotResultLoadScheduled = false;
+ qint64 m_plotFileLastSize = -1;
+ int m_plotResultLoadAttempts = 0;
QString m_errorBuffer;
};
diff --git a/src/backends/octave/octaveexpression.cpp b/src/backends/octave/octaveexpression.cpp
index d548ab4d..121f1803 100644
--- a/src/backends/octave/octaveexpression.cpp
+++ b/src/backends/octave/octaveexpression.cpp
@@ -235,6 +235,7 @@ void OctaveExpression::imageChanged()
const QUrl& url = QUrl::fromLocalFile(m_plotFilename);
QByteArray pdfData = file.readAll();
auto* newResult = new Cantor::PdfResult(url, pdfData);
+ newResult->setRole(Cantor::Result::Role::Plot);
bool found = false;
for (int i = 0; i < results().size(); i++)
diff --git a/src/backends/python/pythonexpression.cpp b/src/backends/python/pythonexpression.cpp
index 6f400578..5a5d97e3 100644
--- a/src/backends/python/pythonexpression.cpp
+++ b/src/backends/python/pythonexpression.cpp
@@ -143,6 +143,7 @@ void PythonExpression::imageChanged()
return;
auto* newResult = new Cantor::ImageResult(QUrl::fromLocalFile(m_tempFile->fileName()));
+ newResult->setRole(Cantor::Result::Role::Plot);
if (result() == nullptr)
setResult(newResult);
else
@@ -153,6 +154,7 @@ void PythonExpression::imageChanged()
{
replaceResult(i, newResult);
found = true;
+ break;
}
if (!found)
addResult(newResult);
diff --git a/src/backends/qalculate/qalculateexpression.cpp b/src/backends/qalculate/qalculateexpression.cpp
index 8ceaea1e..6eefcc4a 100644
--- a/src/backends/qalculate/qalculateexpression.cpp
+++ b/src/backends/qalculate/qalculateexpression.cpp
@@ -646,7 +646,9 @@ void QalculateExpression::evaluatePlotCommand()
deletePlotDataParameters(plotDataParameterList);
if (plotInline) {
- setResult(new Cantor::ImageResult(QUrl::fromLocalFile(QString::fromStdString(plotParameters.filename))));
+ auto* result = new Cantor::ImageResult(QUrl::fromLocalFile(QString::fromStdString(plotParameters.filename)));
+ result->setRole(Cantor::Result::Role::Plot);
+ setResult(result);
setStatus(Cantor::Expression::Done);
}
}
diff --git a/src/backends/sage/sageexpression.cpp b/src/backends/sage/sageexpression.cpp
index b7addd4a..a6dedb21 100644
--- a/src/backends/sage/sageexpression.cpp
+++ b/src/backends/sage/sageexpression.cpp
@@ -220,12 +220,16 @@ void SageExpression::evalFinished()
if(type.inherits(QLatin1String("image/gif")))
{
qDebug()<<"adding animation";
- addResult( new Cantor::AnimationResult(QUrl::fromLocalFile(m_imagePath), i18n("Result of %1" , command() ) ) );
+ auto* result = new Cantor::AnimationResult(QUrl::fromLocalFile(m_imagePath), i18n("Result of %1" , command() ) );
+ result->setRole(Cantor::Result::Role::Plot);
+ addResult(result);
}
else
{
qDebug()<<"adding image";
- addResult( new Cantor::ImageResult(QUrl::fromLocalFile(m_imagePath ), i18n("Result of %1" , command() ) ) );
+ auto* result = new Cantor::ImageResult(QUrl::fromLocalFile(m_imagePath ), i18n("Result of %1" , command() ) );
+ result->setRole(Cantor::Result::Role::Plot);
+ addResult(result);
}
}
setStatus(Cantor::Expression::Done);
diff --git a/src/backends/scilab/scilabexpression.cpp b/src/backends/scilab/scilabexpression.cpp
index 5c60dcfe..4477b9f2 100644
--- a/src/backends/scilab/scilabexpression.cpp
+++ b/src/backends/scilab/scilabexpression.cpp
@@ -97,7 +97,9 @@ void ScilabExpression::parsePlotFile(QString filename)
qDebug() << "parsePlotFile";
qDebug() << "ScilabExpression::parsePlotFile: " << filename;
- setResult(new ScilabPlotResult(QUrl::fromLocalFile(filename)));
+ auto* result = new ScilabPlotResult(QUrl::fromLocalFile(filename));
+ result->setRole(Cantor::Result::Role::Plot);
+ setResult(result);
setPlotPending(false);