diff --git a/src/backends/R/rbackend.cpp b/src/backends/R/rbackend.cpp index ab619b9b..efeae8ef 100644 --- a/src/backends/R/rbackend.cpp +++ b/src/backends/R/rbackend.cpp @@ -1,111 +1,116 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2009 Alexander Rieder */ #include "rbackend.h" #include "rsession.h" #include "rextensions.h" #include "settings.h" #include "rsettingswidget.h" #include #include "cantor_macros.h" #include RBackend::RBackend(QObject* parent,const QList& args) : Cantor::Backend(parent, args) { setObjectName(QLatin1String("rbackend")); qDebug()<<"Creating RBackend"; new RScriptExtension(this); new RPlotExtension(this); new RVariableManagementExtension(this); } RBackend::~RBackend() { qDebug()<<"Destroying RBackend"; } QString RBackend::id() const { return QLatin1String("r"); } QString RBackend::version() const { return QLatin1String("Undefined"); } Cantor::Session* RBackend::createSession() { qDebug()<<"Spawning a new R session"; return new RSession(this); } Cantor::Backend::Capabilities RBackend::capabilities() const { qDebug()<<"Requesting capabilities of RSession"; - return Cantor::Backend::InteractiveMode | - Cantor::Backend::SyntaxHighlighting | - Cantor::Backend::Completion | - Cantor::Backend::VariableManagement; + Cantor::Backend::Capabilities cap= + SyntaxHighlighting| + Completion | + InteractiveMode; + + if (RServerSettings::variableManagement()) + cap |= VariableManagement; + + return cap; } bool RBackend::requirementsFullfilled() const { QFileInfo info(QStandardPaths::findExecutable( QLatin1String("cantor_rserver") ) ); return info.isExecutable(); } QWidget* RBackend::settingsWidget(QWidget* parent) const { return new RSettingsWidget(parent); } KConfigSkeleton* RBackend::config() const { return RServerSettings::self(); } QUrl RBackend::helpUrl() const { const QUrl& localDoc = RServerSettings::self()->localDoc(); if (!localDoc.isEmpty()) return localDoc; else return QUrl(i18nc("the url to the documentation of R, please check if there is a translated version and use the correct url", "http://rwiki.sciviews.org/doku.php?id=rdoc:rdoc")); } QString RBackend::description() const { return i18n("R is a language and environment for statistical computing and graphics, similar to the S language and environment.
"\ "It provides a wide variety of statistical (linear and nonlinear modelling, "\ "classical statistical tests, time-series analysis, classification, clustering, ...) "\ "and graphical techniques, and is highly extensible. The S language is often the "\ "vehicle of choice for research in statistical methodology, "\ "and R provides an Open Source route to participation in that activity."); } K_PLUGIN_FACTORY_WITH_JSON(rbackend, "rbackend.json", registerPlugin();) #include "rbackend.moc" diff --git a/src/backends/R/rserver/rserver.cpp b/src/backends/R/rserver/rserver.cpp index 7d90c205..0cdb3789 100644 --- a/src/backends/R/rserver/rserver.cpp +++ b/src/backends/R/rserver/rserver.cpp @@ -1,511 +1,513 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2009 Alexander Rieder Copyright (C) 2010 Oleksiy Protas */ // TODO: setStatus in syntax and completions, to be or not to be? // on the one hand comme il faut, on another, causes flickering in UI #include "rserver.h" #include #include "radaptor.h" #include "rcallbacks.h" #include "settings.h" #include #include #include #include #include //R includes #include #include #include #include #define R_INTERFACE_PTRS #include RServer::RServer() : m_isInitialized(false),m_isCompletionAvailable(false) { new RAdaptor(this); m_tmpDir = QDir::tempPath() + QString::fromLatin1("/cantor_rserver-%1").arg(getpid()); QDir dir; dir.mkdir(m_tmpDir); qDebug()<<"storing plots at "<integratePlots()) { qDebug()<<"integrating plots"; newPlotDevice(); } //Loading automatic run scripts foreach (const QString& path, RServerSettings::self()->autorunScripts()) { int errorOccurred=0; if (QFile::exists(path)) R_tryEval(lang2(install("source"),mkString(path.toUtf8().data())),nullptr,&errorOccurred); // TODO: error handling else { qDebug()<<(QLatin1String("Script ")+path+QLatin1String(" not found")); // FIXME: or should we throw a messagebox } } qDebug()<<"done initializing"; } //Code from the RInside library void RServer::autoload() { #include "rautoloads.h" /* Autoload default packages and names from autoloads.h * * This function behaves in almost every way like * R's autoload: * function (name, package, reset = FALSE, ...) * { * if (!reset && exists(name, envir = .GlobalEnv, inherits = FALSE)) * stop("an object with that name already exists") * m <- match.call() * m[[1]] <- as.name("list") * newcall <- eval(m, parent.frame()) * newcall <- as.call(c(as.name("autoloader"), newcall)) * newcall$reset <- NULL * if (is.na(match(package, .Autoloaded))) * assign(".Autoloaded", c(package, .Autoloaded), env = .AutoloadEnv) * do.call("delayedAssign", list(name, newcall, .GlobalEnv, * .AutoloadEnv)) * invisible() * } * * What's missing is the updating of the string vector .Autoloaded with * the list of packages, which by my code analysis is useless and only * for informational purposes. * */ //void autoloads(void){ SEXP da, dacall, al, alcall, AutoloadEnv, name, package; int i,j, idx=0, errorOccurred, ptct; /* delayedAssign call*/ PROTECT(da = Rf_findFun(Rf_install("delayedAssign"), R_GlobalEnv)); PROTECT(AutoloadEnv = Rf_findVar(Rf_install(".AutoloadEnv"), R_GlobalEnv)); if (AutoloadEnv == R_NilValue){ qDebug()<<"Cannot find .AutoloadEnv"; //exit(1); } PROTECT(dacall = allocVector(LANGSXP,5)); SETCAR(dacall,da); /* SETCAR(CDR(dacall),name); */ /* arg1: assigned in loop */ /* SETCAR(CDR(CDR(dacall)),alcall); */ /* arg2: assigned in loop */ SETCAR(CDR(CDR(CDR(dacall))),R_GlobalEnv); /* arg3 */ SETCAR(CDR(CDR(CDR(CDR(dacall)))),AutoloadEnv); /* arg3 */ /* autoloader call */ PROTECT(al = Rf_findFun(Rf_install("autoloader"), R_GlobalEnv)); PROTECT(alcall = allocVector(LANGSXP,3)); SET_TAG(alcall, R_NilValue); /* just like do_ascall() does */ SETCAR(alcall,al); /* SETCAR(CDR(alcall),name); */ /* arg1: assigned in loop */ /* SETCAR(CDR(CDR(alcall)),package); */ /* arg2: assigned in loop */ ptct = 5; for(i = 0; i < packc; ++i){ idx += (i != 0)? packobjc[i-1] : 0; for (j = 0; j < packobjc[i]; ++j){ /*printf("autload(%s,%s)\n",packobj[idx+j],pack[i]);*/ PROTECT(name = NEW_CHARACTER(1)); PROTECT(package = NEW_CHARACTER(1)); SET_STRING_ELT(name, 0, COPY_TO_USER_STRING(packobj[idx+j])); SET_STRING_ELT(package, 0, COPY_TO_USER_STRING(pack[i])); /* Set up autoloader call */ PROTECT(alcall = allocVector(LANGSXP,3)); SET_TAG(alcall, R_NilValue); /* just like do_ascall() does */ SETCAR(alcall,al); SETCAR(CDR(alcall),name); SETCAR(CDR(CDR(alcall)),package); /* Setup delayedAssign call */ SETCAR(CDR(dacall),name); SETCAR(CDR(CDR(dacall)),alcall); R_tryEval(dacall,R_GlobalEnv,&errorOccurred); if (errorOccurred){ qDebug()<<"Error calling delayedAssign!"; //exit(1); } ptct += 3; } } UNPROTECT(ptct); /* Initialize the completion libraries if needed, adapted from sys-std.c of R */ // TODO: should we do this or init on demand? // if (completion is needed) // TODO: discuss how to pass parameter { /* First check if namespace is loaded */ if (findVarInFrame(R_NamespaceRegistry,install("utils"))==R_UnboundValue) { /* Then try to load it */ SEXP cmdSexp, cmdexpr; ParseStatus status; int i; const char *p="try(loadNamespace('rcompgen'), silent=TRUE)"; PROTECT(cmdSexp=mkString(p)); cmdexpr=PROTECT(R_ParseVector(cmdSexp,-1,&status,R_NilValue)); if(status==PARSE_OK) { for(i=0;icmd=cmd; expr->hasOtherResults=false; setStatus(RServer::Busy); setCurrentExpression(expr); expr->std_buffer.clear(); expr->err_buffer.clear(); ReturnCode returnCode=RServer::SuccessCode; QString returnText; QStringList neededFiles; //Code to evaluate an R function (taken from RInside library) ParseStatus status; SEXP cmdSexp, cmdexpr = R_NilValue; SEXP result; int i, errorOccurred; QByteArray memBuf; memBuf.append(cmd.toUtf8()); PROTECT(cmdSexp = allocVector(STRSXP, 1)); SET_STRING_ELT(cmdSexp, 0, mkChar((char*)memBuf.data())); cmdexpr = PROTECT(R_ParseVector(cmdSexp, -1, &status, R_NilValue)); switch (status) { case PARSE_OK: qDebug()<<"PARSING "< 1 */ for (i = 0; i < length(cmdexpr); ++i) { result = R_tryEval(VECTOR_ELT(cmdexpr, i), nullptr, &errorOccurred); if (errorOccurred) { qDebug()<<"Error occurred."; break; } // TODO: multiple results } memBuf.clear(); break; case PARSE_INCOMPLETE: /* need to read another line */ qDebug()<<"parse incomplete.."; break; case PARSE_NULL: qDebug()<<"ParseStatus is null: "<std_buffer<<" err: "<err_buffer; //if the command didn't print anything on its own, print the result //TODO: handle some known result types like lists, matrices separately // to make the output look better, by using html (tables etc.) if(expr->std_buffer.isEmpty()&&expr->err_buffer.isEmpty()) { qDebug()<<"printing result..."; SEXP count=PROTECT(R_tryEval(lang2(install("length"),result),nullptr,&errorOccurred)); // TODO: error checks if (*INTEGER(count)==0) qDebug() << "no result, so show nothing"; else Rf_PrintValue(result); UNPROTECT(1); } setCurrentExpression(nullptr); //is this save? if(!expr->err_buffer.isEmpty()) { returnCode=RServer::ErrorCode; returnText=expr->err_buffer; } else { returnCode=RServer::SuccessCode; returnText=expr->std_buffer; } }else { returnCode=RServer::ErrorCode; returnText=i18n("Error Parsing Command"); } if(internal) { qDebug()<<"internal result: "<hasOtherResults=true; newPlotDevice(); neededFiles<hasOtherResults) emit expressionFinished(returnCode, returnText); else showFiles(neededFiles); setStatus(Idle); } void RServer::completeCommand(const QString& cmd) { // setStatus(RServer::Busy); // TODO: is static okay? guess RServer is a singletone, but ... // TODO: error handling? // TODO: investigate encoding problem // TODO: propage the flexibility of token selection upward // TODO: what if install() fails? investigate // TODO: investigate why errors break the whole foodchain of RServer callbacks in here static SEXP comp_env=R_FindNamespace(mkString("utils")); static SEXP tokenizer_func=install(".guessTokenFromLine"); static SEXP linebuffer_func=install(".assignLinebuffer"); static SEXP buffer_end_func=install(".assignEnd"); static SEXP complete_func=install(".completeToken"); static SEXP retrieve_func=install(".retrieveCompletions"); /* Setting buffer parameters */ int errorOccurred=0; // TODO: error cheks, too lazy to do it now R_tryEval(lang2(linebuffer_func,mkString(cmd.toUtf8().data())),comp_env,&errorOccurred); R_tryEval(lang2(buffer_end_func,ScalarInteger(cmd.size())),comp_env,&errorOccurred); /* Passing the tokenizing work to professionals */ SEXP token=PROTECT(R_tryEval(lang1(tokenizer_func),comp_env,&errorOccurred)); /* Doing the actual stuff */ R_tryEval(lang1(complete_func),comp_env,&errorOccurred); SEXP completions=PROTECT(R_tryEval(lang1(retrieve_func),comp_env,&errorOccurred)); /* Populating the list of completions */ QStringList completionOptions; for (int i=0;i true + + + true + diff --git a/src/backends/R/rvariablemodel.cpp b/src/backends/R/rvariablemodel.cpp index bfde75de..44d3ad6b 100644 --- a/src/backends/R/rvariablemodel.cpp +++ b/src/backends/R/rvariablemodel.cpp @@ -1,75 +1,80 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2018 Nikita Sirgienko */ #include "rvariablemodel.h" #include "rsession.h" using namespace Cantor; RVariableModel::RVariableModel(RSession* session): DefaultVariableModel(session) { } void RVariableModel::update() { static_cast(session())->updateSymbols(this); } void RVariableModel::parseResult(const QStringList& names, const QStringList& values, const QStringList& funcs) { QList vars; - for (int i = 0; i < names.size(); i++) - vars.append(Variable{names[i], values[i]}); + if (!values.isEmpty()) // Variables management disabled + for (int i = 0; i < names.size(); i++) + vars.append(Variable{names[i], values[i]}); + else + for (int i = 0; i < names.size(); i++) + vars.append(Variable{names[i], QString()}); + setVariables(vars); // Handle functions QStringList addedFuncs; QStringList removedFuncs; int i = 0; while (i < m_functions.size()) if (!funcs.contains(m_functions[i])) { removedFuncs << m_functions[i]; m_functions.removeAt(i); } else i++; for (const QString newFunc : funcs) if(!m_functions.contains(newFunc)) { addedFuncs << newFunc; m_functions << newFunc; } if (!addedFuncs.isEmpty()) emit functionsAdded(addedFuncs); if (!removedFuncs.isEmpty()) emit functionsRemoved(removedFuncs); } void RVariableModel::clearFunctions() { emit functionsRemoved(m_functions); m_functions.clear(); } diff --git a/src/backends/R/settings.ui b/src/backends/R/settings.ui index 769643c1..b9316bae 100644 --- a/src/backends/R/settings.ui +++ b/src/backends/R/settings.ui @@ -1,51 +1,61 @@ RSettingsBase 0 0 414 231 Path to local documentation: Integrate Plots in Worksheet + + + + Let Cantor follow the creation/destruction of variables + + + Enable Variable Management + + + Scripts to autorun diff --git a/src/backends/maxima/maximavariablemodel.cpp b/src/backends/maxima/maximavariablemodel.cpp index 93db37e2..ba7c0dfa 100644 --- a/src/backends/maxima/maximavariablemodel.cpp +++ b/src/backends/maxima/maximavariablemodel.cpp @@ -1,230 +1,235 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2012 Alexander Rieder */ #include "maximavariablemodel.h" #include "maximasession.h" #include "maximaexpression.h" #include "textresult.h" #include "latexresult.h" #include #include +#include "settings.h" + //command used to inspect a maxima variable. %1 is the name of that variable const QString MaximaVariableModel::inspectCommand=QLatin1String(":lisp($disp $%1)"); const QString MaximaVariableModel::variableInspectCommand=QLatin1String(":lisp(cantor-inspect $%1)"); MaximaVariableModel::MaximaVariableModel( MaximaSession* session) : Cantor::DefaultVariableModel(session), m_variableExpression(nullptr), m_functionExpression(nullptr) { } void MaximaVariableModel::clearFunctions() { emit functionsRemoved(functionNames()); m_functions.clear(); } void MaximaVariableModel::update() { if (!m_variableExpression) { qDebug()<<"checking for new variables"; const QString& cmd1=variableInspectCommand.arg(QLatin1String("values")); m_variableExpression = session()->evaluateExpression(cmd1, Cantor::Expression::FinishingBehavior::DoNotDelete, true); connect(m_variableExpression, &Cantor::Expression::statusChanged, this, &MaximaVariableModel::parseNewVariables); } if (!m_functionExpression) { qDebug()<<"checking for new functions"; const QString& cmd2=inspectCommand.arg(QLatin1String("functions")); m_functionExpression = session()->evaluateExpression(cmd2, Cantor::Expression::FinishingBehavior::DoNotDelete, true); connect(m_functionExpression, &Cantor::Expression::statusChanged, this, &MaximaVariableModel::parseNewFunctions); } } QList parse(MaximaExpression* expr) { if(!expr || (expr->status()!=Cantor::Expression::Done && expr->errorMessage() != QLatin1String("$DONE")) || expr->results().isEmpty()) { return QList(); } //for parsing of names and values below (old code) we need to combine multiple results back to one string QString text; for (auto* result : expr->results()) { if(result->type()==Cantor::TextResult::Type) text += dynamic_cast(result)->plain(); else if(expr->result()->type()==Cantor::LatexResult::Type) text += dynamic_cast(result)->plain(); } const int nameIndex=text.indexOf(QLatin1Char(']')); QString namesString=text.left(nameIndex); //namesString.chop(1); namesString=namesString.mid(1); namesString=namesString.trimmed(); qDebug()<<"variable names: "<(); QStringList variableNames; QString valuesString; bool hasValues = false; QStringList variableValues; if ( namesString.contains(QLatin1Char(')')) ) { //function definition(s): e.g //text = "[f1(x),f2(x,y),f3(x,y,z)]\n$DONE" //nameString = f1(x),f2(x,y),f3(x,y,z) //variableString = "\n$DONE" variableNames = namesString.split(QLatin1String("),")); } else { //variable definition(s): e.g. //text = "[a,b]\n1\n\"-cantor-value-separator-\"\n2\n\"-cantor-value-separator-\"\n($A $B)" //nameString = "[a,b]" //variableString = "\n1\n\"-cantor-value-separator-\"\n2\n\"-cantor-value-separator-\"\n($A $B)" variableNames = namesString.split(QLatin1Char(',')); - valuesString = text.mid(nameIndex+1).trimmed(); - valuesString = valuesString.remove(QLatin1String("\n")); //lists with many elements have line breaks, remove them - variableValues = valuesString.split(QLatin1String("\"-cantor-value-separator-\"")); - hasValues = variableValues.isEmpty(); + if (MaximaSettings::self()->variableManagement()) + { + valuesString = text.mid(nameIndex+1).trimmed(); + valuesString = valuesString.remove(QLatin1String("\n")); //lists with many elements have line breaks, remove them + variableValues = valuesString.split(QLatin1String("\"-cantor-value-separator-\"")); + hasValues = variableValues.isEmpty(); + } } qDebug()< variables; variables.reserve(variableNames.size()); for(int i=0;ii) { var.value=variableValues.at(i).trimmed(); var.value=var.value.remove(QLatin1String("\n")); //lists with many elements have line breaks, remove them } else var.value=QLatin1String("unknown"); variables< newVars=parse(static_cast(m_variableExpression)); setVariables(newVars); //the expression is not needed anymore m_variableExpression->deleteLater(); m_variableExpression = nullptr; } void MaximaVariableModel::parseNewFunctions(Cantor::Expression::Status status) { if (status != Cantor::Expression::Done && status != Cantor::Expression::Error) return; qDebug()<<"parsing functions"; // List of variables? QList newFuncs=parse(static_cast(m_functionExpression)); QStringList addedFuncs; QStringList removedFuncs; //remove the old variables int i = 0; while (i < m_functions.size()) { //check if this var is present in the new variables bool found=false; for (const Variable& func : newFuncs) if(m_functions[i] == func.name) { found=true; break; } if(!found) { removedFuncs<deleteLater(); m_functionExpression = nullptr; emit functionsAdded(addedFuncs); emit functionsRemoved(removedFuncs); } MaximaSession* MaximaVariableModel::maximaSession() { return static_cast (session()); } QStringList MaximaVariableModel::functionNames(bool stripParameters) { QStringList names; for (const QString func: m_functions) { QString name=func; if(stripParameters) { name=name.left(name.lastIndexOf(QLatin1Char('('))); } names< This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "octavebackend.h" #include "octavesession.h" #include "octaveextensions.h" #include "settings.h" #include "cantor_macros.h" #include #include #include "ui_settings.h" OctaveBackend::OctaveBackend(QObject* parent, const QList& args): Backend(parent, args) { new OctaveHistoryExtension(this); new OctaveScriptExtension(this); new OctavePlotExtension(this); new OctaveLinearAlgebraExtension(this); new OctaveVariableManagementExtension(this); new OctavePackagingExtension(this); } QString OctaveBackend::id() const { return QLatin1String("octave"); } QString OctaveBackend::version() const { return QLatin1String("4.0 and 4.2"); } Cantor::Backend::Capabilities OctaveBackend::capabilities() const { - return SyntaxHighlighting | Completion | SyntaxHelp | VariableManagement; + Cantor::Backend::Capabilities cap= + SyntaxHighlighting| + Completion | + SyntaxHelp; + if (OctaveSettings::self()->variableManagement()) + cap |= VariableManagement; + return cap; } Cantor::Session* OctaveBackend::createSession() { return new OctaveSession(this); } bool OctaveBackend::requirementsFullfilled() const { return QFileInfo(OctaveSettings::path().toLocalFile()).isExecutable(); } QUrl OctaveBackend::helpUrl() const { const QUrl& localDoc = OctaveSettings::self()->localDoc(); if (!localDoc.isEmpty()) return localDoc; else return QUrl(i18nc("the url to the documentation of Octave, please check if there is a translated version (currently Czech and Japanese) and use the correct url", "http://www.gnu.org/software/octave/doc/interpreter/")); } QString OctaveBackend::description() const { return i18n("GNU Octave is a high-level language, primarily intended for numerical computations.
" "It provides a convenient command line interface for solving linear and nonlinear problems numerically, and for performing other numerical experiments using a language that is mostly compatible with Matlab."); } QWidget* OctaveBackend::settingsWidget(QWidget* parent) const { QWidget* widget = new QWidget(parent); Ui::OctaveSettingsBase ui; ui.setupUi(widget); return widget; } KConfigSkeleton* OctaveBackend::config() const { return OctaveSettings::self(); } K_PLUGIN_FACTORY_WITH_JSON(octavebackend, "octavebackend.json", registerPlugin();) #include "octavebackend.moc" diff --git a/src/backends/octave/octavebackend.kcfg b/src/backends/octave/octavebackend.kcfg index b8d7014a..da9b14d9 100644 --- a/src/backends/octave/octavebackend.kcfg +++ b/src/backends/octave/octavebackend.kcfg @@ -1,24 +1,28 @@ QStandardPaths QUrl::fromLocalFile(QStandardPaths::findExecutable( QLatin1String("octave-cli") )) true + + + true + diff --git a/src/backends/octave/octavevariablemodel.cpp b/src/backends/octave/octavevariablemodel.cpp index fcfa8819..69e9243a 100644 --- a/src/backends/octave/octavevariablemodel.cpp +++ b/src/backends/octave/octavevariablemodel.cpp @@ -1,88 +1,92 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2018 Nikita Sirgienko */ #include "octavevariablemodel.h" #include "octavesession.h" #include "textresult.h" #include +#include "settings.h" + using namespace Cantor; OctaveVariableModel::OctaveVariableModel(OctaveSession* session): DefaultVariableModel(session), m_expr(nullptr) { } void OctaveVariableModel::update() { static const QString& cmd = QLatin1String( "printf('__cantor_delimiter_line__\\n');" "__cantor_list__ = who();" "for __cantor_index__ = 1:length(__cantor_list__)" " __cantor_varname__ = char(__cantor_list__{__cantor_index__});" " printf([__cantor_varname__ '\\n']);" " eval(['disp(' __cantor_varname__ ')']);" " printf('__cantor_delimiter_line__\\n')" "endfor;" "clear __cantor_list__;" "clear __cantor_index__;" "clear __cantor_varname__;" ); if (m_expr) return; m_expr = session()->evaluateExpression(cmd, Expression::FinishingBehavior::DoNotDelete, true); connect(m_expr, &Expression::statusChanged, this, &OctaveVariableModel::parseNewVariables); } void OctaveVariableModel::parseNewVariables(Expression::Status status) { switch(status) { case Expression::Status::Done: { static const QLatin1String delimiter("__cantor_delimiter_line__"); // Result always must be, if we done, so don't check it QString text = static_cast(m_expr->result())->plain(); const QStringList& lines = text.split(delimiter, QString::SkipEmptyParts); QList vars; for (QString line : lines) { line = line.trimmed(); const QString& name = line.section(QLatin1String("\n"), 0, 0); - const QString& value = line.section(QLatin1String("\n"), 1); + QString value; + if (OctaveSettings::self()->variableManagement()) + value = line.section(QLatin1String("\n"), 1); vars << Variable{name, value}; } setVariables(vars); break; } default: return; } m_expr->deleteLater(); m_expr = nullptr; } diff --git a/src/backends/octave/settings.ui b/src/backends/octave/settings.ui index e4fa0e06..b558ff11 100644 --- a/src/backends/octave/settings.ui +++ b/src/backends/octave/settings.ui @@ -1,85 +1,95 @@ OctaveSettingsBase 0 0 400 300 Path to Octave: Path to local documentation: Integrate Plots in Worksheet + + + + Let Cantor follow the creation/destruction of variables + + + Enable Variable Management + + + Scripts to autorun Qt::Vertical 20 40 KUrlRequester QFrame
kurlrequester.h
diff --git a/src/backends/python/pythonbackend.cpp b/src/backends/python/pythonbackend.cpp index 5191ee63..18dce4f7 100644 --- a/src/backends/python/pythonbackend.cpp +++ b/src/backends/python/pythonbackend.cpp @@ -1,62 +1,52 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2012 Filipe Saraiva */ #include "pythonbackend.h" #include "pythonsession.h" #include "pythonextensions.h" #include "ui_settings.h" #include #include PythonBackend::PythonBackend(QObject* parent, const QList& args) : Cantor::Backend(parent, args) { qDebug()<<"Creating PythonBackend"; new PythonLinearAlgebraExtension(this); new PythonPackagingExtension(this); new PythonPlotExtension(this); new PythonScriptExtension(this); new PythonVariableManagementExtension(this); } PythonBackend::~PythonBackend() { qDebug()<<"Destroying PythonBackend"; } -Cantor::Backend::Capabilities PythonBackend::capabilities() const -{ - qDebug()<<"Requesting capabilities of PythonSession"; - - return Cantor::Backend::SyntaxHighlighting | - Cantor::Backend::Completion | - Cantor::Backend::SyntaxHelp | - Cantor::Backend::VariableManagement; -} - QWidget* PythonBackend::settingsWidget(QWidget* parent) const { QWidget* widget=new QWidget(parent); Ui::PythonSettingsBase s; s.setupUi(widget); return widget; } diff --git a/src/backends/python/pythonbackend.h b/src/backends/python/pythonbackend.h index 16c10fd8..8eb2679e 100644 --- a/src/backends/python/pythonbackend.h +++ b/src/backends/python/pythonbackend.h @@ -1,41 +1,41 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2012 Filipe Saraiva */ #ifndef _PYTHONBACKEND_H #define _PYTHONBACKEND_H #include "backend.h" #include class CANTOR_PYTHONBACKEND_EXPORT PythonBackend : public Cantor::Backend { Q_OBJECT public: explicit PythonBackend(QObject* parent = nullptr, const QList& args = QList()); ~PythonBackend() override; - Cantor::Backend::Capabilities capabilities() const override; - QWidget* settingsWidget(QWidget* parent) const override; + KConfigSkeleton* config() const override = 0; + Cantor::Backend::Capabilities capabilities() const override = 0; }; #endif /* _PYTHONBACKEND_H */ diff --git a/src/backends/python/pythonserver.cpp b/src/backends/python/pythonserver.cpp index 07c5eccc..fc7af615 100644 --- a/src/backends/python/pythonserver.cpp +++ b/src/backends/python/pythonserver.cpp @@ -1,202 +1,205 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2015 Minh Ngo */ #include "pythonserver.h" #include PythonServer::PythonServer(QObject* parent) : QObject(parent), m_pModule(nullptr) { } namespace { QString pyObjectToQString(PyObject* obj) { #if PY_MAJOR_VERSION == 3 return QString::fromUtf8(PyUnicode_AsUTF8(obj)); #elif PY_MAJOR_VERSION == 2 return QString::fromLocal8Bit(PyString_AsString(obj)); #else #warning Unknown Python version #endif } } void PythonServer::login() { Py_InspectFlag = 1; Py_Initialize(); m_pModule = PyImport_AddModule("__main__"); filePath = QStringLiteral("python_cantor_worksheet"); } void PythonServer::runPythonCommand(const QString& command) const { PyObject* py_dict = PyModule_GetDict(m_pModule); const char* prepareCommand = "import sys;\n"\ "class CatchOutPythonBackend:\n"\ " def __init__(self):\n"\ " self.value = ''\n"\ " def write(self, txt):\n"\ " self.value += txt\n"\ "outputPythonBackend = CatchOutPythonBackend()\n"\ "errorPythonBackend = CatchOutPythonBackend()\n"\ "sys.stdout = outputPythonBackend\n"\ "sys.stderr = errorPythonBackend\n"; PyRun_SimpleString(prepareCommand); #if PY_MAJOR_VERSION == 3 PyObject* compile = Py_CompileString(command.toStdString().c_str(), filePath.toStdString().c_str(), Py_single_input); // There are two reasons for the error: // 1) This code is not single expression, so we can't compile this with flag Py_single_input // 2) There are errors in the code if (PyErr_Occurred()) { PyErr_Clear(); // Try to recompile code as sequence of expressions compile = Py_CompileString(command.toStdString().c_str(), filePath.toStdString().c_str(), Py_file_input); if (PyErr_Occurred()) { // We now know, that we have a syntax error, so print the traceback and exit PyErr_PrintEx(0); return; } } PyEval_EvalCode(compile, py_dict, py_dict); #elif PY_MAJOR_VERSION == 2 // Python 2.X don't check, that input string contains only one expression. // So for checking this, we compile string as file and as single expression and compare bytecode // FIXME? PyObject* codeFile = Py_CompileString(command.toStdString().c_str(), filePath.toStdString().c_str(), Py_file_input); if (PyErr_Occurred()) { PyErr_PrintEx(0); return; } PyObject* codeSingle = Py_CompileString(command.toStdString().c_str(), filePath.toStdString().c_str(), Py_single_input); if (PyErr_Occurred()) { // We have error with Py_single_input, but haven't error with Py_file_input // So, the code can't be compiled as singel input -> use file input right away PyErr_Clear(); PyEval_EvalCode((PyCodeObject*)codeFile, py_dict, py_dict); } else { PyObject* bytecode1 = ((PyCodeObject*)codeSingle)->co_code; PyObject* bytecode2 = ((PyCodeObject*)codeFile)->co_code; if (PyObject_Length(bytecode1) >= PyObject_Length(bytecode2)) { PyEval_EvalCode((PyCodeObject*)codeSingle, py_dict, py_dict); } else { PyEval_EvalCode((PyCodeObject*)codeFile, py_dict, py_dict); } } #else #warning Unknown Python version #endif if (PyErr_Occurred()) PyErr_PrintEx(0); } QString PythonServer::getError() const { PyObject *errorPython = PyObject_GetAttrString(m_pModule, "errorPythonBackend"); PyObject *error = PyObject_GetAttrString(errorPython, "value"); return pyObjectToQString(error); } QString PythonServer::getOutput() const { PyObject *outputPython = PyObject_GetAttrString(m_pModule, "outputPythonBackend"); PyObject *output = PyObject_GetAttrString(outputPython, "value"); return pyObjectToQString(output); } void PythonServer::setFilePath(const QString& path) { this->filePath = path; PyRun_SimpleString(("__file__ = '"+path.toStdString()+"'").c_str()); } -QString PythonServer::variables() const +QString PythonServer::variables(bool parseValue) const { // FIXME: This code allows get full form of numpy array, but for big arrays it's could cause performonce problems // especially for displaying in variables panel // So, uncomment this, when fix this problem /* "try: \n" " import numpy \n" " __cantor_numpy_internal__ = numpy.get_printoptions()['threshold'] \n" " numpy.set_printoptions(threshold=100000000) \n" "except ModuleNotFoundError: \n" " pass \n" "try: \n" " import numpy \n" " numpy.set_printoptions(threshold=__cantor_numpy_internal__) \n" " del __cantor_numpy_internal__ \n" "except ModuleNotFoundError: \n" " pass \n" */ PyRun_SimpleString("__tmp_globals__ = globals()"); PyObject* globals = PyObject_GetAttrString(m_pModule,"__tmp_globals__"); PyObject *key, *value; Py_ssize_t pos = 0; QStringList vars; const QChar sep(30); // INFORMATION SEPARATOR TWO while (PyDict_Next(globals, &pos, &key, &value)) { const QString& keyString = pyObjectToQString(key); if (keyString.startsWith(QLatin1String("__"))) continue; if (keyString == QLatin1String("CatchOutPythonBackend") || keyString == QLatin1String("errorPythonBackend") || keyString == QLatin1String("outputPythonBackend")) continue; if (PyModule_Check(value)) continue; if (PyFunction_Check(value)) continue; if (PyType_Check(value)) continue; - const QString& valueString = pyObjectToQString(PyObject_Repr(value)); + QString valueString; + if (parseValue) + valueString = pyObjectToQString(PyObject_Repr(value)); + vars.append(keyString + QChar(31) + valueString); } return vars.join(sep); } diff --git a/src/backends/python/pythonserver.h b/src/backends/python/pythonserver.h index b52bc85a..a36c2ee5 100644 --- a/src/backends/python/pythonserver.h +++ b/src/backends/python/pythonserver.h @@ -1,48 +1,48 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2015 Minh Ngo */ #ifndef _PYTHONSERVER_H #define _PYTHONSERVER_H #include #include struct _object; using PyObject = _object; class PythonServer : public QObject { Q_OBJECT public: explicit PythonServer(QObject* parent = nullptr); public Q_SLOTS: Q_SCRIPTABLE void login(); Q_SCRIPTABLE void setFilePath(const QString& path); Q_SCRIPTABLE void runPythonCommand(const QString& command) const; Q_SCRIPTABLE QString getOutput() const; Q_SCRIPTABLE QString getError() const; - Q_SCRIPTABLE QString variables() const; + Q_SCRIPTABLE QString variables(bool parseValue) const; private: PyObject* m_pModule; QString filePath; }; #endif diff --git a/src/backends/python/pythonsession.h b/src/backends/python/pythonsession.h index 0129ba9e..ecfa4571 100644 --- a/src/backends/python/pythonsession.h +++ b/src/backends/python/pythonsession.h @@ -1,98 +1,99 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2012 Filipe Saraiva Copyright (C) 2015 Minh Ngo */ #ifndef _PYTHONSESSION_H #define _PYTHONSESSION_H #include "session.h" #include #include class PythonExpression; class PythonVariableModel; class KDirWatch; class QDBusInterface; class KProcess; class CANTOR_PYTHONBACKEND_EXPORT PythonSession : public Cantor::Session { Q_OBJECT public: PythonSession(Cantor::Backend* backend, int pythonVersion, const QString serverName, const QString DbusChannelName); ~PythonSession() override = default; void login() override; void logout() override; void interrupt() override; void runExpression(PythonExpression* expr); Cantor::Expression* evaluateExpression(const QString& command, Cantor::Expression::FinishingBehavior behave = Cantor::Expression::FinishingBehavior::DoNotDelete, bool internal = false) override; Cantor::CompletionObject* completionFor(const QString& command, int index=-1) override; QSyntaxHighlighter* syntaxHighlighter(QObject* parent) override; QAbstractItemModel* variableModel() override; void setWorksheetPath(const QString& path) override; virtual bool integratePlots() const = 0; virtual QStringList autorunScripts() const = 0; + virtual bool variableManagement() const = 0; private: PythonVariableModel* m_variableModel; QList m_runningExpressions; PythonExpression* m_currentExpression; QDBusInterface* m_pIface; KProcess* m_pProcess; QString serverName; QString DbusChannelName; QString worksheetPath; int m_pythonVersion; bool m_needUpdate; protected: QString m_output; QString m_error; private: void getPythonCommandOutput(const QString& commandProcessing); QString identifyPythonModule(const QString& command) const; QString identifyVariableModule(const QString& command) const; bool identifyKeywords(const QString& command); void runPythonCommand(const QString& command) const; QString getOutput() const; QString getError() const; virtual void readExpressionOutput(const QString& commandProcessing); protected: void updateOutput(); private Q_SLOTS: void readOutput(const QString& commandProcessing); void expressionFinished(); }; #endif /* _PYTHONSESSION_H */ diff --git a/src/backends/python/pythonvariablemodel.cpp b/src/backends/python/pythonvariablemodel.cpp index b3939cd6..cb934a33 100644 --- a/src/backends/python/pythonvariablemodel.cpp +++ b/src/backends/python/pythonvariablemodel.cpp @@ -1,61 +1,62 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2018 Nikita Sirgienko */ #include "pythonvariablemodel.h" #include "pythonsession.h" #include "textresult.h" #include #include #include #include using namespace Cantor; PythonVariableModel::PythonVariableModel(PythonSession* session): DefaultVariableModel(session), m_pIface(nullptr) { } void PythonVariableModel::setPythonServer(QDBusInterface* pIface) { m_pIface = pIface; } void PythonVariableModel::update() { if (!m_pIface) return; - const QString& data = QDBusReply(m_pIface->call(QString::fromLatin1("variables"))).value(); + bool variableManagement = static_cast(session())->variableManagement(); + const QString& data = QDBusReply(m_pIface->call(QString::fromLatin1("variables"), variableManagement)).value(); const QStringList& records = data.split(QChar(30), QString::SkipEmptyParts); QList variables; for (const QString& record : records) { const QString& name = record.section(QChar(31), 0, 0); const QString& value = record.section(QChar(31), 1, 1); variables << Variable{name, value}; } setVariables(variables); } diff --git a/src/backends/python/settings.ui b/src/backends/python/settings.ui index 7cbd5d2c..ac787f0b 100644 --- a/src/backends/python/settings.ui +++ b/src/backends/python/settings.ui @@ -1,71 +1,81 @@ PythonSettingsBase 0 0 400 300 Path to local documentation: Integrate Plots in Worksheet + + + + + Let Cantor follow the creation/destruction of variables + + + Enable Variable Management + + Scripts to autorun Qt::Vertical 20 40 KUrlRequester QFrame
kurlrequester.h
diff --git a/src/backends/python2/python2backend.cpp b/src/backends/python2/python2backend.cpp index 24d8767b..87c9c052 100644 --- a/src/backends/python2/python2backend.cpp +++ b/src/backends/python2/python2backend.cpp @@ -1,78 +1,93 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2014, 2015 Minh Ngo */ #include "python2backend.h" #include "python2session.h" #include "cantor_macros.h" #include "settings.h" #include Python2Backend::Python2Backend(QObject* parent, const QList args) : PythonBackend(parent, args) { setObjectName(QLatin1String("python2backend")); // Because the plugin may not have been loaded with // ExportExternalSymbols, we load the python symbols again // to make sure that python modules such as numpy see them // (see bug #330032) QLibrary pythonLib(QLatin1String("python2.7")); pythonLib.setLoadHints(QLibrary::ExportExternalSymbolsHint); pythonLib.load(); } Cantor::Session* Python2Backend::createSession() { return new Python2Session(this); } QString Python2Backend::id() const { return QLatin1String("python2"); } QString Python2Backend::version() const { return QLatin1String("2.7"); } +Cantor::Backend::Capabilities Python2Backend::capabilities() const +{ + qDebug()<<"Requesting capabilities of Python3Session"; + + Backend::Capabilities cap = + Cantor::Backend::SyntaxHighlighting | + Cantor::Backend::Completion | + Cantor::Backend::SyntaxHelp; + + if(PythonSettings::variableManagement()) + cap |= Cantor::Backend::VariableManagement; + + return cap; +} + QUrl Python2Backend::helpUrl() const { const QUrl& localDoc = PythonSettings::self()->localDoc(); if (!localDoc.isEmpty()) return localDoc; else return QUrl(i18nc("the url to the documentation Python 2", "http://docs.python.org/2/")); } QString Python2Backend::description() const { return i18n("

