Commit 71c30b16 authored by Shubham  .'s avatar Shubham .
Browse files

Merge branch 'master' into gsoc20_documentation

parents 5b945842 8aac1569
......@@ -40,3 +40,5 @@ install(
FILES ${scripts}
DESTINATION ${KDE_INSTALL_DATADIR}/cantor/juliabackend/scripts
)
install(FILES graphic_packages.xml DESTINATION ${KDE_INSTALL_DATADIR}/cantor/julia)
<GraphicPackages>
<GraphicPackage>
<Id>gr</Id>
<Name>Julia integrated</Name>
<TestPresenceCommand>
try
import GR
println("1")
catch e
println("0")
end
</TestPresenceCommand>
<EnableCommand>
if (haskey(ENV, "GKS_WSTYPE"))
__cantor_gr_gks_previous__ = ENV["GKS_WSTYPE"]
__cantor_gr_gks_need_restore__ = true
else
__cantor_gr_gks_need_restore__ = false
end
ENV["GKS_WSTYPE"] = "nul"
ENV["GKSwstype"] = ""
GR.emergencyclosegks()
</EnableCommand>
<DisableCommand>
if (__cantor_gr_gks_need_restore__)
ENV["GKS_WSTYPE"] = __cantor_gr_gks_previous__
else
delete!(ENV, "GKS_WSTYPE")
end
ENV["GKSwstype"] = ""
GR.emergencyclosegks()
</DisableCommand>
<ToFileCommandTemplate>
GR.savefig("%1%2.%3")
</ToFileCommandTemplate>
<PlotPrecenseKeywords>
contour
contourf
grid
grid3d
histogram
imshow
plot
plot3
polar
polyline
polyline3d
polymarker
polymarker3d
scatter
scatter3
show
surface
</PlotPrecenseKeywords>
</GraphicPackage>
</GraphicPackages>
......@@ -58,7 +58,7 @@ Cantor::Session *JuliaBackend::createSession()
Cantor::Backend::Capabilities JuliaBackend::capabilities() const
{
Cantor::Backend::Capabilities cap = SyntaxHighlighting | Completion;
Cantor::Backend::Capabilities cap = SyntaxHighlighting | Completion | IntegratedPlots;
if (JuliaSettings::variableManagement())
cap |= VariableManagement;
......
......@@ -49,7 +49,6 @@ void JuliaCompletionObject::fetchCompletions()
allCompletions << JuliaKeywords::instance()->keywords();
allCompletions << JuliaKeywords::instance()->variables();
allCompletions << JuliaKeywords::instance()->functions();
allCompletions << JuliaKeywords::instance()->plotShowingCommands();
setCompletions(allCompletions);
emit fetchingDone();
......
......@@ -28,6 +28,11 @@
#include "textresult.h"
#include "imageresult.h"
const QStringList JuliaExpression::plotExtensions({
QLatin1String("svg"),
QLatin1String("png")
});
JuliaExpression::JuliaExpression(Cantor::Session *session, bool internal)
: Cantor::Expression(session, internal)
{
......@@ -35,7 +40,6 @@ JuliaExpression::JuliaExpression(Cantor::Session *session, bool internal)
void JuliaExpression::evaluate()
{
setStatus(Cantor::Expression::Computing);
auto juliaSession = static_cast<JuliaSession *>(session());
juliaSession->enqueueExpression(this);
......@@ -48,24 +52,28 @@ QString JuliaExpression::internalCommand()
// Plots integration
m_plot_filename.clear();
if (juliaSession->integratePlots() && checkPlotShowingCommands()) {
// Simply add plot saving command to the end of execution
QStringList inlinePlotFormats;
inlinePlotFormats << QLatin1String("svg");
inlinePlotFormats << QLatin1String("png");
auto inlinePlotFormat =
inlinePlotFormats[JuliaSettings::inlinePlotFormat()];
m_plot_filename = QDir::tempPath() +
QString::fromLatin1("/cantor-julia-export-%1.%2")
.arg(QUuid::createUuid().toString()).arg(inlinePlotFormat);
QString saveFigCommand =
QString::fromLatin1("\nGR.savefig(\"%1\")\n").arg(m_plot_filename);
cmd = cmd.append(saveFigCommand);
// Not sure about how this code will work with two graphic packages activated in the same time (they both will save to one file?)...
if (!session()->enabledGraphicPackages().isEmpty() && !isInternal())
{
QStringList cmdWords = cmd.split(QRegularExpression(QStringLiteral("\\b")), QString::SkipEmptyParts);
for (const Cantor::GraphicPackage& package : session()->enabledGraphicPackages())
{
for (const QString& plotCmd : package.plotCommandPrecentsKeywords())
if (cmdWords.contains(plotCmd))
{
if (package.isHavePlotCommand())
{
m_plot_filename = juliaSession->plotFilePrefixPath() + QString::number(id()) + QLatin1String(".") + plotExtensions[JuliaSettings::inlinePlotFormat()];
cmd.append(QLatin1String("\n"));
cmd.append(package.savePlotCommand(juliaSession->plotFilePrefixPath(), id(), plotExtensions[JuliaSettings::inlinePlotFormat()]));
}
break;
}
}
}
qDebug() << "expression internal command:" << cmd;
return cmd;
}
......@@ -93,14 +101,3 @@ void JuliaExpression::interrupt()
setStatus(Cantor::Expression::Interrupted);
}
bool JuliaExpression::checkPlotShowingCommands()
{
for (auto showingCommand :
JuliaKeywords::instance()->plotShowingCommands()) {
if (command().contains(showingCommand + QLatin1String("("))) {
return true;
}
}
return false;
}
......@@ -57,15 +57,10 @@ public:
*/
void finalize(const QString& output, const QString& error, bool wasException);
public:
static const QStringList plotExtensions;
private:
/// If not empty, it's a filename of plot image file expression is awaiting
/// to get
/// If not empty, it's a filename of plot image file expression is awaiting to get
QString m_plot_filename;
/**
* @return bool indicator if current expression contains command that
* shows plot
*/
bool checkPlotShowingCommands();
};
......@@ -32,7 +32,6 @@ JuliaHighlighter::JuliaHighlighter(QObject *parent, JuliaSession* session)
addKeywords(JuliaKeywords::instance()->keywords());
addVariables(JuliaKeywords::instance()->variables());
addFunctions(JuliaKeywords::instance()->functions());
addFunctions(JuliaKeywords::instance()->plotShowingCommands());
}
void JuliaHighlighter::highlightBlock(const QString &text)
......
......@@ -40,24 +40,6 @@ JuliaKeywords::JuliaKeywords()
m_variables << QLatin1String("NaN");
m_variables << QLatin1String("nothing");
m_variables << QLatin1String("true");
m_plotShowingCommands << QLatin1String("contour");
m_plotShowingCommands << QLatin1String("contourf");
m_plotShowingCommands << QLatin1String("grid");
m_plotShowingCommands << QLatin1String("grid3d");
m_plotShowingCommands << QLatin1String("histogram");
m_plotShowingCommands << QLatin1String("imshow");
m_plotShowingCommands << QLatin1String("plot");
m_plotShowingCommands << QLatin1String("plot3");
m_plotShowingCommands << QLatin1String("polar");
m_plotShowingCommands << QLatin1String("polyline");
m_plotShowingCommands << QLatin1String("polyline3d");
m_plotShowingCommands << QLatin1String("polymarker");
m_plotShowingCommands << QLatin1String("polymarker3d");
m_plotShowingCommands << QLatin1String("scatter");
m_plotShowingCommands << QLatin1String("scatter3");
m_plotShowingCommands << QLatin1String("show");
m_plotShowingCommands << QLatin1String("surface");
}
JuliaKeywords *JuliaKeywords::instance()
......
......@@ -39,14 +39,6 @@ public:
*/
const QStringList &keywords() const { return m_keywords; }
/**
* @return list of predefined commands, that are capable to show plot
*/
const QStringList &plotShowingCommands() const
{
return m_plotShowingCommands;
}
/**
* @return list of known variable names
*/
......@@ -93,7 +85,6 @@ public:
private:
QStringList m_keywords; //< list of predefined keywords
QStringList m_plotShowingCommands; //< list of predefined plot showing cmds
QStringList m_variables; //< list of variables known at the moment
QStringList m_removedVariables; //< list of variables removed during cleaning
QStringList m_functions; //< list of known function at the moment
......
......@@ -19,12 +19,15 @@
*/
#include "juliasession.h"
#include <random>
#include <KProcess>
#include <KLocalizedString>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusReply>
#include <QStandardPaths>
#include <QDir>
#include "defaultvariablemodel.h"
......@@ -43,6 +46,8 @@ JuliaSession::JuliaSession(Cantor::Backend *backend)
: Session(backend)
, m_process(nullptr)
, m_interface(nullptr)
, m_isIntegratedPlotsEnabled(false)
, m_isIntegratedPlotsSettingsEnabled(false)
{
setVariableModel(new JuliaVariableModel(this));
}
......@@ -113,13 +118,18 @@ void JuliaSession::login()
static_cast<JuliaVariableModel*>(variableModel())->setJuliaServer(m_interface);
// Plots integration
if (integratePlots()) {
runJuliaCommand(
QLatin1String("import GR; ENV[\"GKS_WSTYPE\"] = \"nul\"")
);
updateVariables();
}
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<int> rand_dist(0, 999999999);
m_plotFilePrefixPath =
QDir::tempPath()
+ QLatin1String("/cantor_octave_")
+ QString::number(m_process->pid())
+ QLatin1String("_")
+ QString::number(rand_dist(mt))
+ QLatin1String("_");
updateVariables();
changeStatus(Session::Done);
emit loginDone();
......@@ -143,6 +153,21 @@ void JuliaSession::logout()
interrupt();
}
if (!m_plotFilePrefixPath.isEmpty())
{
int i = 0;
const QString& extension = JuliaExpression::plotExtensions[JuliaSettings::inlinePlotFormat()];
QString filename = m_plotFilePrefixPath + QString::number(i) + QLatin1String(".") + extension;
while (QFile::exists(filename))
{
QFile::remove(filename);
i++;
filename = m_plotFilePrefixPath + QString::number(i) + QLatin1String(".") + extension;
}
}
m_isIntegratedPlotsEnabled = false;
m_isIntegratedPlotsSettingsEnabled = false;
Session::logout();
}
......@@ -170,6 +195,9 @@ Cantor::Expression *JuliaSession::evaluateExpression(
Cantor::Expression::FinishingBehavior behave,
bool internal)
{
if (!internal)
updateGraphicPackagesFromSettings();
JuliaExpression *expr = new JuliaExpression(this, internal);
expr->setFinishingBehavior(behave);
......@@ -265,9 +293,46 @@ bool JuliaSession::getWasException()
}
bool JuliaSession::integratePlots()
QString JuliaSession::plotFilePrefixPath() const
{
return m_plotFilePrefixPath;
}
void JuliaSession::updateGraphicPackagesFromSettings()
{
if (m_isIntegratedPlotsSettingsEnabled == JuliaSettings::integratePlots())
return;
if (m_isIntegratedPlotsEnabled && JuliaSettings::integratePlots() == false)
{
updateEnabledGraphicPackages(QList<Cantor::GraphicPackage>());
m_isIntegratedPlotsEnabled = false;
m_isIntegratedPlotsSettingsEnabled = JuliaSettings::integratePlots();
return;
}
else if (!m_isIntegratedPlotsEnabled && JuliaSettings::integratePlots() == true)
{
m_isIntegratedPlotsEnabled = true;
m_isIntegratedPlotsSettingsEnabled = true;
updateEnabledGraphicPackages(backend()->availableGraphicPackages());
}
}
QString JuliaSession::graphicPackageErrorMessage(QString packageId) const
{
return JuliaSettings::integratePlots();
QString text;
if (packageId == QLatin1String("gr")) {
return i18n(
"On this moment, integrated graphic can handle only one of Julia packages - GR graphic package. "
"And for using this feature you need to install the package first. "
"For this, run Pkg.install(\"GR\") in Cantor or in julia REPL. Also, it is important "
"to note, that this is a long operation and better use julia REPL, because Cantor don't "
"show intermediate text unlike the julia."
);
}
return text;
}
......@@ -86,10 +86,7 @@ public:
*/
QSyntaxHighlighter *syntaxHighlighter(QObject *parent) override;
/**
* @return indicator if config says to integrate plots into worksheet
*/
bool integratePlots();
QString plotFilePrefixPath() const;
private Q_SLOTS:
/**
......@@ -107,6 +104,11 @@ private:
/// Cache to speedup modules whos calls
QMap<QString, QString> m_whos_cache;
/// Variables for handling plot integration: settings value and real state
QString m_plotFilePrefixPath;
bool m_isIntegratedPlotsEnabled;
bool m_isIntegratedPlotsSettingsEnabled;
void runFirstExpression() override;
/**
......@@ -146,4 +148,8 @@ private:
* @return indicator of exception occurred during the last command execution
*/
bool getWasException();
void updateGraphicPackagesFromSettings();
QString graphicPackageErrorMessage(QString packageId) const override;
};
......@@ -51,3 +51,5 @@ if(BUILD_TESTING)
endif(BUILD_TESTING)
install(FILES cantor_octave.knsrc DESTINATION ${KDE_INSTALL_CONFDIR} )
install(FILES graphic_packages.xml DESTINATION ${KDE_INSTALL_DATADIR}/cantor/octave)
<GraphicPackages>
<GraphicPackage>
<Id>octave_universal</Id>
<Name>Octave</Name>
<TestPresenceCommand>
if (length(available_graphics_toolkits()) > 0)
printf("%d", 1);
else
printf("%d", 0);
endif
</TestPresenceCommand>
<EnableCommand>
set (0, "defaultfigurevisible","off");
</EnableCommand>
<DisableCommand>
set (0, "defaultfigurevisible","on");
</DisableCommand>
<ToFileCommandTemplate>
__cantor_plot_filename__ ='%1%2.%3';
try
print(strcat('-d', '%3'), __cantor_plot_filename__, '-tight');
catch
try
print(strcat('-d', '%3'), __cantor_plot_filename__);
end_try_catch
end_try_catch
clear __cantor_plot_filename__
</ToFileCommandTemplate>
<PlotPrecenseKeywords>
plot
semilogx
semilogy
loglog
polar
contour
bar
stairs
errorbar
sombrero
hist
fplot
imshow
stem
stem3
scatter
pareto
rose
pie
quiver
compass
feather
pcolor
area
fill
comet
plotmatrix
plot3
mesh
meshc
meshz
surf
surfc
surfl
surfnorm
isosurface
isonormals
isocaps
ezplot3
ezmesh
ezmeshc
ezsurf
ezsurfc
cantor_plot2d
cantor_plot3d
</PlotPrecenseKeywords>
</GraphicPackage>
</GraphicPackages>
......@@ -48,9 +48,11 @@ QString OctaveBackend::version() const
Cantor::Backend::Capabilities OctaveBackend::capabilities() const
{
Cantor::Backend::Capabilities cap =
SyntaxHighlighting|
Completion |
SyntaxHelp;
SyntaxHighlighting |
Completion |
SyntaxHelp |
IntegratedPlots;
if (OctaveSettings::self()->variableManagement())
cap |= VariableManagement;
return cap;
......
......@@ -37,25 +37,6 @@
static const QString printCommandTemplate = QString::fromLatin1("cantor_print('%1', '%2');");
static const QStringList plotCommands({
QLatin1String("plot"), QLatin1String("semilogx"), QLatin1String("semilogy"),
QLatin1String("loglog"), QLatin1String("polar"), QLatin1String("contour"),
QLatin1String("bar"), QLatin1String("stairs"), QLatin1String("errorbar"),
QLatin1String("sombrero"), QLatin1String("hist"), QLatin1String("fplot"),
QLatin1String("imshow"), QLatin1String("stem"), QLatin1String("stem3"),
QLatin1String("scatter"), QLatin1String("pareto"), QLatin1String("rose"),
QLatin1String("pie"), QLatin1String("quiver"), QLatin1String("compass"),
QLatin1String("feather"), QLatin1String("pcolor"), QLatin1String("area"),
QLatin1String("fill"), QLatin1String("comet"), QLatin1String("plotmatrix"),
/* 3d-plots */
QLatin1String("plot3"), QLatin1String("mesh"), QLatin1String("meshc"),
QLatin1String("meshz"), QLatin1String("surf"), QLatin1String("surfc"),
QLatin1String("surfl"), QLatin1String("surfnorm"), QLatin1String("isosurface"),
QLatin1String("isonormals"), QLatin1String("isocaps"),
/* 3d-plots defined by a function */
QLatin1String("ezplot3"), QLatin1String("ezmesh"), QLatin1String("ezmeshc"),
QLatin1String("ezsurf"), QLatin1String("ezsurfc"), QLatin1String("cantor_plot2d"),
QLatin1String("cantor_plot3d")});
const QStringList OctaveExpression::plotExtensions({
#ifdef WITH_EPS
QLatin1String("eps"),
......@@ -71,10 +52,6 @@ OctaveExpression::OctaveExpression(Cantor::Session* session, bool internal): Exp
OctaveExpression::~OctaveExpression()
{
if(m_tempFile) {
delete m_tempFile;
m_tempFile = nullptr;
}
}
void OctaveExpression::interrupt()
......@@ -86,47 +63,11 @@ void OctaveExpression::interrupt()
void OctaveExpression::evaluate()
{
if(m_tempFile) {
delete m_tempFile;
m_tempFile = nullptr;
}
qDebug() << "evaluate";
QString cmd = command();
QStringList cmdWords = cmd.split(QRegularExpression(QStringLiteral("\\b")), QString::SkipEmptyParts);
if (static_cast<OctaveSession*>(session())->isIntegratedPlotsEnabled() && !cmdWords.contains(QLatin1String("help")) && !cmdWords.contains(QLatin1String("completion_matches")))
{
for (const QString& plotCmd : plotCommands)
{
if (cmdWords.contains(plotCmd))
{
qDebug() << "Executing a plot command";
/*
#ifdef WITH_EPS
QLatin1String ext(".eps");
#else
QLatin1String ext(".png");
#endif
*/
m_tempFile = new QTemporaryFile(QDir::tempPath() + QLatin1String("/cantor_octave-XXXXXX.")+plotExtensions[OctaveSettings::inlinePlotFormat()]);
m_tempFile->open();
qDebug() << "plot temp file" << m_tempFile->fileName();
QFileSystemWatcher* watcher = fileWatcher();
if (!watcher->files().isEmpty())
watcher->removePaths(watcher->files());
watcher->addPath(m_tempFile->fileName());
connect(watcher, &QFileSystemWatcher::fileChanged, this, &OctaveExpression::imageChanged, Qt::UniqueConnection);
m_plotPending = true;
break;
}
}
}
m_plotFilename.clear();
m_finished = false;
m_plotPending = false;
session()->enqueueExpression(this);
}
......@@ -134,11 +75,42 @@ QString OctaveExpression::internalCommand()
{
QString cmd = command();
if (m_plotPending)
OctaveSession* octaveSession = static_cast<OctaveSession*>(session());
if (octaveSession->isIntegratedPlotsEnabled() && !session()->enabledGraphicPackages().isEmpty() && !isInternal())
{
if (!cmd.endsWith(QLatin1Char(';')) && !cmd.endsWith(QLatin1Char(',')))
cmd += QLatin1Char(',');
cmd += printCommandTemplate.arg(QFileInfo(m_tempFile->fileName()).suffix()).arg(m_tempFile->fileName());
QStringList cmdWords = cmd.split(QRegularExpression(QStringLiteral("\\b")), QString::SkipEmptyParts);
if (!cmdWords.contains(QLatin1String("help")) && !cmdWords.contains(QLatin1String("completion_matches")))
{
Q_ASSERT(session()->enabledGraphicPackages().size() == 1);
const Cantor::GraphicPackage& package = session()->enabledGraphicPackages().first();
Q_ASSERT(package.id() == QLatin1String("octave_universal"));
for (const QString& plotCmd : package.plotCommandPrecentsKeywords())
if (cmdWords.contains(plotCmd))
{
if (package.isHavePlotCommand())
{
m_plotFilename = octaveSession->plotFilePrefixPath() + QString::number(id()) + QLatin1String(".") + plotExtensions[OctaveSettings::inlinePlotFormat()];
if (!cmd.endsWith(QLatin1Char(';')) && !cmd.endsWith(QLatin1Char(',')))