/**
* 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("WARNING: " + RS.escape(msg) + "");
};
}
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; i100) {
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("" + RS.escape("ecma> ") + ""
+ "" + RS.escape(command) + "");
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("" + RS.escape(res.toString()) + "");
}
catch (e) {
appendAndScroll("" + RS.escape(e.toString()) + "");
//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