Python is a remarkably powerful dynamic programming language that is used in a wide variety of application domains. " \ "There are several Python packages to scientific programming.

" \ "

This backend supports Python 2.

"); } KConfigSkeleton* Python2Backend::config() const { return PythonSettings::self(); } K_PLUGIN_FACTORY_WITH_JSON(python2backend, "python2backend.json", registerPlugin();) #include "python2backend.moc" diff --git a/src/backends/python2/python2backend.h b/src/backends/python2/python2backend.h index 1d910c75..13117b75 100644 --- a/src/backends/python2/python2backend.h +++ b/src/backends/python2/python2backend.h @@ -1,42 +1,43 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2014, 2015 Minh Ngo */ #ifndef _PYTHON2BACKEND_H #define _PYTHON2BACKEND_H #include "../python/pythonbackend.h" class Python2Backend : public PythonBackend { Q_OBJECT public: explicit Python2Backend(QObject* parent = nullptr, const QList args = QList()); Cantor::Session* createSession() override; QString id() const override; QString version() const override; + Cantor::Backend::Capabilities capabilities() const override; QUrl helpUrl() const override; QString description() const override; KConfigSkeleton* config() const override; }; #endif diff --git a/src/backends/python2/python2backend.kcfg b/src/backends/python2/python2backend.kcfg index d461f16e..12afafd9 100644 --- a/src/backends/python2/python2backend.kcfg +++ b/src/backends/python2/python2backend.kcfg @@ -1,19 +1,23 @@ false + + + true + diff --git a/src/backends/python2/python2session.cpp b/src/backends/python2/python2session.cpp index 9ff5c69d..7ed92280 100644 --- a/src/backends/python2/python2session.cpp +++ b/src/backends/python2/python2session.cpp @@ -1,46 +1,51 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2015 Minh Ngo */ #include "python2session.h" #include "settings.h" #include "../python/pythonexpression.h" #include "../python/pythonkeywords.h" #include #include #include #include #include Python2Session::Python2Session(Cantor::Backend* backend) : PythonSession(backend, 2, QLatin1String("cantor_python2server"), QLatin1String("org.kde.Cantor.Python2")) { } bool Python2Session::integratePlots() const { return PythonSettings::integratePlots(); } QStringList Python2Session::autorunScripts() const { return PythonSettings::autorunScripts(); } + +bool Python2Session::variableManagement() const +{ + return PythonSettings::variableManagement(); +} diff --git a/src/backends/python2/python2session.h b/src/backends/python2/python2session.h index 40004801..3a54af93 100644 --- a/src/backends/python2/python2session.h +++ b/src/backends/python2/python2session.h @@ -1,35 +1,36 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2015 Minh Ngo */ #ifndef _PYTHON2SESSION_H #define _PYTHON2SESSION_H #include "../python/pythonsession.h" class Python2Session : public PythonSession { public: explicit Python2Session(Cantor::Backend* backend); bool integratePlots() const override; QStringList autorunScripts() const override; + bool variableManagement() const override; }; #endif diff --git a/src/backends/python3/python3backend.cpp b/src/backends/python3/python3backend.cpp index 31f11c50..3105b606 100644 --- a/src/backends/python3/python3backend.cpp +++ b/src/backends/python3/python3backend.cpp @@ -1,71 +1,86 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2014, 2015 Minh Ngo */ #include "python3backend.h" #include "python3session.h" #include "cantor_macros.h" #include "settings.h" #include Python3Backend::Python3Backend(QObject* parent, const QList& args) : PythonBackend(parent, args) { setObjectName(QLatin1String("python3backend")); } Cantor::Session* Python3Backend::createSession() { return new Python3Session(this); } QString Python3Backend::id() const { return QLatin1String("python3"); } QString Python3Backend::version() const { return QLatin1String("3.6"); } +Cantor::Backend::Capabilities Python3Backend::capabilities() const +{ + qDebug()<<"Requesting capabilities of Python3Session"; + + Backend::Capabilities cap = + Cantor::Backend::SyntaxHighlighting | + Cantor::Backend::Completion | + Cantor::Backend::SyntaxHelp; + + if(PythonSettings::variableManagement()) + cap |= Cantor::Backend::VariableManagement; + + return cap; +} + QUrl Python3Backend::helpUrl() const { const QUrl& localDoc = PythonSettings::self()->localDoc(); if (!localDoc.isEmpty()) return localDoc; else return QUrl(i18nc("the url to the documentation Python 3", "http://docs.python.org/3/")); } QString Python3Backend::description() const { return i18n("

