From c36273122647c31efb253f019237e0b5472f5053 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 May 2014 09:57:37 -0700 Subject: [PATCH 01/12] Add support to load script engines not based on a file --- interface/src/Application.cpp | 19 ++++++++++++------- interface/src/Application.h | 2 +- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1e3e11910e..76fc29e97a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3381,15 +3381,20 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript return _scriptEnginesHash[scriptName]; } - // start the script on a new thread... - ScriptEngine* scriptEngine = new ScriptEngine(QUrl(scriptName), &_controllerScriptingInterface); - _scriptEnginesHash.insert(scriptName, scriptEngine); + ScriptEngine* scriptEngine; + if (scriptName.isNull()) { + scriptEngine = new ScriptEngine(NO_SCRIPT, "", &_controllerScriptingInterface); + } else { + // start the script on a new thread... + scriptEngine = new ScriptEngine(QUrl(scriptName), &_controllerScriptingInterface); + _scriptEnginesHash.insert(scriptName, scriptEngine); - if (!scriptEngine->hasScript()) { - qDebug() << "Application::loadScript(), script failed to load..."; - return NULL; + if (!scriptEngine->hasScript()) { + qDebug() << "Application::loadScript(), script failed to load..."; + return NULL; + } + _runningScriptsWidget->setRunningScripts(getRunningScripts()); } - _runningScriptsWidget->setRunningScripts(getRunningScripts()); // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so // we can use the same ones from the application. diff --git a/interface/src/Application.h b/interface/src/Application.h index ea0de764b9..9ff2009f2d 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -290,7 +290,7 @@ public slots: void loadScriptURLDialog(); void toggleLogDialog(); void initAvatarAndViewFrustum(); - ScriptEngine* loadScript(const QString& fileNameString, bool loadScriptFromEditor = false); + ScriptEngine* loadScript(const QString& fileNameString = QString(), bool loadScriptFromEditor = false); void stopAllScripts(bool restart = false); void stopScript(const QString& scriptName); void reloadAllScripts(); From 3d28cff9dfe5f66c9ef2cac7a8ae8e35446b2cf8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 May 2014 09:58:06 -0700 Subject: [PATCH 02/12] Add console to menu --- interface/src/Menu.cpp | 15 +++++++++++++++ interface/src/Menu.h | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index e1d0c6a574..103cefbb2f 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -78,6 +78,7 @@ Menu::Menu() : _faceshiftEyeDeflection(DEFAULT_FACESHIFT_EYE_DEFLECTION), _frustumDrawMode(FRUSTUM_DRAW_MODE_ALL), _viewFrustumOffset(DEFAULT_FRUSTUM_OFFSET), + _jsConsole(NULL), _octreeStatsDialog(NULL), _lodToolsDialog(NULL), _maxVoxels(DEFAULT_MAX_VOXELS_PER_SYSTEM), @@ -222,6 +223,12 @@ Menu::Menu() : _chatWindow = new ChatWindow(Application::getInstance()->getWindow()); #endif + addActionToQMenuAndActionHash(toolsMenu, + MenuOption::Console, + Qt::CTRL | Qt::Key_QuoteLeft, + this, + SLOT(showConsole())); + QMenu* viewMenu = addMenu("View"); addCheckableActionToQMenuAndActionHash(viewMenu, @@ -1195,6 +1202,14 @@ void Menu::toggleChat() { #endif } +void Menu::showConsole() { + QMainWindow* mainWindow = Application::getInstance()->getWindow(); + if (!_jsConsole) { + _jsConsole = new JSConsole(mainWindow); + } + _jsConsole->setVisible(!_jsConsole->isVisible()); +} + void Menu::audioMuteToggled() { QAction *muteAction = _actionHash.value(MenuOption::MuteAudio); muteAction->setChecked(Application::getInstance()->getAudio()->getMuted()); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 230584bf07..b1d33e0a27 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -26,6 +26,7 @@ #include "location/LocationManager.h" #include "ui/PreferencesDialog.h" #include "ui/ChatWindow.h" +#include "ui/JSConsole.h" #include "ui/ScriptEditorWindow.h" const float ADJUST_LOD_DOWN_FPS = 40.0; @@ -187,6 +188,7 @@ private slots: void showMetavoxelEditor(); void showScriptEditor(); void showChat(); + void showConsole(); void toggleChat(); void audioMuteToggled(); void namedLocationCreated(LocationManager::NamedLocationCreateResponse response); @@ -241,6 +243,7 @@ private: QPointer _MetavoxelEditor; QPointer _ScriptEditor; QPointer _chatWindow; + JSConsole* _jsConsole; OctreeStatsDialog* _octreeStatsDialog; LodToolsDialog* _lodToolsDialog; int _maxVoxels; @@ -297,6 +300,7 @@ namespace MenuOption { const QString CollideWithParticles = "Collide With Particles"; const QString CollideWithVoxels = "Collide With Voxels"; const QString Collisions = "Collisions"; + const QString Console = "Console..."; const QString DecreaseAvatarSize = "Decrease Avatar Size"; const QString DecreaseVoxelSize = "Decrease Voxel Size"; const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD"; From 8aa9cea30e76c796ba3cd1bc242dca8d34f1ac0d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 May 2014 09:59:02 -0700 Subject: [PATCH 03/12] Add custom evaluation of commands in ScriptEngine --- libraries/script-engine/src/ScriptEngine.cpp | 12 ++++++++++++ libraries/script-engine/src/ScriptEngine.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index be97b37b46..3f92d8426b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -304,6 +304,18 @@ void ScriptEngine::evaluate() { } } +QScriptValue ScriptEngine::evaluate(const QString& program, const QString& fileName, int lineNumber) { + QScriptValue result = _engine.evaluate(program, fileName, lineNumber); + bool hasUncaughtException = _engine.hasUncaughtException(); + if (hasUncaughtException) { + int line = _engine.uncaughtExceptionLineNumber(); + qDebug() << "Uncaught exception at line" << line << ": " << result.toString(); + } + emit evaluationFinished(result, hasUncaughtException); + _engine.clearExceptions(); + return result; +} + void ScriptEngine::sendAvatarIdentityPacket() { if (_isAvatar && _avatarData) { _avatarData->sendIdentityPacket(); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 09d41e3e2e..7c9f263694 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -93,6 +93,7 @@ public: public slots: void stop(); + QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1); QObject* setInterval(const QScriptValue& function, int intervalMS); QObject* setTimeout(const QScriptValue& function, int timeoutMS); void clearInterval(QObject* timer) { stopTimer(reinterpret_cast(timer)); } @@ -108,6 +109,7 @@ signals: void printedMessage(const QString& message); void errorMessage(const QString& message); void runningStateChanged(); + void evaluationFinished(QScriptValue result, bool isException); protected: QString _scriptContents; From 5a5d5b4983cf182bd4339a9082526b9fd7d5bbf7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 May 2014 09:59:28 -0700 Subject: [PATCH 04/12] Add JSConsole --- interface/src/ui/JSConsole.cpp | 229 +++++++++++++++++++++++++++++++++ interface/src/ui/JSConsole.h | 62 +++++++++ 2 files changed, 291 insertions(+) create mode 100644 interface/src/ui/JSConsole.cpp create mode 100644 interface/src/ui/JSConsole.h diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp new file mode 100644 index 0000000000..d0880cd50b --- /dev/null +++ b/interface/src/ui/JSConsole.cpp @@ -0,0 +1,229 @@ +// +// JSConsole.cpp +// interface/src/ui +// +// Created by Ryan Huffman on 05/12/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include +#include + +#include "Application.h" +#include "ScriptHighlighting.h" + +#include "JSConsole.h" + +const int NO_CURRENT_HISTORY_COMMAND = -1; +const int MAX_HISTORY_SIZE = 64; + +const QString ACTIVE_PROMPT_STYLESHEET = "color: rgb(0, 0, 255);"; +const QString INACTIVE_PROMPT_STYLESHEET = "color: rgba(0, 0, 0, 0.5);"; +const QString COMMAND_STYLE = "color: rgb(30, 141, 255);"; + +const QString RESULT_ERROR_STYLE = "color: rgb(255, 0, 0);"; +const QString RESULT_SUCCESS_STYLE = "color: rgb(160, 160, 160);"; + +const QString GUTTER_ERROR = "
X
"; +const QString GUTTER_PREVIOUS_COMMAND = "
<
"; + +JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : + QDialog(parent, Qt::WindowStaysOnTopHint), + _ui(new Ui::Console), + _currentCommandInHistory(NO_CURRENT_HISTORY_COMMAND), + _commandHistory(), + _scriptEngine(scriptEngine) { + + _ui->setupUi(this); + _ui->promptTextEdit->setLineWrapMode(QTextEdit::NoWrap); + _ui->promptTextEdit->installEventFilter(this); + + connect(_ui->scrollArea->verticalScrollBar(), SIGNAL(rangeChanged(int, int)), this, SLOT(scrollToBottom())); + connect(_ui->promptTextEdit, SIGNAL(textChanged()), this, SLOT(resizeTextInput())); + + + if (_scriptEngine == NULL) { + _scriptEngine = Application::getInstance()->loadScript(); + } + + connect(_scriptEngine, SIGNAL(evaluationFinished(QScriptValue, bool)), + this, SLOT(handleEvalutationFinished(QScriptValue, bool))); + connect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(handlePrint(const QString&))); + + setWindowOpacity(0.95); +} + +JSConsole::~JSConsole() { + delete _ui; +} + +void JSConsole::executeCommand(const QString& command) { + _commandHistory.prepend(command); + if (_commandHistory.length() > MAX_HISTORY_SIZE) { + _commandHistory.removeLast(); + } + + _ui->promptTextEdit->setDisabled(true); + _ui->promptGutterLabel->setStyleSheet(INACTIVE_PROMPT_STYLESHEET); + + appendMessage(">", "
" + command.toHtmlEscaped() + "
"); + + QMetaObject::invokeMethod(_scriptEngine, "evaluate", Q_ARG(const QString&, command)); + + resetCurrentCommandHistory(); +} + +void JSConsole::handleEvalutationFinished(QScriptValue result, bool isException) { + _ui->promptTextEdit->setDisabled(false); + _ui->promptGutterLabel->setStyleSheet(ACTIVE_PROMPT_STYLESHEET); + + // Make sure focus is still on this window - some commands are blocking and can take awhile to execute. + if (window()->isActiveWindow()) { + _ui->promptTextEdit->setFocus(); + } + + QString gutter = (isException || result.isError()) ? GUTTER_ERROR : GUTTER_PREVIOUS_COMMAND; + QString resultColor = (isException || result.isError()) ? RESULT_ERROR_STYLE : RESULT_SUCCESS_STYLE; + QString resultStr = "
" + result.toString().toHtmlEscaped()  + "
"; + appendMessage(gutter, resultStr); +} + +void JSConsole::handlePrint(const QString& message) { + appendMessage("", message); +} + +void JSConsole::mouseReleaseEvent(QMouseEvent* event) { + _ui->promptTextEdit->setFocus(); +} + +void JSConsole::showEvent(QShowEvent* event) { + _ui->promptTextEdit->setFocus(); +} + +bool JSConsole::eventFilter(QObject* sender, QEvent* event) { + if (sender == _ui->promptTextEdit) { + if (event->type() == QEvent::KeyPress) { + QKeyEvent* keyEvent = static_cast(event); + int key = keyEvent->key(); + + if ((key == Qt::Key_Return || key == Qt::Key_Enter)) { + if (keyEvent->modifiers() & Qt::ShiftModifier) { + // If the shift key is being used then treat it as a regular return/enter. If this isn't done, + // a new QTextBlock isn't created. + keyEvent->setModifiers(keyEvent->modifiers() & ~Qt::ShiftModifier); + } else { + QString command = _ui->promptTextEdit->toPlainText().trimmed(); + + if (!command.isEmpty()) { + QTextCursor cursor = _ui->promptTextEdit->textCursor(); + cursor.select(QTextCursor::Document); + cursor.removeSelectedText(); + + executeCommand(command); + } + + return true; + } + } else if (key == Qt::Key_Down) { + // Go to the next command in history if the cursor is at the last line of the current command. + int blockNumber = _ui->promptTextEdit->textCursor().blockNumber(); + int blockCount = _ui->promptTextEdit->document()->blockCount(); + if (blockNumber == blockCount - 1) { + setToNextCommandInHistory(); + return true; + } + } else if (key == Qt::Key_Up) { + // Go to the previous command in history if the cursor is at the first line of the current command. + int blockNumber = _ui->promptTextEdit->textCursor().blockNumber(); + if (blockNumber == 0) { + setToPreviousCommandInHistory(); + return true; + } + } + } + } + return false; +} + +void JSConsole::setToNextCommandInHistory() { + if (_currentCommandInHistory >= 0) { + _currentCommandInHistory--; + if (_currentCommandInHistory == NO_CURRENT_HISTORY_COMMAND) { + setAndSelectCommand(_rootCommand); + } else { + setAndSelectCommand(_commandHistory[_currentCommandInHistory]); + } + } +} + +void JSConsole::setToPreviousCommandInHistory() { + if (_currentCommandInHistory < (_commandHistory.length() - 1)) { + if (_currentCommandInHistory == NO_CURRENT_HISTORY_COMMAND) { + _rootCommand = _ui->promptTextEdit->toPlainText(); + } + _currentCommandInHistory++; + setAndSelectCommand(_commandHistory[_currentCommandInHistory]); + } +} + +void JSConsole::resetCurrentCommandHistory() { + _currentCommandInHistory = NO_CURRENT_HISTORY_COMMAND; +} + +void JSConsole::resizeTextInput() { + _ui->promptTextEdit->setMaximumHeight(_ui->promptTextEdit->document()->size().height()); + _ui->promptTextEdit->updateGeometry(); +} + +void JSConsole::setAndSelectCommand(const QString& text) { + QTextCursor cursor = _ui->promptTextEdit->textCursor(); + cursor.select(QTextCursor::Document); + cursor.deleteChar(); + cursor.insertText(text); + cursor.movePosition(QTextCursor::End); +} + +void JSConsole::scrollToBottom() { + QScrollBar* scrollBar = _ui->scrollArea->verticalScrollBar(); + scrollBar->setValue(scrollBar->maximum()); +} + +void JSConsole::appendMessage(const QString& gutter, const QString& message) { + QWidget* logLine = new QWidget(_ui->logArea); + QHBoxLayout* layout = new QHBoxLayout(logLine); + layout->setMargin(0); + layout->setSpacing(4); + + QLabel* gutterLabel = new QLabel(logLine); + QLabel* messageLabel = new QLabel(logLine); + + gutterLabel->setFixedWidth(16); + gutterLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); + messageLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); + + QFont font("Courier New"); + font.setStyleHint(QFont::Monospace); + gutterLabel->setFont(font); + messageLabel->setFont(font); + + gutterLabel->setText(gutter); + messageLabel->setText(message); + + layout->addWidget(gutterLabel); + layout->addWidget(messageLabel); + logLine->setLayout(layout); + + layout->setAlignment(gutterLabel, Qt::AlignTop); + + layout->setStretch(0, 0); + layout->setStretch(1, 1); + + _ui->logArea->layout()->addWidget(logLine); + + _ui->logArea->updateGeometry(); + scrollToBottom(); +} diff --git a/interface/src/ui/JSConsole.h b/interface/src/ui/JSConsole.h new file mode 100644 index 0000000000..ebc8aeb43b --- /dev/null +++ b/interface/src/ui/JSConsole.h @@ -0,0 +1,62 @@ +// +// JSConsole.h +// interface/src/ui +// +// Created by Ryan Huffman on 05/12/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_JSConsole_h +#define hifi_JSConsole_h + +#include +#include +#include +#include + +#include "ui_console.h" +#include "ScriptEngine.h" + +class JSConsole : public QDialog { + Q_OBJECT +public: + JSConsole(QWidget* parent, ScriptEngine* scriptEngine = NULL); + ~JSConsole(); + +public slots: + void executeCommand(const QString& command); + +signals: + void commandExecuting(const QString& command); + void commandFinished(const QString& result); + +protected: + void setAndSelectCommand(const QString& command); + virtual bool eventFilter(QObject* sender, QEvent* event); + virtual void mouseReleaseEvent(QMouseEvent* event); + virtual void showEvent(QShowEvent* event); + +protected slots: + void scrollToBottom(); + void resizeTextInput(); + void handleEvalutationFinished(QScriptValue result, bool isException); + void handlePrint(const QString& message); + +private: + void appendMessage(const QString& gutter, const QString& message); + void setToNextCommandInHistory(); + void setToPreviousCommandInHistory(); + void resetCurrentCommandHistory(); + + Ui::Console* _ui; + int _currentCommandInHistory; + QList _commandHistory; + QString _rootCommand; + ScriptEngine* _scriptEngine; +}; + + +#endif // hifi_JSConsole_h From 1d7272cbbf5735cda554bffe829549eb6da88199 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Mon, 26 May 2014 10:18:04 -0700 Subject: [PATCH 05/12] Add console.ui interface file --- interface/ui/console.ui | 257 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 interface/ui/console.ui diff --git a/interface/ui/console.ui b/interface/ui/console.ui new file mode 100644 index 0000000000..2f5e6d235e --- /dev/null +++ b/interface/ui/console.ui @@ -0,0 +1,257 @@ + + + Console + + + + 0 + 0 + 1018 + 263 + + + + Dialog + + + QDialog { background: white } + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOn + + + true + + + + + 0 + 0 + 1003 + 263 + + + + background-color: white; + + + + 4 + + + 4 + + + 4 + + + 4 + + + 4 + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + background-color: white; + + + + 4 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16 + 0 + + + + + 16 + 16 + + + + + 75 + true + + + + background-color: white; font-weight: bold; color: blue; + + + > + + + + + + + + 0 + 0 + + + + + Courier New + + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + Qt::TextEditorInteraction + + + + + + + + + + + + + + + + + + + + + From 422c2eac6733ddc83174396fd6d8550c988b70a8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 May 2014 07:29:48 -0700 Subject: [PATCH 06/12] Update showConsole -> toggleConsole and change shortcut --- interface/src/Menu.cpp | 6 +++--- interface/src/Menu.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 7e641fb069..cce8399491 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -229,9 +229,9 @@ Menu::Menu() : addActionToQMenuAndActionHash(toolsMenu, MenuOption::Console, - Qt::CTRL | Qt::Key_QuoteLeft, + Qt::CTRL | Qt::ALT | Qt::Key_J, this, - SLOT(showConsole())); + SLOT(toggleConsole())); QMenu* viewMenu = addMenu("View"); @@ -1230,7 +1230,7 @@ void Menu::toggleChat() { #endif } -void Menu::showConsole() { +void Menu::toggleConsole() { QMainWindow* mainWindow = Application::getInstance()->getWindow(); if (!_jsConsole) { _jsConsole = new JSConsole(mainWindow); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 1aace5d83b..c9577e708e 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -190,7 +190,7 @@ private slots: void showMetavoxelEditor(); void showScriptEditor(); void showChat(); - void showConsole(); + void toggleConsole(); void toggleChat(); void audioMuteToggled(); void namedLocationCreated(LocationManager::NamedLocationCreateResponse response); From b9248e0bbf7bfe9e57590ace44a7664d72207801 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 May 2014 08:03:46 -0700 Subject: [PATCH 07/12] Update JSConsole to QWidget --- interface/src/Menu.cpp | 18 +++++++++++++++++- interface/src/Menu.h | 2 +- interface/src/ui/JSConsole.cpp | 2 +- interface/src/ui/JSConsole.h | 2 +- interface/ui/console.ui | 24 +++++++++++++----------- 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index cce8399491..a924528c2b 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -72,6 +72,11 @@ const int ONE_SECOND_OF_FRAMES = 60; const int FIVE_SECONDS_OF_FRAMES = 5 * ONE_SECOND_OF_FRAMES; const float MUTE_RADIUS = 50; +const QString CONSOLE_TITLE = "Scripting Console"; +const float CONSOLE_WINDOW_OPACITY = 0.95; +const int CONSOLE_WIDTH = 800; +const int CONSOLE_HEIGHT = 200; + Menu::Menu() : _actionHash(), _audioJitterBufferSamples(0), @@ -1233,7 +1238,18 @@ void Menu::toggleChat() { void Menu::toggleConsole() { QMainWindow* mainWindow = Application::getInstance()->getWindow(); if (!_jsConsole) { - _jsConsole = new JSConsole(mainWindow); + QDialog* dialog = new QDialog(mainWindow, Qt::WindowStaysOnTopHint); + QVBoxLayout* layout = new QVBoxLayout(dialog); + dialog->setLayout(new QVBoxLayout(dialog)); + + dialog->resize(QSize(CONSOLE_WIDTH, CONSOLE_HEIGHT)); + layout->setMargin(0); + layout->setSpacing(0); + layout->addWidget(new JSConsole(dialog)); + dialog->setWindowOpacity(CONSOLE_WINDOW_OPACITY); + dialog->setWindowTitle(CONSOLE_TITLE); + + _jsConsole = dialog; } _jsConsole->setVisible(!_jsConsole->isVisible()); } diff --git a/interface/src/Menu.h b/interface/src/Menu.h index c9577e708e..6b37791b45 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -245,7 +245,7 @@ private: QPointer _MetavoxelEditor; QPointer _ScriptEditor; QPointer _chatWindow; - JSConsole* _jsConsole; + QDialog* _jsConsole; OctreeStatsDialog* _octreeStatsDialog; LodToolsDialog* _lodToolsDialog; int _maxVoxels; diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index d0880cd50b..267be0bc6d 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -32,7 +32,7 @@ const QString GUTTER_ERROR = "
X
"; const QString GUTTER_PREVIOUS_COMMAND = "
<
"; JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : - QDialog(parent, Qt::WindowStaysOnTopHint), + QWidget(parent), _ui(new Ui::Console), _currentCommandInHistory(NO_CURRENT_HISTORY_COMMAND), _commandHistory(), diff --git a/interface/src/ui/JSConsole.h b/interface/src/ui/JSConsole.h index ebc8aeb43b..f28132a1f5 100644 --- a/interface/src/ui/JSConsole.h +++ b/interface/src/ui/JSConsole.h @@ -20,7 +20,7 @@ #include "ui_console.h" #include "ScriptEngine.h" -class JSConsole : public QDialog { +class JSConsole : public QWidget { Q_OBJECT public: JSConsole(QWidget* parent, ScriptEngine* scriptEngine = NULL); diff --git a/interface/ui/console.ui b/interface/ui/console.ui index 2f5e6d235e..7c86ab3d8f 100644 --- a/interface/ui/console.ui +++ b/interface/ui/console.ui @@ -1,13 +1,13 @@ Console - + 0 0 - 1018 - 263 + 1055 + 205 @@ -75,8 +75,8 @@ 0 0 - 1003 - 263 + 1040 + 205 @@ -203,14 +203,14 @@ - background-color: white; font-weight: bold; color: blue; + background-color: white; font-weight: bold; color: rgb(169, 187, 195); > - + @@ -220,9 +220,14 @@ - Courier New + Inconsolata,Lucida Console,Andale Mono,Monaco + -1 + + font-family: Inconsolata, Lucida Console, Andale Mono, Monaco; +font-size:14px + QFrame::NoFrame @@ -232,9 +237,6 @@ Qt::ScrollBarAlwaysOff - - Qt::TextEditorInteraction - From 9af0269151c55e07c453ffb2dba9f8ce12a87f44 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 May 2014 08:05:56 -0700 Subject: [PATCH 08/12] Update console style --- interface/resources/styles/console.qss | 20 ++++++++++++++ interface/src/ui/JSConsole.cpp | 38 +++++++++++++------------- 2 files changed, 39 insertions(+), 19 deletions(-) create mode 100644 interface/resources/styles/console.qss diff --git a/interface/resources/styles/console.qss b/interface/resources/styles/console.qss new file mode 100644 index 0000000000..c10e429cea --- /dev/null +++ b/interface/resources/styles/console.qss @@ -0,0 +1,20 @@ +* { + font-family: Inconsolata, Lucida Console, Andale Mono, Monaco; + font-size: 14px; +} + +promptTextEdit { + color: rgb(117, 133, 140); +} + +promptTextEdit:!enabled { + color: rgba(0, 0, 0, 0.5); +} + +promptGutterLabel { + color: rgba(117, 133, 140); +} + +promptGutterLabel:!enabled { + color: rgba(0, 0, 0, 0.5); +} diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 267be0bc6d..59d2765812 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -21,15 +21,13 @@ const int NO_CURRENT_HISTORY_COMMAND = -1; const int MAX_HISTORY_SIZE = 64; -const QString ACTIVE_PROMPT_STYLESHEET = "color: rgb(0, 0, 255);"; -const QString INACTIVE_PROMPT_STYLESHEET = "color: rgba(0, 0, 0, 0.5);"; -const QString COMMAND_STYLE = "color: rgb(30, 141, 255);"; +const QString COMMAND_STYLE = "color: rgb(38, 106, 155);"; -const QString RESULT_ERROR_STYLE = "color: rgb(255, 0, 0);"; -const QString RESULT_SUCCESS_STYLE = "color: rgb(160, 160, 160);"; +const QString RESULT_SUCCESS_STYLE = "color: rgb(103, 115, 115);"; +const QString RESULT_ERROR_STYLE = "color: rgb(209, 59, 34);"; -const QString GUTTER_ERROR = "
X
"; -const QString GUTTER_PREVIOUS_COMMAND = "
<
"; +const QString GUTTER_PREVIOUS_COMMAND = "<"; +const QString GUTTER_ERROR = "X"; JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : QWidget(parent), @@ -38,8 +36,15 @@ JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : _commandHistory(), _scriptEngine(scriptEngine) { + QFile styleSheet(Application::resourcesPath() + "styles/console.qss"); + if (styleSheet.open(QIODevice::ReadOnly)) { + QDir::setCurrent(Application::resourcesPath()); + setStyleSheet(styleSheet.readAll()); + } + _ui->setupUi(this); _ui->promptTextEdit->setLineWrapMode(QTextEdit::NoWrap); + _ui->promptTextEdit->setWordWrapMode(QTextOption::NoWrap); _ui->promptTextEdit->installEventFilter(this); connect(_ui->scrollArea->verticalScrollBar(), SIGNAL(rangeChanged(int, int)), this, SLOT(scrollToBottom())); @@ -54,7 +59,7 @@ JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : this, SLOT(handleEvalutationFinished(QScriptValue, bool))); connect(_scriptEngine, SIGNAL(printedMessage(const QString&)), this, SLOT(handlePrint(const QString&))); - setWindowOpacity(0.95); + resizeTextInput(); } JSConsole::~JSConsole() { @@ -68,9 +73,8 @@ void JSConsole::executeCommand(const QString& command) { } _ui->promptTextEdit->setDisabled(true); - _ui->promptGutterLabel->setStyleSheet(INACTIVE_PROMPT_STYLESHEET); - appendMessage(">", "
" + command.toHtmlEscaped() + "
"); + appendMessage(">", "" + command.toHtmlEscaped() + ""); QMetaObject::invokeMethod(_scriptEngine, "evaluate", Q_ARG(const QString&, command)); @@ -79,7 +83,6 @@ void JSConsole::executeCommand(const QString& command) { void JSConsole::handleEvalutationFinished(QScriptValue result, bool isException) { _ui->promptTextEdit->setDisabled(false); - _ui->promptGutterLabel->setStyleSheet(ACTIVE_PROMPT_STYLESHEET); // Make sure focus is still on this window - some commands are blocking and can take awhile to execute. if (window()->isActiveWindow()) { @@ -88,7 +91,7 @@ void JSConsole::handleEvalutationFinished(QScriptValue result, bool isException) QString gutter = (isException || result.isError()) ? GUTTER_ERROR : GUTTER_PREVIOUS_COMMAND; QString resultColor = (isException || result.isError()) ? RESULT_ERROR_STYLE : RESULT_SUCCESS_STYLE; - QString resultStr = "
" + result.toString().toHtmlEscaped()  + "
"; + QString resultStr = "" + result.toString().toHtmlEscaped() + ""; appendMessage(gutter, resultStr); } @@ -120,8 +123,7 @@ bool JSConsole::eventFilter(QObject* sender, QEvent* event) { if (!command.isEmpty()) { QTextCursor cursor = _ui->promptTextEdit->textCursor(); - cursor.select(QTextCursor::Document); - cursor.removeSelectedText(); + _ui->promptTextEdit->clear(); executeCommand(command); } @@ -175,7 +177,7 @@ void JSConsole::resetCurrentCommandHistory() { } void JSConsole::resizeTextInput() { - _ui->promptTextEdit->setMaximumHeight(_ui->promptTextEdit->document()->size().height()); + _ui->promptTextEdit->setFixedHeight(_ui->promptTextEdit->document()->size().height()); _ui->promptTextEdit->updateGeometry(); } @@ -205,10 +207,8 @@ void JSConsole::appendMessage(const QString& gutter, const QString& message) { gutterLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); messageLabel->setTextInteractionFlags(Qt::TextSelectableByMouse); - QFont font("Courier New"); - font.setStyleHint(QFont::Monospace); - gutterLabel->setFont(font); - messageLabel->setFont(font); + gutterLabel->setStyleSheet("font-size: 14px; font-family: Inconsolata, Lucida Console, Andale Mono, Monaco;"); + messageLabel->setStyleSheet("font-size: 14px; font-family: Inconsolata, Lucida Console, Andale Mono, Monaco;"); gutterLabel->setText(gutter); messageLabel->setText(message); From 4a0a9f8a3651a5ed6e19cd57eabd7855519f3d4b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 May 2014 08:57:29 -0700 Subject: [PATCH 09/12] Update console style --- interface/resources/styles/console.qss | 8 ++++---- interface/src/ui/JSConsole.cpp | 10 +++++----- interface/ui/console.ui | 17 ++++++++--------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/interface/resources/styles/console.qss b/interface/resources/styles/console.qss index c10e429cea..9e8a3c0ad4 100644 --- a/interface/resources/styles/console.qss +++ b/interface/resources/styles/console.qss @@ -3,18 +3,18 @@ font-size: 14px; } -promptTextEdit { +#promptTextEdit { color: rgb(117, 133, 140); } -promptTextEdit:!enabled { +#promptTextEdit:!enabled { color: rgba(0, 0, 0, 0.5); } -promptGutterLabel { +#promptGutterLabel { color: rgba(117, 133, 140); } -promptGutterLabel:!enabled { +#promptGutterLabel:!enabled { color: rgba(0, 0, 0, 0.5); } diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 59d2765812..87d2fb4860 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -36,17 +36,17 @@ JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : _commandHistory(), _scriptEngine(scriptEngine) { + _ui->setupUi(this); + _ui->promptTextEdit->setLineWrapMode(QTextEdit::NoWrap); + _ui->promptTextEdit->setWordWrapMode(QTextOption::NoWrap); + _ui->promptTextEdit->installEventFilter(this); + QFile styleSheet(Application::resourcesPath() + "styles/console.qss"); if (styleSheet.open(QIODevice::ReadOnly)) { QDir::setCurrent(Application::resourcesPath()); setStyleSheet(styleSheet.readAll()); } - _ui->setupUi(this); - _ui->promptTextEdit->setLineWrapMode(QTextEdit::NoWrap); - _ui->promptTextEdit->setWordWrapMode(QTextOption::NoWrap); - _ui->promptTextEdit->installEventFilter(this); - connect(_ui->scrollArea->verticalScrollBar(), SIGNAL(rangeChanged(int, int)), this, SLOT(scrollToBottom())); connect(_ui->promptTextEdit, SIGNAL(textChanged()), this, SLOT(resizeTextInput())); diff --git a/interface/ui/console.ui b/interface/ui/console.ui index 7c86ab3d8f..d4b0b2bc74 100644 --- a/interface/ui/console.ui +++ b/interface/ui/console.ui @@ -187,27 +187,30 @@ 16 - 0 + 23 16 - 16 + 23 - 75 - true + 50 + false - background-color: white; font-weight: bold; color: rgb(169, 187, 195); + padding: 0px 0 0 0; > + + Qt::PlainText +
@@ -224,10 +227,6 @@ -1 - - font-family: Inconsolata, Lucida Console, Andale Mono, Monaco; -font-size:14px - QFrame::NoFrame From 44c5e56a4bb6484725a34e1ad6251bf30faa6f73 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 May 2014 14:09:53 -0700 Subject: [PATCH 10/12] Update JSConsole colors --- interface/resources/styles/console.qss | 8 ++++---- interface/src/ui/JSConsole.cpp | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/interface/resources/styles/console.qss b/interface/resources/styles/console.qss index 9e8a3c0ad4..021d5d84e9 100644 --- a/interface/resources/styles/console.qss +++ b/interface/resources/styles/console.qss @@ -4,17 +4,17 @@ } #promptTextEdit { - color: rgb(117, 133, 140); + color: #425d72; } #promptTextEdit:!enabled { - color: rgba(0, 0, 0, 0.5); + color: #7f7f7f; } #promptGutterLabel { - color: rgba(117, 133, 140); + color: #a9bbc3; } #promptGutterLabel:!enabled { - color: rgba(0, 0, 0, 0.5); + color: #7f7f7f; } diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 87d2fb4860..921c571d44 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -21,13 +21,13 @@ const int NO_CURRENT_HISTORY_COMMAND = -1; const int MAX_HISTORY_SIZE = 64; -const QString COMMAND_STYLE = "color: rgb(38, 106, 155);"; +const QString COMMAND_STYLE = "color: #266a9b;"; -const QString RESULT_SUCCESS_STYLE = "color: rgb(103, 115, 115);"; -const QString RESULT_ERROR_STYLE = "color: rgb(209, 59, 34);"; +const QString RESULT_SUCCESS_STYLE = "color: #677373;"; +const QString RESULT_ERROR_STYLE = "color: #d13b22;"; -const QString GUTTER_PREVIOUS_COMMAND = "<"; -const QString GUTTER_ERROR = "X"; +const QString GUTTER_PREVIOUS_COMMAND = "<"; +const QString GUTTER_ERROR = "X"; JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : QWidget(parent), From 6ef802621550b0a3d34bfe0dfcf831997f63f21b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 27 May 2014 14:10:09 -0700 Subject: [PATCH 11/12] Add console to script editor --- interface/src/ui/ScriptEditorWindow.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/interface/src/ui/ScriptEditorWindow.cpp b/interface/src/ui/ScriptEditorWindow.cpp index 41732d18c6..3f63f0741b 100644 --- a/interface/src/ui/ScriptEditorWindow.cpp +++ b/interface/src/ui/ScriptEditorWindow.cpp @@ -27,6 +27,9 @@ #include "Application.h" #include "FlowLayout.h" +#include "JSConsole.h" + +const int CONSOLE_HEIGHT = 150; ScriptEditorWindow::ScriptEditorWindow() : _ScriptEditorWindowUI(new Ui::ScriptEditorWindow), @@ -48,6 +51,10 @@ ScriptEditorWindow::ScriptEditorWindow() : connect(new QShortcut(QKeySequence("Ctrl+S"), this), &QShortcut::activated, this,&ScriptEditorWindow::saveScriptClicked); connect(new QShortcut(QKeySequence("Ctrl+O"), this), &QShortcut::activated, this, &ScriptEditorWindow::loadScriptClicked); connect(new QShortcut(QKeySequence("F5"), this), &QShortcut::activated, this, &ScriptEditorWindow::toggleRunScriptClicked); + + QWidget* console = new JSConsole(this); + console->setFixedHeight(CONSOLE_HEIGHT); + this->layout()->addWidget(console); } ScriptEditorWindow::~ScriptEditorWindow() { From 425632e072fe64196d7f917f1a0bb30027d31423 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 29 May 2014 08:48:22 -0700 Subject: [PATCH 12/12] Add 'f' to end of const float to follow coding standard --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index a924528c2b..c21214bed5 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -73,7 +73,7 @@ const int FIVE_SECONDS_OF_FRAMES = 5 * ONE_SECOND_OF_FRAMES; const float MUTE_RADIUS = 50; const QString CONSOLE_TITLE = "Scripting Console"; -const float CONSOLE_WINDOW_OPACITY = 0.95; +const float CONSOLE_WINDOW_OPACITY = 0.95f; const int CONSOLE_WIDTH = 800; const int CONSOLE_HEIGHT = 200;