diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 32479160..2342eb54 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,105 +1,106 @@ ######################################################################### # Subdirectories ######################################################################### add_subdirectory(lib) +add_subdirectory(scripteditor) include_directories( lib ${CMAKE_CURRENT_BINARY_DIR}/lib) if(BUILD_TESTING) include(ECMMarkAsTest) include_directories( lib/test ) endif(BUILD_TESTING) if(LIBSPECTRE_FOUND) include_directories(${LIBSPECTRE_INCLUDE_DIR}) endif(LIBSPECTRE_FOUND) add_subdirectory(backends) add_subdirectory(assistants) add_subdirectory(xslt) add_subdirectory(panelplugins) #build the config object in a separate library, shared between shell and part kconfig_add_kcfg_files(config_SRCS settings.kcfgc) add_library( cantor_config SHARED ${config_SRCS} ) target_link_libraries( cantor_config KF5::Parts KF5::NewStuff ) install( TARGETS cantor_config ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} ) set(cantor_SRCS main.cpp cantor.cpp backendchoosedialog.cpp ) install(FILES cantor.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR}) ki18n_wrap_ui(cantor_SRCS settings.ui) ki18n_wrap_ui(cantor_SRCS backendchooser.ui) file(GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/../icons/*-apps-cantor.png") ecm_add_app_icon(cantor_SRCS ICONS ${ICONS_SRCS}) add_executable(cantor ${cantor_SRCS}) target_link_libraries(cantor KF5::Parts KF5::NewStuff KF5::ConfigCore KF5::CoreAddons KF5::ConfigGui KF5::Crash KF5::XmlGui cantorlibs cantor_config) ########### install files ############### install(TARGETS cantor ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} ) install( PROGRAMS org.kde.cantor.desktop DESTINATION ${KDE_INSTALL_APPDIR} ) install( FILES cantor_shell.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/cantor ) install( FILES cantor.knsrc DESTINATION ${KDE_INSTALL_CONFDIR} ) ######################################################################### # KPART SECTION ######################################################################### set(cantor_PART_SRCS cantor_part.cpp worksheet.cpp worksheetview.cpp worksheetentry.cpp worksheettextitem.cpp worksheetimageitem.cpp commandentry.cpp textentry.cpp pagebreakentry.cpp imageentry.cpp latexentry.cpp placeholderentry.cpp worksheetcursor.cpp searchbar.cpp actionbar.cpp worksheettoolbutton.cpp imagesettingsdialog.cpp - scripteditorwidget.cpp + scripteditor/scripteditorwidget.cpp resultitem.cpp textresultitem.cpp imageresultitem.cpp animationresultitem.cpp loadedexpression.cpp animation.cpp epsrenderer.cpp ) ki18n_wrap_ui(cantor_PART_SRCS imagesettings.ui) ki18n_wrap_ui(cantor_PART_SRCS standardsearchbar.ui) ki18n_wrap_ui(cantor_PART_SRCS extendedsearchbar.ui) configure_file (config-cantor.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-cantor.h ) kcoreaddons_add_plugin(cantorpart SOURCES ${cantor_PART_SRCS} JSON "cantor_part.json" INSTALL_NAMESPACE ".") set_target_properties(cantorpart PROPERTIES PREFIX "${CMAKE_SHARED_LIBRARY_PREFIX}") target_link_libraries(cantorpart KF5::Parts KF5::NewStuff KF5::TextEditor ${Qt5XmlPatterns_LIBRARIES} KF5::KIOCore KF5::KIOFileWidgets KF5::KIOWidgets Qt5::PrintSupport cantorlibs cantor_config ) if(LIBSPECTRE_FOUND) target_link_libraries(cantorpart ${LIBSPECTRE_LIBRARY}) endif(LIBSPECTRE_FOUND) install( FILES cantor_part.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/cantor ) install( FILES cantor_scripteditor.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/cantor ) diff --git a/src/backends/R/rserver/rserver.cpp b/src/backends/R/rserver/rserver.cpp index e1835274..6b7d44b2 100644 --- a/src/backends/R/rserver/rserver.cpp +++ b/src/backends/R/rserver/rserver.cpp @@ -1,557 +1,560 @@ /* 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 // Not making a member to prevent pulling R headers into rserver.h bool htmlVector(SEXP expr, QTextStream& fp) { // TODO TextResult clamps the newlines, beware // fp << "\n"; // TODO move this to some other place and make configurable fp << QLatin1String(""); fp << QLatin1String(""); int leftOnThisRow=25; for (int i=0; i"); fp << QLatin1String(""); leftOnThisRow=25; } QString cellData; switch (TYPEOF(expr)) { case REALSXP: cellData=QString::number(REAL(expr)[i]); break; case INTSXP: cellData=QString::number(INTEGER(expr)[i]); break; case STRSXP: cellData=QLatin1String(CHAR(STRING_ELT(expr,i))); break; default: return false; } fp << QLatin1String(""); // TODO HTML-safening leftOnThisRow--; } fp << QLatin1String(""); fp << QLatin1String("
[1]
[")+QString::number(i+1)+QLatin1String("]")+cellData+QLatin1String("
"); // fp << ""; return true; } RServer::RServer() : m_isInitialized(false),m_isCompletionAvailable(false) { new RAdaptor(this); QDir dir; dir.mkdir(QDir::tempPath() + QString::fromLatin1("/cantor/rserver-%1").arg(getpid())); m_tmpDir=QDir::tempPath() + QString::fromLatin1("/cantor/rserver-%1").arg(getpid()); 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())),NULL,&errorOccurred); // TODO: error handling else { qDebug()<<(QLatin1String("Script ")+path+QLatin1String(" not found")); // FIXME: or should we throw a messagebox } } qDebug()<<"done initializing"; // FIXME: other way to search symbols, see listSymbols for details listSymbols(); } //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), NULL, &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 spearately // 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),NULL,&errorOccurred)); // TODO: error checks if (*INTEGER(count)==1) Rf_PrintValue(result); else { static int htmlresult_id=0; QString fname=QString::fromLatin1("%1/Rtable%2.html").arg(m_tmpDir,QString::number(htmlresult_id++)); QFile fp(fname); if (fp.open(QIODevice::WriteOnly)) { QTextStream s(&fp); bool canProcess=htmlVector(result,s); fp.close(); if (canProcess) { neededFiles<hasOtherResults=true; } else Rf_PrintValue(result); //In case we do not know yet how to display it } } UNPROTECT(1); } setCurrentExpression(0); //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); // FIXME: Calling this every evaluation is probably ugly listSymbols(); } 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 */ #include "cantor_part.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "worksheet.h" #include "worksheetview.h" #include "searchbar.h" -#include "scripteditorwidget.h" +#include "scripteditor/scripteditorwidget.h" #include "lib/backend.h" #include "lib/extension.h" #include "lib/assistant.h" #include "lib/panelpluginhandler.h" #include "lib/panelplugin.h" #include "lib/worksheetaccess.h" #include "settings.h" //A concrete implementation of the WorksheetAccesssInterface class WorksheetAccessInterfaceImpl : public Cantor::WorksheetAccessInterface { //Q_OBJECT public: WorksheetAccessInterfaceImpl(QObject* parent, Worksheet* worksheet) : WorksheetAccessInterface(parent), m_worksheet(worksheet) { qDebug()<<"new worksheetaccess interface"; connect(worksheet, SIGNAL(sessionChanged()), this, SIGNAL(sessionChanged())); } ~WorksheetAccessInterfaceImpl() override { } QByteArray saveWorksheetToByteArray() Q_DECL_OVERRIDE { return m_worksheet->saveToByteArray(); } void loadWorksheetFromByteArray(QByteArray* data) Q_DECL_OVERRIDE { m_worksheet->load(data); } Cantor::Session* session() Q_DECL_OVERRIDE { return m_worksheet->session(); } // public Q_SLOTS: void evaluate() Q_DECL_OVERRIDE { m_worksheet->evaluate(); } void interrupt() Q_DECL_OVERRIDE { m_worksheet->interrupt(); } private: Worksheet* m_worksheet; }; CantorPart::CantorPart( QWidget *parentWidget, QObject *parent, const QVariantList & args ): KParts::ReadWritePart(parent), m_searchBar(nullptr), m_initProgressDlg(nullptr), m_showProgressDlg(true), m_showBackendHelp(nullptr), m_statusBarBlocked(false) { qDebug()<<"Created a CantorPart"; m_panelHandler=new Cantor::PanelPluginHandler(this); connect(m_panelHandler, SIGNAL(pluginsChanged()), this, SLOT(pluginsChanged())); QString backendName; if(args.isEmpty()) backendName=QLatin1String("null"); else backendName=args.first().toString(); foreach(const QVariant& arg, args) { if (arg.toString() == QLatin1String("--noprogress") ) { qWarning()<<"not showing the progress bar by request"; m_showProgressDlg=false; } } Cantor::Backend* b=Cantor::Backend::createBackend(backendName); if(!b) { KMessageBox::error(parentWidget, i18n("Backend %1 is not installed", backendName), i18n("Error - Cantor")); setWidget(new QWidget(parentWidget)); //fake being modified so the shell won't try to reuse this part ReadWritePart::setModified(true); return; } qDebug()<<"Backend "<name()<<" offers extensions: "<extensions(); QWidget* widget = new QWidget(parentWidget); QVBoxLayout* layout = new QVBoxLayout(widget); m_worksheet=new Worksheet(b, widget); m_worksheetview=new WorksheetView(m_worksheet, widget); m_worksheetview->setEnabled(false); //disable input until the session has successfully logged in and emits the ready signal connect(m_worksheet, SIGNAL(modified()), this, SLOT(setModified())); connect(m_worksheet, SIGNAL(showHelp(const QString&)), this, SIGNAL(showHelp(const QString&))); connect(m_worksheet, SIGNAL(sessionChanged()), this, SLOT(worksheetSessionChanged())); connect(actionCollection(), SIGNAL(inserted(QAction*)), m_worksheet, SLOT(registerShortcut(QAction*))); layout->addWidget(m_worksheetview); // notify the part that this is our internal widget setWidget(widget); Cantor::WorksheetAccessInterface* iface=new WorksheetAccessInterfaceImpl(this, m_worksheet); Q_UNUSED(iface); // create our actions m_worksheet->createActions(actionCollection()); KStandardAction::saveAs(this, SLOT(fileSaveAs()), actionCollection()); m_save = KStandardAction::save(this, SLOT(save()), actionCollection()); m_save->setPriority(QAction::LowPriority); QAction * savePlain=new QAction(i18n("Save Plain Text"), actionCollection()); actionCollection()->addAction(QLatin1String("file_save_plain"), savePlain); savePlain->setIcon(QIcon::fromTheme(QLatin1String("document-save"))); connect(savePlain, SIGNAL(triggered()), this, SLOT(fileSavePlain())); QAction * undo=KStandardAction::undo(m_worksheet, SIGNAL(undo()), actionCollection()); undo->setPriority(QAction::LowPriority); connect(m_worksheet, SIGNAL(undoAvailable(bool)), undo, SLOT(setEnabled(bool))); QAction * redo=KStandardAction::redo(m_worksheet, SIGNAL(redo()), actionCollection()); redo->setPriority(QAction::LowPriority); connect(m_worksheet, SIGNAL(redoAvailable(bool)), redo, SLOT(setEnabled(bool))); QAction * cut=KStandardAction::cut(m_worksheet, SIGNAL(cut()), actionCollection()); cut->setPriority(QAction::LowPriority); connect(m_worksheet, SIGNAL(cutAvailable(bool)), cut, SLOT(setEnabled(bool))); QAction * copy=KStandardAction::copy(m_worksheet, SIGNAL(copy()), actionCollection()); copy->setPriority(QAction::LowPriority); connect(m_worksheet, SIGNAL(copyAvailable(bool)), copy, SLOT(setEnabled(bool))); QAction * paste=KStandardAction::paste(m_worksheet, SIGNAL(paste()), actionCollection()); paste->setPriority(QAction::LowPriority); connect(m_worksheet, SIGNAL(pasteAvailable(bool)), paste, SLOT(setEnabled(bool))); QAction * find=KStandardAction::find(this, SLOT(showSearchBar()), actionCollection()); find->setPriority(QAction::LowPriority); QAction * replace=KStandardAction::replace(this, SLOT(showExtendedSearchBar()), actionCollection()); replace->setPriority(QAction::LowPriority); m_findNext = KStandardAction::findNext(this, SLOT(findNext()), actionCollection()); m_findNext->setEnabled(false); m_findPrev = KStandardAction::findPrev(this, SLOT(findPrev()), actionCollection()); m_findPrev->setEnabled(false); QAction * latexExport=new QAction(i18n("Export to LaTeX"), actionCollection()); actionCollection()->addAction(QLatin1String("file_export_latex"), latexExport); latexExport->setIcon(QIcon::fromTheme(QLatin1String("document-export"))); connect(latexExport, SIGNAL(triggered()), this, SLOT(exportToLatex())); QAction * print = KStandardAction::print(this, SLOT(print()), actionCollection()); print->setPriority(QAction::LowPriority); QAction * printPreview = KStandardAction::printPreview(this, SLOT(printPreview()), actionCollection()); printPreview->setPriority(QAction::LowPriority); KStandardAction::zoomIn(m_worksheetview, SLOT(zoomIn()), actionCollection()); KStandardAction::zoomOut(m_worksheetview, SLOT(zoomOut()), actionCollection()); m_evaluate=new QAction(i18n("Evaluate Worksheet"), actionCollection()); actionCollection()->addAction(QLatin1String("evaluate_worksheet"), m_evaluate); m_evaluate->setIcon(QIcon::fromTheme(QLatin1String("system-run"))); m_evaluate->setShortcut(Qt::CTRL+Qt::Key_E); connect(m_evaluate, SIGNAL(triggered()), this, SLOT(evaluateOrInterrupt())); m_typeset=new KToggleAction(i18n("Typeset using LaTeX"), actionCollection()); m_typeset->setChecked(Settings::self()->typesetDefault()); actionCollection()->addAction(QLatin1String("enable_typesetting"), m_typeset); connect(m_typeset, SIGNAL(toggled(bool)), this, SLOT(enableTypesetting(bool))); m_highlight=new KToggleAction(i18n("Syntax Highlighting"), actionCollection()); m_highlight->setChecked(Settings::self()->highlightDefault()); actionCollection()->addAction(QLatin1String("enable_highlighting"), m_highlight); connect(m_highlight, SIGNAL(toggled(bool)), m_worksheet, SLOT(enableHighlighting(bool))); m_completion=new KToggleAction(i18n("Completion"), actionCollection()); m_completion->setChecked(Settings::self()->completionDefault()); actionCollection()->addAction(QLatin1String("enable_completion"), m_completion); connect(m_completion, SIGNAL(toggled(bool)), m_worksheet, SLOT(enableCompletion(bool))); m_exprNumbering=new KToggleAction(i18n("Line Numbers"), actionCollection()); m_exprNumbering->setChecked(Settings::self()->expressionNumberingDefault()); actionCollection()->addAction(QLatin1String("enable_expression_numbers"), m_exprNumbering); connect(m_exprNumbering, SIGNAL(toggled(bool)), m_worksheet, SLOT(enableExpressionNumbering(bool))); m_animateWorksheet=new KToggleAction(i18n("Animate Worksheet"), actionCollection()); m_animateWorksheet->setChecked(Settings::self()->animationDefault()); actionCollection()->addAction(QLatin1String("enable_animations"), m_animateWorksheet); connect(m_animateWorksheet, SIGNAL(toggled(bool)), m_worksheet, SLOT(enableAnimations(bool))); QAction * restart=new QAction(i18n("Restart Backend"), actionCollection()); actionCollection()->addAction(QLatin1String("restart_backend"), restart); restart->setIcon(QIcon::fromTheme(QLatin1String("system-reboot"))); connect(restart, SIGNAL(triggered()), this, SLOT(restartBackend())); QAction * evaluateCurrent=new QAction(i18n("Evaluate Entry"), actionCollection()); actionCollection()->addAction(QLatin1String("evaluate_current"), evaluateCurrent); actionCollection()->setDefaultShortcut(evaluateCurrent, Qt::SHIFT + Qt::Key_Return); connect(evaluateCurrent, SIGNAL(triggered()), m_worksheet, SLOT(evaluateCurrentEntry())); QAction * insertCommandEntry=new QAction(i18n("Insert Command Entry"), actionCollection()); actionCollection()->addAction(QLatin1String("insert_command_entry"), insertCommandEntry); actionCollection()->setDefaultShortcut(insertCommandEntry, Qt::CTRL + Qt::Key_Return); connect(insertCommandEntry, SIGNAL(triggered()), m_worksheet, SLOT(insertCommandEntry())); QAction * insertTextEntry=new QAction(i18n("Insert Text Entry"), actionCollection()); actionCollection()->addAction(QLatin1String("insert_text_entry"), insertTextEntry); connect(insertTextEntry, SIGNAL(triggered()), m_worksheet, SLOT(insertTextEntry())); QAction * insertLatexEntry=new QAction(i18n("Insert Latex Entry"), actionCollection()); actionCollection()->addAction(QLatin1String("insert_latex_entry"), insertLatexEntry); connect(insertLatexEntry, SIGNAL(triggered()), m_worksheet, SLOT(insertLatexEntry())); QAction * insertPageBreakEntry=new QAction(i18n("Insert Page Break"), actionCollection()); actionCollection()->addAction(QLatin1String("insert_page_break_entry"), insertPageBreakEntry); connect(insertPageBreakEntry, SIGNAL(triggered()), m_worksheet, SLOT(insertPageBreakEntry())); QAction * insertImageEntry=new QAction(i18n("Insert Image"), actionCollection()); actionCollection()->addAction(QLatin1String("insert_image_entry"), insertImageEntry); connect(insertImageEntry, SIGNAL(triggered()), m_worksheet, SLOT(insertImageEntry())); /* QAction * insertCommandEntryBefore=new QAction(i18n("Insert Command Entry Before"), actionCollection()); //insertCommandEntryBefore->setShortcut(Qt::CTRL + Qt::Key_Return); actionCollection()->addAction("insert_command_entry_before", insertCommandEntryBefore); connect(insertCommandEntryBefore, SIGNAL(triggered()), m_worksheet, SLOT(insertCommandEntryBefore())); QAction * insertTextEntryBefore=new QAction(i18n("Insert Text Entry Before"), actionCollection()); //insertTextEntryBefore->setShortcut(Qt::CTRL + Qt::Key_Return); actionCollection()->addAction("insert_text_entry_before", insertTextEntryBefore); connect(insertTextEntryBefore, SIGNAL(triggered()), m_worksheet, SLOT(insertTextEntryBefore())); QAction * insertPageBreakEntryBefore=new QAction(i18n("Insert Page Break Before"), actionCollection()); actionCollection()->addAction("insert_page_break_entry_before", insertPageBreakEntryBefore); connect(insertPageBreakEntryBefore, SIGNAL(triggered()), m_worksheet, SLOT(insertPageBreakEntryBefore())); QAction * insertImageEntryBefore=new QAction(i18n("Insert Image Entry Before"), actionCollection()); //insertTextEntryBefore->setShortcut(Qt::CTRL + Qt::Key_Return); actionCollection()->addAction("insert_image_entry_before", insertImageEntryBefore); connect(insertImageEntryBefore, SIGNAL(triggered()), m_worksheet, SLOT(insertImageEntryBefore())); */ QAction * removeCurrent=new QAction(i18n("Remove current Entry"), actionCollection()); actionCollection()->addAction(QLatin1String("remove_current"), removeCurrent); actionCollection()->setDefaultShortcut(removeCurrent, Qt::ShiftModifier + Qt::Key_Delete); connect(removeCurrent, SIGNAL(triggered()), m_worksheet, SLOT(removeCurrentEntry())); m_showBackendHelp=new QAction(i18n("Show %1 Help", b->name()) , actionCollection()); m_showBackendHelp->setIcon(QIcon::fromTheme(QLatin1String("help-contents"))); actionCollection()->addAction(QLatin1String("backend_help"), m_showBackendHelp); connect(m_showBackendHelp, SIGNAL(triggered()), this, SLOT(showBackendHelp())); QAction * publishWorksheet=new QAction(i18n("Publish Worksheet"), actionCollection()); publishWorksheet->setIcon(QIcon::fromTheme(QLatin1String("get-hot-new-stuff"))); actionCollection()->addAction(QLatin1String("file_publish_worksheet"), publishWorksheet); connect(publishWorksheet, SIGNAL(triggered()), this, SLOT(publishWorksheet())); KToggleAction* showEditor=new KToggleAction(i18n("Show Script Editor"), actionCollection()); showEditor->setChecked(false); actionCollection()->addAction(QLatin1String("show_editor"), showEditor); connect(showEditor, SIGNAL(toggled(bool)), this, SLOT(showScriptEditor(bool))); showEditor->setEnabled(b->extensions().contains(QLatin1String("ScriptExtension"))); QAction * showCompletion=new QAction(i18n("Show Completion"), actionCollection()); actionCollection()->addAction(QLatin1String("show_completion"), showCompletion); QList showCompletionShortcuts; showCompletionShortcuts << Qt::Key_Tab << Qt::CTRL + Qt::Key_Space; actionCollection()->setDefaultShortcuts(showCompletion, showCompletionShortcuts); connect(showCompletion, SIGNAL(triggered()), m_worksheet, SLOT(showCompletion())); // set our XML-UI resource file setXMLFile(QLatin1String("cantor_part.rc")); // we are read-write by default setReadWrite(true); // we are not modified since we haven't done anything yet setModified(false); worksheetSessionChanged(); } CantorPart::~CantorPart() { if (m_scriptEditor) { disconnect(m_scriptEditor, SIGNAL(destroyed()), this, SLOT(scriptEditorClosed())); delete m_scriptEditor; } if (m_searchBar) delete m_searchBar; } void CantorPart::setReadWrite(bool rw) { // notify your internal widget of the read-write state m_worksheetview->setInteractive(rw); ReadWritePart::setReadWrite(rw); } void CantorPart::setModified(bool modified) { // get a handle on our Save action and make sure it is valid if (!m_save) return; // if so, we either enable or disable it based on the current // state if (modified) m_save->setEnabled(true); else m_save->setEnabled(false); // in any event, we want our parent to do it's thing ReadWritePart::setModified(modified); } KAboutData& CantorPart::createAboutData() { // the non-i18n name here must be the same as the directory in // which the part's rc file is installed ('partrcdir' in the // Makefile) static KAboutData about(QLatin1String("cantorpart"), QLatin1String("Cantor"), QLatin1String(CANTOR_VERSION), i18n("CantorPart"), KAboutLicense::GPL, i18n("(C) 2009-2015 Alexander Rieder"), QString(), QLatin1String("http://edu.kde.org/cantor")); about.addAuthor( i18n("Alexander Rieder"), QString(), QLatin1String("alexanderrieder@gmail.com") ); return about; } bool CantorPart::openFile() { //don't crash if for some reason the worksheet is invalid if(m_worksheet==nullptr) { qWarning()<<"trying to open in an invalid cantor part"; return false; } QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); QElapsedTimer timer; timer.start(); const bool rc = m_worksheet->load(localFilePath()); QApplication::restoreOverrideCursor(); if (rc) { qDebug()<< "Worksheet successfully loaded in " << (float)timer.elapsed()/1000 << " seconds)."; updateCaption(); } return rc; } bool CantorPart::saveFile() { // if we aren't read-write, return immediately if (isReadWrite() == false) return false; qDebug()<<"saving to: "<save( localFilePath() ); setModified(false); return true; } void CantorPart::fileSaveAs() { // this slot is called whenever the File->Save As menu is selected QString worksheetFilter = i18n("Cantor Worksheet (*.cws)"); QString filter = worksheetFilter; //if the backend supports scripts, also append their scriptFile endings to the filter Cantor::Backend * const backend=m_worksheet->session()->backend(); if (backend->extensions().contains(QLatin1String("ScriptExtension"))) { Cantor::ScriptExtension* e=dynamic_cast(backend->extension(QLatin1String("ScriptExtension"))); filter+=QLatin1Char('\n')+e->scriptFileFilter(); } QString selectedFilter; QString file_name = QFileDialog::getSaveFileName(widget(), i18n("Save as"), QString(), filter, &selectedFilter); if (file_name.isEmpty()) return; //depending on user's selection, save as a worksheet or as a plain script file if (selectedFilter == worksheetFilter) { if (!file_name.endsWith(QLatin1String(".cws"))) file_name += QLatin1String(".cws"); saveAs(QUrl::fromLocalFile(file_name)); } else m_worksheet->savePlain(file_name); updateCaption(); } void CantorPart::fileSavePlain() { QString file_name = QFileDialog::getSaveFileName(widget(), i18n("Save"), QString(), QString()); if (!file_name.isEmpty()) m_worksheet->savePlain(file_name); } void CantorPart::exportToLatex() { // this slot is called whenever the File->Save As menu is selected, QString filter=i18n("*.tex|LaTeX Document"); QString file_name = QFileDialog::getSaveFileName(widget(), i18n("Export to LaTeX"), QString(), QString()); if (file_name.isEmpty() == false) m_worksheet->saveLatex(file_name); } void CantorPart::guiActivateEvent( KParts::GUIActivateEvent * event ) { KParts::ReadWritePart::guiActivateEvent(event); if(event->activated()) { if(m_scriptEditor) m_scriptEditor->show(); }else { if(m_scriptEditor) m_scriptEditor->hide(); } } void CantorPart::evaluateOrInterrupt() { qDebug()<<"evalorinterrupt"; if(m_worksheet->isRunning()) m_worksheet->interrupt(); else m_worksheet->evaluate(); } void CantorPart::restartBackend() { m_worksheet->session()->logout(); m_worksheet->session()->login(); } void CantorPart::worksheetStatusChanged(Cantor::Session::Status status) { qDebug()<<"wsStatusChange"<setText(i18n("Interrupt")); m_evaluate->setShortcut(Qt::CTRL+Qt::Key_I); m_evaluate->setIcon(QIcon::fromTheme(QLatin1String("dialog-close"))); setStatusMessage(i18n("Calculating...")); }else { m_evaluate->setText(i18n("Evaluate Worksheet")); m_evaluate->setShortcut(Qt::CTRL+Qt::Key_E); m_evaluate->setIcon(QIcon::fromTheme(QLatin1String("system-run"))); setStatusMessage(i18n("Ready")); } } void CantorPart::showSessionError(const QString& message) { qDebug()<<"Error: "<session(), SIGNAL(statusChanged(Cantor::Session::Status)), this, SLOT(worksheetStatusChanged(Cantor::Session::Status))); connect(m_worksheet->session(), SIGNAL(loginStarted()),this, SLOT(worksheetSessionLoginStarted())); connect(m_worksheet->session(), SIGNAL(loginDone()),this, SLOT(worksheetSessionLoginDone())); connect(m_worksheet->session(), SIGNAL(error(const QString&)), this, SLOT(showSessionError(const QString&))); loadAssistants(); m_panelHandler->setSession(m_worksheet->session()); adjustGuiToSession(); initialized(); } void CantorPart::initialized() { if (m_worksheet->isEmpty()) m_worksheet->appendCommandEntry(); m_worksheetview->setEnabled(true); m_worksheetview->setFocus(); setStatusMessage(i18n("Initialization complete")); updateCaption(); } void CantorPart::worksheetSessionLoginStarted() { setStatusMessage(i18n("Initializing...")); QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); } void CantorPart::worksheetSessionLoginDone() { setStatusMessage(i18n("Ready")); QApplication::restoreOverrideCursor(); } void CantorPart::enableTypesetting(bool enable) { m_worksheet->session()->setTypesettingEnabled(enable); } void CantorPart::showBackendHelp() { qDebug()<<"showing backends help"; Cantor::Backend* backend=m_worksheet->session()->backend(); QUrl url = backend->helpUrl(); qDebug()<<"launching url "<session()->backend()->name(), filename)); } void CantorPart::pluginsChanged() { foreach(Cantor::PanelPlugin* plugin, m_panelHandler->plugins()) { connect(plugin, SIGNAL(requestRunCommand(QString)), this, SLOT(runCommand(QString))); } } void CantorPart::loadAssistants() { qDebug()<<"loading assistants..."; QStringList assistantDirs; foreach(const QString &dir, QCoreApplication::libraryPaths()){ assistantDirs << dir + QDir::separator() + QLatin1String("cantor/assistants"); } QPluginLoader loader; foreach(const QString &dir, assistantDirs){ qDebug() << "dir: " << dir; QStringList assistants; QDir assistantDir = QDir(dir); assistants = assistantDir.entryList(); foreach (const QString &assistant, assistants){ if (assistant==QLatin1String(".") || assistant==QLatin1String("..")) continue; loader.setFileName(dir + QDir::separator() + assistant); if (!loader.load()){ qDebug() << "Error while loading assistant: " << assistant; continue; } KPluginFactory* factory = KPluginLoader(loader.fileName()).factory(); Cantor::Assistant* plugin = factory->create(this); Cantor::Backend* backend=worksheet()->session()->backend(); KPluginMetaData info(loader); plugin->setPluginInfo(info); plugin->setBackend(backend); qDebug()<<"plugin "<requiredExtensions(); bool supported=true; foreach(const QString& req, plugin->requiredExtensions()) supported=supported && backend->extensions().contains(req); qDebug()<<"plugin "<name(); if(supported) { plugin->initActions(); connect(plugin, SIGNAL(requested()), this, SLOT(runAssistant())); }else { removeChildClient(plugin); plugin->deleteLater(); } } } } void CantorPart::runAssistant() { Cantor::Assistant* a=qobject_cast(sender()); QStringList cmds=a->run(widget()); qDebug()<appendCommandEntry(cmd); } void CantorPart::showSearchBar() { if (!m_searchBar) { m_searchBar = new SearchBar(widget(), m_worksheet); widget()->layout()->addWidget(m_searchBar); connect(m_searchBar, SIGNAL(destroyed(QObject*)), this, SLOT(searchBarDeleted())); } m_findNext->setEnabled(true); m_findPrev->setEnabled(true); m_searchBar->showStandard(); m_searchBar->setFocus(); } void CantorPart::showExtendedSearchBar() { if (!m_searchBar) { m_searchBar = new SearchBar(widget(), m_worksheet); widget()->layout()->addWidget(m_searchBar); connect(m_searchBar, SIGNAL(destroyed(QObject*)), this, SLOT(searchBarDeleted())); } m_findNext->setEnabled(true); m_findPrev->setEnabled(true); m_searchBar->showExtended(); m_searchBar->setFocus(); } void CantorPart::findNext() { if (m_searchBar) m_searchBar->next(); } void CantorPart::findPrev() { if (m_searchBar) m_searchBar->prev(); } void CantorPart::searchBarDeleted() { m_searchBar = nullptr; m_findNext->setEnabled(false); m_findPrev->setEnabled(false); } void CantorPart::adjustGuiToSession() { #ifdef WITH_EPS m_typeset->setVisible(m_worksheet->session()->backend()->capabilities().testFlag(Cantor::Backend::LaTexOutput)); #else m_typeset->setVisible(false); #endif m_completion->setVisible(m_worksheet->session()->backend()->capabilities().testFlag(Cantor::Backend::Completion)); //this is 0 on the first call if(m_showBackendHelp) m_showBackendHelp->setText(i18n("Show %1 Help", m_worksheet->session()->backend()->name())); } void CantorPart::publishWorksheet() { int ret = KMessageBox::questionYesNo(widget(), i18n("Do you want to upload current Worksheet to public web server?"), i18n("Question - Cantor")); if (ret != KMessageBox::Yes) return; if (isModified()||url().isEmpty()) { ret = KMessageBox::warningContinueCancel(widget(), i18n("The Worksheet is not saved. You should save it before uploading."), i18n("Warning - Cantor"), KStandardGuiItem::save(), KStandardGuiItem::cancel()); if (ret != KMessageBox::Continue) return; if (!saveFile()) return; } qDebug()<<"uploading file "<session()->backend()->id().toLower()), widget()); dialog.setUploadFile(url()); dialog.exec(); } void CantorPart::print() { QPrinter printer; QPointer dialog = new QPrintDialog(&printer, widget()); // TODO: Re-enable print selection //if (m_worksheet->textCursor().hasSelection()) // dialog->addEnabledOption(QAbstractPrintDialog::PrintSelection); if (dialog->exec() == QDialog::Accepted) m_worksheet->print(&printer); delete dialog; } void CantorPart::printPreview() { QPrintPreviewDialog *dialog = new QPrintPreviewDialog(widget()); connect(dialog, SIGNAL(paintRequested(QPrinter*)), m_worksheet, SLOT(print(QPrinter*))); dialog->exec(); } void CantorPart::showScriptEditor(bool show) { if(show) { if (m_scriptEditor) { return; } Cantor::ScriptExtension* scriptE=dynamic_cast(m_worksheet->session()->backend()->extension(QLatin1String("ScriptExtension"))); if (!scriptE) { return; } m_scriptEditor=new ScriptEditorWidget(scriptE->scriptFileFilter(), scriptE->highlightingMode(), widget()->window()); connect(m_scriptEditor, SIGNAL(runScript(const QString&)), this, SLOT(runScript(const QString&))); connect(m_scriptEditor, SIGNAL(destroyed()), this, SLOT(scriptEditorClosed())); m_scriptEditor->show(); }else { m_scriptEditor->deleteLater(); } } void CantorPart::scriptEditorClosed() { QAction* showEditor = actionCollection()->action(QLatin1String("show_editor")); if (showEditor) { showEditor->setChecked(false); } } void CantorPart::runScript(const QString& file) { Cantor::Backend* backend=m_worksheet->session()->backend(); if(!backend->extensions().contains(QLatin1String("ScriptExtension"))) { KMessageBox::error(widget(), i18n("This backend does not support scripts."), i18n("Error - Cantor")); return; } Cantor::ScriptExtension* scriptE=dynamic_cast(backend->extension(QLatin1String("ScriptExtension"))); m_worksheet->appendCommandEntry(scriptE->runExternalScript(file)); } void CantorPart::blockStatusBar() { m_statusBarBlocked=true; } void CantorPart::unblockStatusBar() { m_statusBarBlocked=false; if(!m_cachedStatusMessage.isNull()) setStatusMessage(m_cachedStatusMessage); m_cachedStatusMessage.clear(); } void CantorPart::setStatusMessage(const QString& message) { if(!m_statusBarBlocked) emit setStatusBarText(message); else m_cachedStatusMessage=message; } void CantorPart::showImportantStatusMessage(const QString& message) { setStatusMessage(message); blockStatusBar(); QTimer::singleShot(3000, this, SLOT(unblockStatusBar())); } K_PLUGIN_FACTORY_WITH_JSON(CantorPartFactory, "cantor_part.json", registerPlugin();) #include "cantor_part.moc" diff --git a/src/scripteditor/CMakeLists.txt b/src/scripteditor/CMakeLists.txt new file mode 100644 index 00000000..ec75fa43 --- /dev/null +++ b/src/scripteditor/CMakeLists.txt @@ -0,0 +1,10 @@ +set( scripteditor_SRCS + main.cpp + scripteditorwidget.cpp +) + +add_executable( cantor_scripteditor ${scripteditor_SRCS} ) + +target_link_libraries(cantor_scripteditor KF5::TextEditor) + +install(TARGETS cantor_scripteditor ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} ) \ No newline at end of file diff --git a/src/scripteditor/main.cpp b/src/scripteditor/main.cpp new file mode 100644 index 00000000..1d68da79 --- /dev/null +++ b/src/scripteditor/main.cpp @@ -0,0 +1,44 @@ +/* + 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 Sirgienko Nikita + */ + +#include +#include +#include +#include "scripteditorwidget.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + ScriptEditorWidget* editor = new ScriptEditorWidget(QLatin1String(""),QLatin1String("")); + + if (argc == 2) + { + // Open file, passed in arguments + QString filename = QLatin1String(argv[1]); + QUrl path = QUrl::fromLocalFile(filename); + qDebug() << "open " << path; + editor->open(path); + } + + editor->show(); + + return app.exec(); +} \ No newline at end of file diff --git a/src/scripteditorwidget.cpp b/src/scripteditor/scripteditorwidget.cpp similarity index 98% rename from src/scripteditorwidget.cpp rename to src/scripteditor/scripteditorwidget.cpp index 79cd52be..7adab9c6 100644 --- a/src/scripteditorwidget.cpp +++ b/src/scripteditor/scripteditorwidget.cpp @@ -1,155 +1,159 @@ /* 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 "scripteditorwidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #include #include ScriptEditorWidget::ScriptEditorWidget(const QString& filter, const QString& highlightingMode, QWidget* parent) : KXmlGuiWindow(parent) { setObjectName(QLatin1String("ScriptEditor")); m_filter=filter; m_tmpFile=nullptr; KStandardAction::openNew(this, SLOT(newScript()), actionCollection()); KStandardAction::open(this, SLOT(open()), actionCollection()); KStandardAction::close(this, SLOT(close()), actionCollection()); QAction * runAction = actionCollection()->addAction(QLatin1String("file_execute"), this, SLOT(run())); runAction->setIcon(QIcon::fromTheme(QLatin1String("system-run"))); runAction->setText(i18n("Run Script")); KTextEditor::Editor* editor = KTextEditor::Editor::instance(); if (!editor) { KMessageBox::error(this, i18n("A KDE text-editor component could not be found;\n" "please check your KDE installation.")); m_script=nullptr; } else { m_script=editor->createDocument(nullptr); m_editor=qobject_cast(m_script->createView(this)); m_script->setHighlightingMode(highlightingMode); KConfigGroup cg(KSharedConfig::openConfig(), "ScriptEditor"); setAutoSaveSettings(cg, true); setCentralWidget(m_editor); setupGUI(QSize(500,600), Default, QLatin1String("cantor_scripteditor.rc")); guiFactory()->addClient(m_editor); KWindowConfig::restoreWindowSize(this->windowHandle(), cg); connect(m_script, &KTextEditor::Document::modifiedChanged, this, &ScriptEditorWidget::updateCaption); connect(m_script, &KTextEditor::Document::documentUrlChanged, this, &ScriptEditorWidget::updateCaption); updateCaption(); } } ScriptEditorWidget::~ScriptEditorWidget() { } void ScriptEditorWidget::newScript() { QString highlightingMode = m_script->highlightingMode(); m_script->closeUrl(); m_script->setHighlightingMode(highlightingMode); } void ScriptEditorWidget::open() { QUrl url = QFileDialog::getOpenFileUrl(this, QString(), QUrl(), m_filter); + m_script->openUrl(url); +} +void ScriptEditorWidget::open(QUrl url) +{ m_script->openUrl(url); } void ScriptEditorWidget::run() { QString filename; if(!m_script->url().isLocalFile()) { // If the script is not in a local file, write it to a temporary file if(m_tmpFile==nullptr) { m_tmpFile=new QTemporaryFile(); } else { m_tmpFile->resize(0); } m_tmpFile->open(); QString text=m_script->text(); m_tmpFile->write(text.toUtf8()); m_tmpFile->close(); filename=m_tmpFile->fileName(); }else { m_script->save(); filename=m_script->url().toLocalFile(); } qDebug()<<"running "<queryClose(); else return true; } void ScriptEditorWidget::updateCaption() { QString fileName = m_script->url().toLocalFile(); bool modified = m_script->isModified(); if (fileName.isEmpty()) { setCaption(i18n("Script Editor"), modified); }else { setCaption(i18n("Script Editor - %1", fileName), modified); } } diff --git a/src/scripteditorwidget.h b/src/scripteditor/scripteditorwidget.h similarity index 98% rename from src/scripteditorwidget.h rename to src/scripteditor/scripteditorwidget.h index fd16ef53..bdf63417 100644 --- a/src/scripteditorwidget.h +++ b/src/scripteditor/scripteditorwidget.h @@ -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) 2009 Alexander Rieder */ #ifndef _SCRIPTEDITORWIDGET_H #define _SCRIPTEDITORWIDGET_H #include class QTemporaryFile; class QGridLayout; namespace KTextEditor { class View; class Document; } class ScriptEditorWidget : public KXmlGuiWindow { Q_OBJECT public: explicit ScriptEditorWidget( const QString& filter, const QString& highlightingMode, QWidget* parent = nullptr ); ~ScriptEditorWidget() override; + void open(QUrl url); Q_SIGNALS: void runScript(const QString& filename); private Q_SLOTS: void newScript(); void open(); void run(); void updateCaption(); protected: bool queryClose() Q_DECL_OVERRIDE; private: QString m_filter; KTextEditor::View* m_editor; KTextEditor::Document* m_script; QTemporaryFile* m_tmpFile; }; #endif /* _SCRIPTEDITORWIDGET_H */