| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- /**
- * Copyright (c) 2011-2018 by Andrew Mustun. All rights reserved.
- *
- * DirectDistanceEntry handling added 2013 by Robert S.
- *
- * This file is part of the QCAD project.
- *
- * QCAD 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 3 of the License, or
- * (at your option) any later version.
- *
- * QCAD 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 QCAD.
- */
- include("scripts/WidgetFactory.js");
- include("scripts/simple.js");
- /**
- * \class EcmaScriptShell
- * \brief Dockable script shell with history.
- * \ingroup ecma_misc_development
- */
- function EcmaScriptShell(guiAction) {
- EAction.call(this, guiAction);
- }
- /*
- EcmaScriptShell.getPreferencesCategory = function() {
- return [ qsTr("Widgets"), qsTr("ECMA Script Shell") ];
- };
- */
- EcmaScriptShell.prototype = new EAction();
- EcmaScriptShell.includeBasePath = includeBasePath;
- /**
- * Shows / hides the script shell widget.
- */
- EcmaScriptShell.prototype.beginEvent = function() {
- EAction.prototype.beginEvent.call(this);
- var appWin = RMainWindowQt.getMainWindow();
- var dock = appWin.findChild("EcmaScriptShellDock");
- if (!RSettings.getOriginalArguments().contains("-no-show")) {
- if (dock.visible===false) {
- // show warning:
- if (RSettings.getBoolValue("EcmaScriptShell/DontShowDialog", false)!==true) {
- var dialog = WidgetFactory.createDialog(EcmaScriptShell.includeBasePath, "EcmaScriptShellDialog.ui", appWin);
- var bb = dialog.findChild("ButtonBox");
- var b = bb.addButton(qsTr("Show ECMAScript Shell"), QDialogButtonBox.AcceptRole);
- b["default"] = false;
- bb.button(QDialogButtonBox.Cancel)["default"] = true;
- var l = dialog.findChild("Message");
- l.openExternalLinks = true;
- var ret = dialog.exec();
- if (ret!==QDialog.Accepted.valueOf()) {
- destr(dialog);
- EAction.activateMainWindow();
- return;
- }
- WidgetFactory.saveState(dialog);
- destr(dialog);
- EAction.activateMainWindow();
- }
- }
- dock.visible = !dock.visible;
- if (dock.visible) dock.raise();
- }
- };
- EcmaScriptShell.prototype.finishEvent = function() {
- EAction.prototype.finishEvent.call(this);
- var appWin = RMainWindowQt.getMainWindow();
- var dock = appWin.findChild("EcmaScriptShellDock");
- this.getGuiAction().setChecked(dock.visible);
- };
- //EcmaScriptShell.prototype.openUrl = function(url) {
- // QDesktopServices.openUrl(url);
- //};
- EcmaScriptShell.col = "#000";
- EcmaScriptShell.colWarning = "#cc0000";
- EcmaScriptShell.colPrompt = "#0000cc";
- EcmaScriptShell.initStyle = function() {
- if (RSettings.hasDarkGuiBackground()) {
- EcmaScriptShell.col = "#fff";
- EcmaScriptShell.colWarning = "#cc0000";
- EcmaScriptShell.colPrompt = "#2E9AFE";
- }
- else {
- EcmaScriptShell.col = "#000";
- EcmaScriptShell.colWarning = "#cc0000";
- EcmaScriptShell.colPrompt = "#0000cc";
- }
- };
- EcmaScriptShell.init = function(basePath) {
- var appWin = EAction.getMainWindow();
- var action = new RGuiAction(qsTr("&Script Shell"), appWin);
- action.setRequiresDocument(false);
- action.setScriptFile(basePath + "/EcmaScriptShell.js");
- action.setIcon(basePath + "/EcmaScriptShell.svg");
- action.setDefaultShortcut(new QKeySequence("g,e"));
- action.setDefaultCommands(["ge"]);
- action.setGroupSortOrder(3800);
- action.setSortOrder(100);
- action.setWidgetNames(["MiscDevelopmentMenu", "MiscDevelopmentToolBar", "MiscDevelopmentToolsPanel"]);
- EcmaScriptShell.initStyle();
- var pl = new RPaletteListenerAdapter();
- appWin.addPaletteListener(pl);
- pl.paletteChanged.connect(EcmaScriptShell.initStyle);
- var formWidget = WidgetFactory.createWidget(basePath, "EcmaScriptShell.ui");
- var frame = formWidget.findChild("Frame");
- // var p = frame.palette;
- // if (!RSettings.hasDarkGuiBackground()) {
- // // white background of command line label:
- // p.setColor(QPalette.Active, QPalette.Window, new QColor(Qt.white));
- // }
- // else {
- // p.setColor(QPalette.Active, QPalette.Window, new QColor("#1e1e1e"));
- // }
- // frame.palette = p;
- // frame.autoFillBackground = true;
- var teHistory = formWidget.findChild("History");
- var leCommand = formWidget.findChild("CommandEdit");
- leCommand.setHistory(RSettings.getStringListValue("EcmaScriptShell/History", []));
- var lCommand = formWidget.findChild("CommandLabel");
- var bToggleTitleBar = formWidget.findChild("ToggleTitleBar");
- var dock = new RDockWidget(qsTr("Script Shell"), appWin);
- dock.objectName = "EcmaScriptShellDock";
- dock.setWidget(formWidget);
-
- appWin.addDockWidget(Qt.RightDockWidgetArea, dock);
- dock.shown.connect(function() { action.setChecked(true); });
- dock.hidden.connect(function() { action.setChecked(false); });
- dock.visible = false;
- if (!isNull(warning)) {
- // initialize simple API warning handler:
- warning.handler = function(msg) {
- appendAndScroll("<span style='color:"+EcmaScriptShell.colWarning+"'>WARNING: " + RS.escape(msg) + "</span>");
- };
- }
- function appendAndScroll(msg) {
- teHistory.append(msg);
- var c = teHistory.textCursor();
- c.movePosition(QTextCursor.End);
- teHistory.setTextCursor(c);
- teHistory.ensureCursorVisible();
- //qDebug(teHistory.html);
- var appWin = EAction.getMainWindow();
- var dlg = appWin.findChild("ProgressDialog");
- if (!appWin.enabled || (!isNull(dlg) && dlg.visible)) {
- QCoreApplication.processEvents();
- }
- }
- var showTitleBar = RSettings.getBoolValue("EcmaScriptShell/ShowTitleBar", false);
- if (!showTitleBar) {
- dock.setTitleBarWidget(new QWidget(dock));
- bToggleTitleBar.checked = false;
- }
- else {
- bToggleTitleBar.checked = true;
- }
- // hide title bar of command line dock widget:
- bToggleTitleBar.toggled.connect(
- function(show) {
- if (show) {
- dock.setTitleBarWidget(null);
- RSettings.setValue("EcmaScriptShell/ShowTitleBar", true);
- }
- else {
- dock.setTitleBarWidget(new QWidget(dock));
- RSettings.setValue("EcmaScriptShell/ShowTitleBar", false);
- }
- }
- );
- var expression = "";
- var bracketsCountR = 0;
- var bracketsCountC = 0;
- var bracketsCountS = 0;
- lCommand.text = ">";
- // user pressed enter, eval command:
- function countBraces(str) {
- for (var i=0, len=str.length; i<len; ++i) {
- switch(str[i]) {
- case '(': ++bracketsCountR; break;
- case ')': --bracketsCountR; break;
- case '{': ++bracketsCountC; break;
- case '}': --bracketsCountC; break;
- case '[': ++bracketsCountS; break;
- case ']': --bracketsCountS; break;
- }
- if (bracketsCountR < 0 || bracketsCountC < 0 || bracketsCountS < 0) {
- // error:
- return false;
- }
- }
- return true;
- }
- leCommand.escape.connect(function() {
- leCommand.setProperty("OpenBrackets", bracketsCountR+bracketsCountC+bracketsCountS);
- bracketsCountR = 0;
- bracketsCountC = 0;
- bracketsCountS = 0;
- lCommand.text = ">";
- expression = "";
- });
- leCommand.commandConfirmed.connect(function(command) {
- // save history:
- var h = leCommand.getHistory();
- if (h.length>100) {
- h = h.slice(-100);
- }
- RSettings.setValue("EcmaScriptShell/History", h);
- leCommand.clear();
- var historySize = RSettings.getIntValue("EcmaScriptShell/HistorySize", 1000);
- var buf = teHistory.plainText.split("\n");
- if (buf.length > historySize) {
- teHistory.setPlainText(buf.slice(-historySize).join("\n"));
- }
- appendAndScroll("<span style='font-style:italic;color:"+EcmaScriptShell.colPrompt+";'>" + RS.escape("ecma> ") + "</span>"
- + "<span style='color:"+EcmaScriptShell.col+"'>" + RS.escape(command) + "</span>");
- leCommand.appendCommand(command);
- // if we have open brackets: continue entering:
- countBraces(command);
- expression+=command + "\n";
- if (bracketsCountR>0 || bracketsCountC>0 || bracketsCountS>0) {
- lCommand.text = "...";
- }
- else {
- var res;
- try {
- //startTransaction();
- //res = RMainWindow.getMainWindow().eval("js", expression);
- res = EcmaScriptShell.eval(expression);
- //endTransaction();
- // make sure input is enabled again:
- if (!isInputEnabled()) {
- enableInput();
- }
- if (res==undefined) {
- res = "undefined";
- }
- appendAndScroll("<span style='color:"+EcmaScriptShell.col+";'>" + RS.escape(res.toString()) + "</span>");
- }
- catch (e) {
- appendAndScroll("<span style='color:"+EcmaScriptShell.colWarning+";'>" + RS.escape(e.toString()) + "</span>");
- //qDebug("error: ", e);
- //qDebug("error: res:", res);
- }
- expression = "";
- bracketsCountR = 0;
- bracketsCountC = 0;
- bracketsCountS = 0;
- lCommand.text = ">";
- }
- leCommand.setFocus();
- });
- // user pressed tab:
- leCommand.completeCommand.connect(function(command) {
- // look from cursor pos backwards:
- //var toComplete = command.substring(0, leCommand.cursorPosition);
- var i2 = leCommand.cursorPosition;
- var i1 = command.regexLastIndexOf(/[^a-zA-Z0-9_]/, i2) + 1;
- var i0 = 0;
- if (i1>2) {
- i0 = command.regexLastIndexOf(/[^a-zA-Z0-9_]/, i1-2) + 1;
- }
- var objName = command.substring(i0, i1-1);
- var toComplete = command.substring(i1, i2);
- var obj = global;
- if (objName.length>0) {
- obj = eval(objName);
- }
- var choices = [];
- //choices = Object.keys(obj);
- for (var k in obj) {
- choices.push(k);
- }
- choices = choices.filter(function(e) { return e.startsWith(toComplete); });
- if (choices.length === 0) {
- // nothing to match
- } else if (choices.length === 1) {
- // only one match. complete it:
- //qDebug("inserting:",choices[0].substring(i2-i1));
- leCommand.insert(choices[0].substring(i2-i1));
- } else {
- // suggest multiple choices that match so far:
- appendAndScroll(choices.join(", "));
- // complete as much as possible:
- var done = false;
- var i = toComplete.length;
- do {
- for (var k=0; k<choices.length; ++k) {
- if (choices[k].length <= i) {
- done = true;
- break;
- }
- if (choices[k][i] != choices[0][i]) {
- done = true;
- break;
- }
- }
- if (!done) {
- leCommand.insert(choices[0][i++]);
- //command = command.concat(choices[0][i++]);
- }
- } while(!done);
- //leCommand.text = command;
- }
- });
- leCommand.clearHistory.connect(teHistory.clear);
- };
- EcmaScriptShell.eval = function(expression) {
- return RMainWindowQt.getMainWindow().eval("js", expression);
- }
|