Python is a remarkably powerful dynamic programming language that is used in a wide variety of application domains. " \ "There are several Python packages to scientific programming.

" \ "

This backend supports Python 3.

"); } KConfigSkeleton* Python3Backend::config() const { return PythonSettings::self(); } K_PLUGIN_FACTORY_WITH_JSON(python3backend, "python3backend.json", registerPlugin();) #include "python3backend.moc" diff --git a/src/backends/python3/python3backend.h b/src/backends/python3/python3backend.h index f0ee1339..0ca67ea1 100644 --- a/src/backends/python3/python3backend.h +++ b/src/backends/python3/python3backend.h @@ -1,41 +1,42 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2014, 2015 Minh Ngo */ #ifndef _PYTHON3BACKEND_H #define _PYTHON3BACKEND_H #include "../python/pythonbackend.h" class Python3Backend : public PythonBackend { public: explicit Python3Backend(QObject* parent = nullptr, const QList& args = QList()); Cantor::Session* createSession() override; QString id() const override; QString version() const override; + Cantor::Backend::Capabilities capabilities() const override; QUrl helpUrl() const override; QString description() const override; KConfigSkeleton* config() const override; }; #endif diff --git a/src/backends/python3/python3backend.kcfg b/src/backends/python3/python3backend.kcfg index 3ceb9800..4e9e6daa 100644 --- a/src/backends/python3/python3backend.kcfg +++ b/src/backends/python3/python3backend.kcfg @@ -1,19 +1,23 @@ false + + + true + diff --git a/src/backends/python3/python3session.cpp b/src/backends/python3/python3session.cpp index c33c4a78..81366d00 100644 --- a/src/backends/python3/python3session.cpp +++ b/src/backends/python3/python3session.cpp @@ -1,37 +1,43 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2015 Minh Ngo */ #include "python3session.h" #include "settings.h" Python3Session::Python3Session(Cantor::Backend* backend) : PythonSession(backend, 3, QLatin1String("cantor_python3server"), QLatin1String("org.kde.Cantor.Python3")) { } bool Python3Session::integratePlots() const { return PythonSettings::integratePlots(); } QStringList Python3Session::autorunScripts() const { return PythonSettings::autorunScripts(); } + +bool Python3Session::variableManagement() const +{ + return PythonSettings::variableManagement(); +} + diff --git a/src/backends/python3/python3session.h b/src/backends/python3/python3session.h index 9abe8616..c859ace6 100644 --- a/src/backends/python3/python3session.h +++ b/src/backends/python3/python3session.h @@ -1,35 +1,36 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2015 Minh Ngo */ #ifndef _PYTHON3SESSION_H #define _PYTHON3SESSION_H #include "../python/pythonsession.h" class Python3Session : public PythonSession { public: explicit Python3Session(Cantor::Backend* backend); bool integratePlots() const override; QStringList autorunScripts() const override; + bool variableManagement() const override; }; #endif