From 38a5b5b8d14b6c155d4583b77505786b3e54d02e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 14 May 2014 00:28:11 -0700 Subject: [PATCH 01/16] Add ScriptsLocation settings value --- interface/resources/styles/preferences.qss | 3 +- interface/src/Menu.cpp | 10 +- interface/src/Menu.h | 7 + interface/src/ui/PreferencesDialog.cpp | 26 ++++ interface/src/ui/PreferencesDialog.h | 1 + interface/src/ui/RunningScriptsWidget.cpp | 33 ++++- interface/ui/preferencesDialog.ui | 143 ++++++++++++++++++++- 7 files changed, 217 insertions(+), 6 deletions(-) diff --git a/interface/resources/styles/preferences.qss b/interface/resources/styles/preferences.qss index e678acd0c9..40e35c8e52 100644 --- a/interface/resources/styles/preferences.qss +++ b/interface/resources/styles/preferences.qss @@ -12,7 +12,8 @@ QLabel#advancedTuningLabel { QPushButton#buttonBrowseHead, QPushButton#buttonBrowseBody, -QPushButton#buttonBrowseLocation { +QPushButton#buttonBrowseLocation, +QPushButton#buttonBrowseScriptsLocation { background-image: url(styles/search.svg); background-repeat: no-repeat; background-position: center center; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 13b72bcdb3..a3d2a0cb56 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -93,8 +93,8 @@ Menu::Menu() : _fastFPSAverage(ONE_SECOND_OF_FRAMES), _loginAction(NULL), _preferencesDialog(NULL), - _snapshotsLocation() -{ + _snapshotsLocation(), + _scriptsLocation() { Application *appInstance = Application::getInstance(); QMenu* fileMenu = addMenu("File"); @@ -501,6 +501,7 @@ void Menu::loadSettings(QSettings* settings) { _boundaryLevelAdjust = loadSetting(settings, "boundaryLevelAdjust", 0); _snapshotsLocation = settings->value("snapshotsLocation", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)).toString(); + setScriptsLocation(settings->value("scriptsLocation", QString()).toString()); settings->beginGroup("View Frustum Offset Camera"); // in case settings is corrupt or missing loadSetting() will check for NaN @@ -545,6 +546,7 @@ void Menu::saveSettings(QSettings* settings) { settings->setValue("avatarLODDistanceMultiplier", _avatarLODDistanceMultiplier); settings->setValue("boundaryLevelAdjust", _boundaryLevelAdjust); settings->setValue("snapshotsLocation", _snapshotsLocation); + settings->setValue("scriptsLocation", _scriptsLocation); settings->beginGroup("View Frustum Offset Camera"); settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffset.yaw); settings->setValue("viewFrustumOffsetPitch", _viewFrustumOffset.pitch); @@ -1604,3 +1606,7 @@ QString Menu::getSnapshotsLocation() const { return _snapshotsLocation; } +void Menu::setScriptsLocation(const QString& scriptsLocation) { + _scriptsLocation = scriptsLocation; + emit scriptLocationChanged(scriptsLocation); +} diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 723d320905..7d4b3f5f6a 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -93,6 +93,9 @@ public: QString getSnapshotsLocation() const; void setSnapshotsLocation(QString snapshotsLocation) { _snapshotsLocation = snapshotsLocation; } + const QString& getScriptsLocation() const { return _scriptsLocation; } + void setScriptsLocation(const QString& scriptsLocation); + BandwidthDialog* getBandwidthDialog() const { return _bandwidthDialog; } FrustumDrawMode getFrustumDrawMode() const { return _frustumDrawMode; } ViewFrustumOffset getViewFrustumOffset() const { return _viewFrustumOffset; } @@ -145,6 +148,9 @@ public: void static goToDomain(const QString newDomain); void static goTo(QString destination); +signals: + void scriptLocationChanged(const QString& newPath); + public slots: void loginForCurrentDomain(); @@ -261,6 +267,7 @@ private: QPointer _attachmentsDialog; QAction* _chatAction; QString _snapshotsLocation; + QString _scriptsLocation; }; namespace MenuOption { diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index eed33fda23..3eb6f94195 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -29,6 +29,7 @@ PreferencesDialog::PreferencesDialog(QWidget* parent, Qt::WindowFlags flags) : F connect(ui.buttonBrowseHead, &QPushButton::clicked, this, &PreferencesDialog::openHeadModelBrowser); connect(ui.buttonBrowseBody, &QPushButton::clicked, this, &PreferencesDialog::openBodyModelBrowser); connect(ui.buttonBrowseLocation, &QPushButton::clicked, this, &PreferencesDialog::openSnapshotLocationBrowser); + connect(ui.buttonBrowseScriptsLocation, &QPushButton::clicked, this, &PreferencesDialog::openScriptsLocationBrowser); } void PreferencesDialog::accept() { @@ -70,13 +71,32 @@ void PreferencesDialog::openBodyModelBrowser() { void PreferencesDialog::openSnapshotLocationBrowser() { setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint); + show(); + QString dir = QFileDialog::getExistingDirectory(this, tr("Snapshots Location"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); if (!dir.isNull() && !dir.isEmpty()) { ui.snapshotLocationEdit->setText(dir); } + setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); + show(); +} + +void PreferencesDialog::openScriptsLocationBrowser() { + setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint); + show(); + + QString dir = QFileDialog::getExistingDirectory(this, tr("Scripts Location"), + ui.scriptsLocationEdit->text(), + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if (!dir.isNull() && !dir.isEmpty()) { + ui.scriptsLocationEdit->setText(dir); + } + + setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint); + show(); } void PreferencesDialog::resizeEvent(QResizeEvent *resizeEvent) { @@ -116,6 +136,8 @@ void PreferencesDialog::loadPreferences() { ui.snapshotLocationEdit->setText(menuInstance->getSnapshotsLocation()); + ui.scriptsLocationEdit->setText(menuInstance->getScriptsLocation()); + ui.pupilDilationSlider->setValue(myAvatar->getHead()->getPupilDilation() * ui.pupilDilationSlider->maximum()); @@ -169,6 +191,10 @@ void PreferencesDialog::savePreferences() { Menu::getInstance()->setSnapshotsLocation(ui.snapshotLocationEdit->text()); } + if (!ui.scriptsLocationEdit->text().isEmpty() && QDir(ui.scriptsLocationEdit->text()).exists()) { + Menu::getInstance()->setScriptsLocation(ui.scriptsLocationEdit->text()); + } + myAvatar->getHead()->setPupilDilation(ui.pupilDilationSlider->value() / (float)ui.pupilDilationSlider->maximum()); myAvatar->setLeanScale(ui.leanScaleSpin->value()); myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value()); diff --git a/interface/src/ui/PreferencesDialog.h b/interface/src/ui/PreferencesDialog.h index c52986cc5c..0573304eda 100644 --- a/interface/src/ui/PreferencesDialog.h +++ b/interface/src/ui/PreferencesDialog.h @@ -42,6 +42,7 @@ private slots: void setHeadUrl(QString modelUrl); void setSkeletonUrl(QString modelUrl); void openSnapshotLocationBrowser(); + void openScriptsLocationBrowser(); }; diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 61241f71fb..86db1c71fe 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -12,18 +12,27 @@ #include "ui_runningScriptsWidget.h" #include "RunningScriptsWidget.h" +#include +#include #include #include #include #include +#include +#include "ScriptListModel.h" #include "Application.h" + RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : FramelessDialog(parent, 0, POSITION_LEFT), - ui(new Ui::RunningScriptsWidget) { + ui(new Ui::RunningScriptsWidget), + _fsm(this), + _spm(this) { ui->setupUi(this); + setAttribute(Qt::WA_DeleteOnClose, false); + setAllowResize(false); ui->hideWidgetButton->setIcon(QIcon(Application::resourcesPath() + "images/close.svg")); @@ -31,6 +40,28 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : ui->stopAllButton->setIcon(QIcon(Application::resourcesPath() + "images/stop.svg")); ui->loadScriptButton->setIcon(QIcon(Application::resourcesPath() + "images/plus-white.svg")); + ui->recentlyLoadedScriptsArea->hide(); + + _fsm.setReadOnly(true); + _fsm.setRootPath(QDir("/Users/huffman/dev/hifi-19644/examples").absolutePath()); + _fsm.setFilter(QDir::NoDotAndDotDot | QDir::Files); + _fsm.setNameFilterDisables(false); + _fsm.setNameFilters(QStringList("*.js")); + _spm.setSourceModel(&_fsm); + _spm.sort(0, Qt::AscendingOrder); + _spm.setDynamicSortFilter(true); + ui->scriptListView->setModel(&_spm); + ui->scriptListView->setAttribute(Qt::WA_MacShowFocusRect, false); + ui->scriptListView->setRootIndex(_spm.mapFromSource(_fsm.index("/Users/huffman/dev/hifi-19644/examples"))); + connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &RunningScriptsWidget::updateFileFilter); + connect(ui->scriptListView, &QListView::doubleClicked, this, &RunningScriptsWidget::scriptFileSelected); + + // QCompleter *completer = new QCompleter(this); + // completer->setModel(&_spm); + // completer->setCompletionMode(QCompleter::InlineCompletion); + // completer->setCaseSensitivity(Qt::CaseInsensitive); + // ui->filterLineEdit->setCompleter(completer); + _runningScriptsTable = new ScriptsTableWidget(ui->runningScriptsTableWidget); _runningScriptsTable->setColumnCount(2); _runningScriptsTable->setColumnWidth(0, 245); diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui index 8a84956269..119b083d37 100644 --- a/interface/ui/preferencesDialog.ui +++ b/interface/ui/preferencesDialog.ui @@ -155,8 +155,8 @@ color: #0e7077 0 0 - 615 - 936 + 600 + 1039 @@ -612,6 +612,145 @@ color: #0e7077 + + + + + 0 + 0 + + + + + 0 + 40 + + + + + Arial + 20 + 50 + false + + + + color: #0e7077 + + + Scripts + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + + Arial + 16 + + + + color: #0e7077 + + + Load scripts from this directory: + + + Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft + + + 0 + + + snapshotLocationEdit + + + + + + + + + + 0 + 0 + + + + + Arial + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 20 + 20 + + + + + + + + + 0 + 0 + + + + + 30 + 30 + + + + + 30 + 30 + + + + + + + + + + + 30 + 30 + + + + + + From 35151b5dada5dace965f4163a6b6b1f5a23a26ed Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 14 May 2014 01:18:08 -0700 Subject: [PATCH 02/16] Add ScripsModel --- interface/src/ScriptsModel.cpp | 209 +++++++++++++++++++++++++++++++++ interface/src/ScriptsModel.h | 62 ++++++++++ 2 files changed, 271 insertions(+) create mode 100644 interface/src/ScriptsModel.cpp create mode 100644 interface/src/ScriptsModel.h diff --git a/interface/src/ScriptsModel.cpp b/interface/src/ScriptsModel.cpp new file mode 100644 index 0000000000..2b819c04b1 --- /dev/null +++ b/interface/src/ScriptsModel.cpp @@ -0,0 +1,209 @@ +// +// ScriptsModel.cpp +// interface/src +// +// Created by Ryan Huffman on 05/12/14. +// Copyright 2014 High Fidelity, Inc. +// +// S3 request code written with ModelBrowser as a reference. +// +// 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 + +#include "ScriptsModel.h" +#include "Menu.h" + + +static const QString S3_URL = "http://highfidelity-public.s3-us-west-1.amazonaws.com"; +static const QString PUBLIC_URL = "http://public.highfidelity.io"; +static const QString MODELS_LOCATION = "scripts/"; + +static const QString PREFIX_PARAMETER_NAME = "prefix"; +static const QString MARKER_PARAMETER_NAME = "marker"; +static const QString IS_TRUNCATED_NAME = "IsTruncated"; +static const QString CONTAINER_NAME = "Contents"; +static const QString KEY_NAME = "Key"; + +static const int SCRIPT_PATH = Qt::UserRole; + +ScriptItem::ScriptItem(const QString& filename, const QString& fullPath) : + _filename(filename), + _fullPath(fullPath) { +}; + +ScriptsModel::ScriptsModel(QObject* parent) : + QAbstractListModel(parent), + _loadingScripts(false), + _localDirectory(), + _fsWatcher(), + _localFiles(), + _remoteFiles() { + + QString scriptPath = Menu::getInstance()->getScriptsLocation(); + + _localDirectory.setPath(scriptPath); + _localDirectory.setFilter(QDir::Files | QDir::Readable); + _localDirectory.setNameFilters(QStringList("*.js")); + + _fsWatcher.addPath(_localDirectory.absolutePath()); + connect(&_fsWatcher, &QFileSystemWatcher::directoryChanged, this, &ScriptsModel::reloadLocalFiles); + + connect(Menu::getInstance(), &Menu::scriptLocationChanged, this, &ScriptsModel::updateScriptsLocation); + + reloadLocalFiles(); + reloadRemoteFiles(); +} + +QVariant ScriptsModel::data(const QModelIndex& index, int role) const { + const QList* files = NULL; + int row = 0; + bool isLocal = index.row() < _localFiles.size(); + if (isLocal) { + files = &_localFiles; + row = index.row(); + } else { + files = &_remoteFiles; + row = index.row() - _localFiles.size(); + } + + if (role == Qt::DisplayRole) { + return QVariant((*files)[row]->getFilename() + (isLocal ? "" : " (remote)")); + } else if (role == ScriptPath) { + return QVariant((*files)[row]->getFullPath()); + } + return QVariant(); +} + +int ScriptsModel::rowCount(const QModelIndex& parent) const { + if (parent.isValid()) { + return 0; + } + return _localFiles.length() + _remoteFiles.length(); +} + +void ScriptsModel::updateScriptsLocation(const QString& newPath) { + _fsWatcher.removePath(_localDirectory.absolutePath()); + _localDirectory.setPath(newPath); + _fsWatcher.addPath(_localDirectory.absolutePath()); + reloadLocalFiles(); +} + +void ScriptsModel::reloadRemoteFiles() { + if (!_loadingScripts) { + _loadingScripts = true; + while (!_remoteFiles.isEmpty()) { + delete _remoteFiles.takeFirst(); + } + requestRemoteFiles(); + } +} + +void ScriptsModel::requestRemoteFiles(QString marker) { + QUrl url(S3_URL); + QUrlQuery query; + query.addQueryItem(PREFIX_PARAMETER_NAME, MODELS_LOCATION); + if (!marker.isEmpty()) { + query.addQueryItem(MARKER_PARAMETER_NAME, marker); + } + url.setQuery(query); + + QNetworkAccessManager* accessManager = new QNetworkAccessManager(this); + connect(accessManager, SIGNAL(finished(QNetworkReply*)), SLOT(downloadFinished(QNetworkReply*))); + + QNetworkRequest request(url); + accessManager->get(request); +} + +void ScriptsModel::downloadFinished(QNetworkReply* reply) { + bool finished = true; + + if (reply->error() == QNetworkReply::NoError) { + QByteArray data = reply->readAll(); + + if (!data.isEmpty()) { + finished = parseXML(data); + } else { + qDebug() << "Error: Received no data when loading remote scripts"; + } + } + + reply->deleteLater(); + sender()->deleteLater(); + + if (finished) { + _loadingScripts = false; + } +} + +bool ScriptsModel::parseXML(QByteArray xmlFile) { + beginResetModel(); + + QXmlStreamReader xml(xmlFile); + QRegExp jsRegex(".*\\.js"); + bool truncated = false; + QString lastKey; + + while (!xml.atEnd() && !xml.hasError()) { + if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == IS_TRUNCATED_NAME) { + while (!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == IS_TRUNCATED_NAME)) { + xml.readNext(); + if (xml.text().toString() == "true") { + truncated = true; + } + } + } + + if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == CONTAINER_NAME) { + while (!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == CONTAINER_NAME)) { + if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == KEY_NAME) { + xml.readNext(); + lastKey = xml.text().toString(); + if (jsRegex.exactMatch(xml.text().toString())) { + _remoteFiles.append(new ScriptItem(lastKey.mid(MODELS_LOCATION.length()), S3_URL + "/" + lastKey)); + } + } + xml.readNext(); + } + } + xml.readNext(); + } + + endResetModel(); + + // Error handling + if (xml.hasError()) { + qDebug() << "Error loading remote scripts: " << xml.errorString(); + return true; + } + + if (truncated) { + requestRemoteFiles(lastKey); + } + + // If this request was not truncated, we are done. + return !truncated; +} + +void ScriptsModel::reloadLocalFiles() { + beginResetModel(); + + while (!_localFiles.isEmpty()) { + delete _localFiles.takeFirst(); + } + + _localDirectory.refresh(); + + const QFileInfoList localFiles = _localDirectory.entryInfoList(); + for (int i = 0; i < localFiles.size(); i++) { + QFileInfo file = localFiles[i]; + _localFiles.append(new ScriptItem(file.fileName(), file.absoluteFilePath())); + } + + endResetModel(); +} diff --git a/interface/src/ScriptsModel.h b/interface/src/ScriptsModel.h new file mode 100644 index 0000000000..250c7eb9a8 --- /dev/null +++ b/interface/src/ScriptsModel.h @@ -0,0 +1,62 @@ +// +// ScriptsModel.h +// interface/src +// +// 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_ScriptsModel_h +#define hifi_ScriptsModel_h + +#include +#include +#include +#include + +class ScriptItem { +public: + ScriptItem(const QString& filename, const QString& fullPath); + + const QString& getFilename() { return _filename; }; + const QString& getFullPath() { return _fullPath; }; + +private: + QString _filename; + QString _fullPath; +}; + +class ScriptsModel : public QAbstractListModel { + Q_OBJECT +public: + ScriptsModel(QObject* parent = NULL); + + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; + virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; + + enum Role { + ScriptPath = Qt::UserRole, + }; + +protected slots: + void updateScriptsLocation(const QString& newPath); + void downloadFinished(QNetworkReply* reply); + void reloadLocalFiles(); + void reloadRemoteFiles(); + +protected: + void requestRemoteFiles(QString marker = QString()); + bool parseXML(QByteArray xmlFile); + +private: + bool _loadingScripts; + QDir _localDirectory; + QFileSystemWatcher _fsWatcher; + QList _localFiles; + QList _remoteFiles; +}; + +#endif // hifi_ScriptsModel_h From 03f9c0c7e23a4b0232fcd490576d3f1d6d1265c7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 14 May 2014 01:42:24 -0700 Subject: [PATCH 03/16] Update Running Scripts Widget to use ScriptModel --- interface/src/ui/RunningScriptsWidget.cpp | 44 +- interface/src/ui/RunningScriptsWidget.h | 9 + interface/ui/runningScriptsWidget.ui | 792 +++++++++++++++------- 3 files changed, 598 insertions(+), 247 deletions(-) diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 86db1c71fe..5eac34731f 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -3,6 +3,7 @@ // interface/src/ui // // Created by Mohammed Nafees on 03/28/2014. +// Updated by Ryan Huffman on 05/13/2014. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -18,17 +19,17 @@ #include #include #include -#include -#include "ScriptListModel.h" #include "Application.h" +#include "Menu.h" +#include "ScriptsModel.h" RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : FramelessDialog(parent, 0, POSITION_LEFT), ui(new Ui::RunningScriptsWidget), - _fsm(this), - _spm(this) { + _scriptsModel(this), + _proxyModel(this) { ui->setupUi(this); setAttribute(Qt::WA_DeleteOnClose, false); @@ -42,17 +43,13 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : ui->recentlyLoadedScriptsArea->hide(); - _fsm.setReadOnly(true); - _fsm.setRootPath(QDir("/Users/huffman/dev/hifi-19644/examples").absolutePath()); - _fsm.setFilter(QDir::NoDotAndDotDot | QDir::Files); - _fsm.setNameFilterDisables(false); - _fsm.setNameFilters(QStringList("*.js")); - _spm.setSourceModel(&_fsm); - _spm.sort(0, Qt::AscendingOrder); - _spm.setDynamicSortFilter(true); - ui->scriptListView->setModel(&_spm); + QString scriptPath = "/Users/huffman/dev/hifi-19644/examples";//Application::getInstance()->getPreviousScriptLocation(); + + _proxyModel.setSourceModel(&_scriptsModel); + _proxyModel.sort(0, Qt::AscendingOrder); + _proxyModel.setDynamicSortFilter(true); + ui->scriptListView->setModel(&_proxyModel); ui->scriptListView->setAttribute(Qt::WA_MacShowFocusRect, false); - ui->scriptListView->setRootIndex(_spm.mapFromSource(_fsm.index("/Users/huffman/dev/hifi-19644/examples"))); connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &RunningScriptsWidget::updateFileFilter); connect(ui->scriptListView, &QListView::doubleClicked, this, &RunningScriptsWidget::scriptFileSelected); @@ -88,6 +85,17 @@ RunningScriptsWidget::~RunningScriptsWidget() { delete ui; } +void RunningScriptsWidget::updateFileFilter(const QString& filter) { + QRegExp regex("^.*" + QRegExp::escape(filter) + ".*$", Qt::CaseInsensitive); + _proxyModel.setFilterRegExp(regex); +} + +void RunningScriptsWidget::scriptFileSelected(const QModelIndex& index) { + QVariant scriptFile = _proxyModel.data(index, ScriptsModel::ScriptPath); + qDebug() << "Loading: " << scriptFile.toString(); + Application::getInstance()->loadScript(scriptFile.toString()); +} + void RunningScriptsWidget::setBoundary(const QRect& rect) { _boundary = rect; } @@ -126,8 +134,6 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) { ui->runningScriptsTableWidget->resize(ui->runningScriptsTableWidget->width(), y - RUNNING_SCRIPTS_TABLE_LEFT_MARGIN); _runningScriptsTable->resize(_runningScriptsTable->width(), y - RUNNING_SCRIPTS_TABLE_LEFT_MARGIN); - ui->reloadAllButton->move(ui->reloadAllButton->x(), y); - ui->stopAllButton->move(ui->stopAllButton->x(), y); ui->recentlyLoadedLabel->move(ui->recentlyLoadedLabel->x(), ui->stopAllButton->y() + ui->stopAllButton->height() + RECENTLY_LOADED_TOP_MARGIN); ui->recentlyLoadedScriptsTableWidget->move(ui->recentlyLoadedScriptsTableWidget->x(), @@ -173,10 +179,12 @@ void RunningScriptsWidget::paintEvent(QPaintEvent* event) { QPainter painter(this); painter.setPen(QColor::fromRgb(225, 225, 225)); // #e1e1e1 + const QPoint& labelPos = ui->runningScriptsArea->mapToParent(ui->currentlyRunningLabel->pos()); + if (ui->currentlyRunningLabel->isVisible()) { // line below the 'Currently Running' label - painter.drawLine(36, ui->currentlyRunningLabel->y() + ui->currentlyRunningLabel->height(), - 300, ui->currentlyRunningLabel->y() + ui->currentlyRunningLabel->height()); + painter.drawLine(36, labelPos.y() + ui->currentlyRunningLabel->height(), + 300, labelPos.y() + ui->currentlyRunningLabel->height()); } if (ui->recentlyLoadedLabel->isVisible()) { diff --git a/interface/src/ui/RunningScriptsWidget.h b/interface/src/ui/RunningScriptsWidget.h index ad310c4ed4..6b45ac2202 100644 --- a/interface/src/ui/RunningScriptsWidget.h +++ b/interface/src/ui/RunningScriptsWidget.h @@ -3,6 +3,7 @@ // interface/src/ui // // Created by Mohammed Nafees on 03/28/2014. +// Updated by Ryan Huffman on 05/13/2014. // Copyright 2014 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -12,6 +13,10 @@ #ifndef hifi_RunningScriptsWidget_h #define hifi_RunningScriptsWidget_h +#include +#include + +#include "ScriptsModel.h" #include "FramelessDialog.h" #include "ScriptsTableWidget.h" @@ -42,9 +47,13 @@ private slots: void stopScript(int row, int column); void loadScript(int row, int column); void allScriptsStopped(); + void updateFileFilter(const QString& filter); + void scriptFileSelected(const QModelIndex& index); private: Ui::RunningScriptsWidget* ui; + QSortFilterProxyModel _proxyModel; + ScriptsModel _scriptsModel; ScriptsTableWidget* _runningScriptsTable; ScriptsTableWidget* _recentlyLoadedScriptsTable; QStringList _recentlyLoadedScripts; diff --git a/interface/ui/runningScriptsWidget.ui b/interface/ui/runningScriptsWidget.ui index 6abd0f2d5a..324a460d1b 100644 --- a/interface/ui/runningScriptsWidget.ui +++ b/interface/ui/runningScriptsWidget.ui @@ -6,8 +6,8 @@ 0 0 - 323 - 894 + 324 + 971 @@ -21,252 +21,586 @@ QWidget { background: #f7f7f7; } - - - - 37 - 29 - 251 - 20 - + + + 20 - - color: #0e7077; + + 20 + + + 20 + + + 20 + + + + + + 0 + + + 0 + + + 0 + + + + + color: #0e7077; font-size: 20pt; background: transparent; - - - <html><head/><body><p><span style=" font-size:18pt;">Running Scripts</span></p></body></html> - - - 0 - - - -1 - - - - - - 36 - 110 - 270 - 20 - - - - color: #0e7077; -font: bold 14pt; + + + <html><head/><body><p><span style=" font-size:18pt;">Running Scripts</span></p></body></html> + + + 0 + + + -1 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + PointingHandCursor + + + border: 0 + + + + + + + 16 + 16 + + + + true + + + + + + + + + + + 0 + 1 + + + + + 0 + 141 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + Helvetica,Arial,sans-serif + 16 + 75 + false + true + + + + color: #0e7077; +font: bold 16pt; background: transparent; - - - <html><head/><body><p><span style=" font-weight:600;">Currently running</span></p></body></html> - - - - - - 36 - 270 - 111 - 35 - - - - PointingHandCursor - - - false - - - background: #0e7077; + + + <html><head/><body><p><span style=" font-weight:600;">Currently running</span></p></body></html> + + + + + + + Qt::Vertical + + + QSizePolicy::Minimum + + + + 0 + 8 + + + + + + + + + 0 + 0 + + + + + 24 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 111 + 35 + + + + PointingHandCursor + + + false + + + background: #0e7077; color: #fff; border-radius: 4px; font: bold 14pt; padding-top: 3px; - - - Reload all - - - - ../resources/images/reload.svg../resources/images/reload.svg - - - - - - 160 - 270 - 93 - 35 - - - - PointingHandCursor - - - background: #0e7077; + + + Reload all + + + + ../../../../../../../../.designer/resources/images/reload.svg../../../../../../../../.designer/resources/images/reload.svg + + + + + + + + 0 + 0 + + + + + 111 + 35 + + + + PointingHandCursor + + + background: #0e7077; color: #fff; border-radius: 4px; font: bold 14pt; padding-top: 3px; - - - Stop all - - - - ../resources/images/stop.svg../resources/images/stop.svg - - - - - - 36 - 320 - 265 - 20 - - - - color: #0e7077; -font: bold 14pt; - - - <html><head/><body><p><span style=" font-weight:600;">Recently loaded</span></p></body></html> - - - - - - 36 - 630 - 211 - 41 - - - - color: #95a5a6; + + + Stop all + + + + ../../../../../../../../.designer/resources/images/stop.svg../../../../../../../../.designer/resources/images/stop.svg + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 8 + + + + + + + + font: 14pt; + + + There are no scripts currently running. + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Qt::Vertical + + + + 20 + 10 + + + + + + + + + 0 + 1 + + + + + 284 + 0 + + + + 0 + + + background: transparent; font-size: 14pt; - - - (click a script or use the 1-9 keys to load and run it) - - - true - - - - - - 285 - 29 - 16 - 16 - - - - PointingHandCursor - - - - - - - 16 - 16 - - - - true - - - - - - 36 - 110 - 271 - 51 - - - - font: 14pt; - - - There are no scripts currently running. - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - 30 - 340 - 272 - 280 - - - - background: transparent; + + + + + + + + + + true + + + + 0 + 100 + + + + + 16777215 + 16777215 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + color: #0e7077; +font: bold 16pt; + + + <html><head/><body><p><span style=" font-weight:600;">Recently loaded</span></p></body></html> + + + + + + + font: 14pt; + + + There are no recently loaded scripts. + + + + + + + + 0 + 1 + + + + + 284 + 0 + + + + background: transparent; font-size: 14pt; - - - - - - 30 - 128 - 272 - 161 - - - - background: transparent; + + + + + + + color: #95a5a6; font-size: 14pt; - - - - - - 36 - 70 - 111 - 35 - - - - PointingHandCursor - - - background: #0e7077; + + + (click a script or use the 1-9 keys to load and run it) + + + true + + + + + + + + + + + 0 + 1 + + + + + 0 + 300 + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 15 + + + + + color: #0e7077; +font: bold 16pt; + + + Scripts + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + 111 + 35 + + + + PointingHandCursor + + + background: #0e7077; color: #fff; border-radius: 4px; font: bold 14pt; padding-top: 3px; - - - Load script - - - - ../resources/images/plus.svg../resources/images/plus.svg - - - widgetTitle - currentlyRunningLabel - recentlyLoadedLabel - recentlyLoadedInstruction - hideWidgetButton - recentlyLoadedScriptsTableWidget - runningScriptsTableWidget - noRunningScriptsLabel - reloadAllButton - stopAllButton - loadScriptButton + + + Load script + + + + ../../../../../../../../.designer/resources/images/plus.svg../../../../../../../../.designer/resources/images/plus.svg + + + + + + + + + + border: 1px solid rgb(128, 128, 128); +border-radius: 2px; +padding: 4px; +background-color: white; + + + filter + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 6 + + + + + + + + border: 1px solid rgb(128, 128, 128); +border-radius: 2px; + + + QFrame::Box + + + QFrame::Plain + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAsNeeded + + + + + + + From 90d3dd3ceb980c0ef582c1adac87f1e58bc596f0 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 14 May 2014 01:43:37 -0700 Subject: [PATCH 04/16] Remove unused lines --- interface/src/ui/RunningScriptsWidget.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 5eac34731f..5a7c2e7925 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -43,8 +43,6 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : ui->recentlyLoadedScriptsArea->hide(); - QString scriptPath = "/Users/huffman/dev/hifi-19644/examples";//Application::getInstance()->getPreviousScriptLocation(); - _proxyModel.setSourceModel(&_scriptsModel); _proxyModel.sort(0, Qt::AscendingOrder); _proxyModel.setDynamicSortFilter(true); @@ -53,12 +51,6 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &RunningScriptsWidget::updateFileFilter); connect(ui->scriptListView, &QListView::doubleClicked, this, &RunningScriptsWidget::scriptFileSelected); - // QCompleter *completer = new QCompleter(this); - // completer->setModel(&_spm); - // completer->setCompletionMode(QCompleter::InlineCompletion); - // completer->setCaseSensitivity(Qt::CaseInsensitive); - // ui->filterLineEdit->setCompleter(completer); - _runningScriptsTable = new ScriptsTableWidget(ui->runningScriptsTableWidget); _runningScriptsTable->setColumnCount(2); _runningScriptsTable->setColumnWidth(0, 245); From 6e80b97efe3774c3690d1ce4711db1be1537d17d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 14 May 2014 01:44:35 -0700 Subject: [PATCH 05/16] Disable hiding of running script area when none are running --- interface/src/ui/RunningScriptsWidget.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 5a7c2e7925..866297f92d 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -96,7 +96,6 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) { _runningScriptsTable->setRowCount(list.size()); ui->noRunningScriptsLabel->setVisible(list.isEmpty()); - ui->currentlyRunningLabel->setVisible(!list.isEmpty()); ui->runningScriptsTableWidget->setVisible(!list.isEmpty()); ui->reloadAllButton->setVisible(!list.isEmpty()); ui->stopAllButton->setVisible(!list.isEmpty()); @@ -220,7 +219,7 @@ void RunningScriptsWidget::createRecentlyLoadedScriptsTable() { } } - ui->recentlyLoadedLabel->setVisible(!_recentlyLoadedScripts.isEmpty()); + ui->noRecentlyLoadedLabel->setVisible(_recentlyLoadedScripts.isEmpty()); ui->recentlyLoadedScriptsTableWidget->setVisible(!_recentlyLoadedScripts.isEmpty()); ui->recentlyLoadedInstruction->setVisible(!_recentlyLoadedScripts.isEmpty()); From a1d5d44bc12630e80e6314788a21a5b7efd85b8f Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 14 May 2014 01:45:07 -0700 Subject: [PATCH 06/16] Update RunningScripts to be created after Menu has been created --- interface/src/Application.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b50e9ef1dc..ec6f0d9eff 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -168,7 +168,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _bytesPerSecond(0), _previousScriptLocation(), _logger(new FileLogger(this)), - _runningScriptsWidget(new RunningScriptsWidget(_window)), + _runningScriptsWidget(NULL), _runningScriptsWidgetWasVisible(false) { // init GnuTLS for DTLS with domain-servers @@ -201,6 +201,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // call Menu getInstance static method to set up the menu _window->setMenuBar(Menu::getInstance()); + _runningScriptsWidget = new RunningScriptsWidget(_window); + unsigned int listenPort = 0; // bind to an ephemeral port by default const char** constArgv = const_cast(argv); const char* portStr = getCmdOption(argc, constArgv, "--listenPort"); From 2eeb3f5f2f078e90fae0d808258011d3c0cd8125 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 21 May 2014 16:56:51 -0700 Subject: [PATCH 07/16] Update loadScript to optionally activate main window --- interface/src/Application.cpp | 4 ++-- interface/src/Application.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8509bd96d1..e89c3d9853 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3412,7 +3412,7 @@ void Application::saveScripts() { _settings->endArray(); } -ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor) { +ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor, bool activateMainWindow) { if(loadScriptFromEditor && _scriptEnginesHash.contains(scriptName) && !_scriptEnginesHash[scriptName]->isFinished()){ return _scriptEnginesHash[scriptName]; } @@ -3486,7 +3486,7 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript workerThread->start(); // restore the main window's active state - if (!loadScriptFromEditor) { + if (activateMainWindow && !loadScriptFromEditor) { _window->activateWindow(); } bumpSettings(); diff --git a/interface/src/Application.h b/interface/src/Application.h index 1968ef4fee..17200a9419 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -303,7 +303,7 @@ public slots: void loadScriptURLDialog(); void toggleLogDialog(); void initAvatarAndViewFrustum(); - ScriptEngine* loadScript(const QString& fileNameString, bool loadScriptFromEditor = false); + ScriptEngine* loadScript(const QString& fileNameString, bool loadScriptFromEditor = false, bool activateMainWindow = false); void scriptFinished(const QString& scriptName); void stopAllScripts(bool restart = false); void stopScript(const QString& scriptName); From b108ea31403cfdd032da606f611e725a76d7aeb1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 21 May 2014 16:57:13 -0700 Subject: [PATCH 08/16] Update script list to only label local files --- interface/src/ScriptsModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ScriptsModel.cpp b/interface/src/ScriptsModel.cpp index 2b819c04b1..f9ed94f3fa 100644 --- a/interface/src/ScriptsModel.cpp +++ b/interface/src/ScriptsModel.cpp @@ -73,7 +73,7 @@ QVariant ScriptsModel::data(const QModelIndex& index, int role) const { } if (role == Qt::DisplayRole) { - return QVariant((*files)[row]->getFilename() + (isLocal ? "" : " (remote)")); + return QVariant((*files)[row]->getFilename() + (isLocal ? " (local)" : "")); } else if (role == ScriptPath) { return QVariant((*files)[row]->getFullPath()); } From c428e6896241752a423c06b9740b394fe573883a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 21 May 2014 17:03:07 -0700 Subject: [PATCH 09/16] Update script window to load script when pressing enter --- interface/src/ui/RunningScriptsWidget.cpp | 68 ++++++++++++++++++----- interface/src/ui/RunningScriptsWidget.h | 7 ++- 2 files changed, 60 insertions(+), 15 deletions(-) diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index b897c96c36..46989200cc 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -13,7 +13,6 @@ #include "ui_runningScriptsWidget.h" #include "RunningScriptsWidget.h" -#include #include #include #include @@ -43,13 +42,18 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : ui->recentlyLoadedScriptsArea->hide(); + ui->filterLineEdit->installEventFilter(this); + + connect(&_proxyModel, &QSortFilterProxyModel::modelReset, + this, &RunningScriptsWidget::selectFirstInList); + _proxyModel.setSourceModel(&_scriptsModel); _proxyModel.sort(0, Qt::AscendingOrder); _proxyModel.setDynamicSortFilter(true); ui->scriptListView->setModel(&_proxyModel); - ui->scriptListView->setAttribute(Qt::WA_MacShowFocusRect, false); + connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &RunningScriptsWidget::updateFileFilter); - connect(ui->scriptListView, &QListView::doubleClicked, this, &RunningScriptsWidget::scriptFileSelected); + connect(ui->scriptListView, &QListView::doubleClicked, this, &RunningScriptsWidget::loadScriptFromList); _runningScriptsTable = new ScriptsTableWidget(ui->runningScriptsTableWidget); _runningScriptsTable->setColumnCount(2); @@ -80,12 +84,19 @@ RunningScriptsWidget::~RunningScriptsWidget() { void RunningScriptsWidget::updateFileFilter(const QString& filter) { QRegExp regex("^.*" + QRegExp::escape(filter) + ".*$", Qt::CaseInsensitive); _proxyModel.setFilterRegExp(regex); + selectFirstInList(); } -void RunningScriptsWidget::scriptFileSelected(const QModelIndex& index) { +void RunningScriptsWidget::loadScriptFromList(const QModelIndex& index) { QVariant scriptFile = _proxyModel.data(index, ScriptsModel::ScriptPath); - qDebug() << "Loading: " << scriptFile.toString(); - Application::getInstance()->loadScript(scriptFile.toString()); + Application::getInstance()->loadScript(scriptFile.toString(), false, false); +} + +void RunningScriptsWidget::loadSelectedScript() { + QModelIndex selectedIndex = ui->scriptListView->currentIndex(); + if (selectedIndex.isValid()) { + loadScriptFromList(selectedIndex); + } } void RunningScriptsWidget::setBoundary(const QRect& rect) { @@ -134,14 +145,43 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) { createRecentlyLoadedScriptsTable(); } -void RunningScriptsWidget::keyPressEvent(QKeyEvent* event) -{ +void RunningScriptsWidget::showEvent(QShowEvent* event) { + if (!event->spontaneous()) { + ui->filterLineEdit->setFocus(); + } + + FramelessDialog::showEvent(event); +} + +void RunningScriptsWidget::selectFirstInList() { + if (_proxyModel.rowCount() > 0) { + ui->scriptListView->setCurrentIndex(_proxyModel.index(0, 0)); + } +} + +bool RunningScriptsWidget::eventFilter(QObject* sender, QEvent* event) { + if (sender == ui->filterLineEdit) { + if (event->type() != QEvent::KeyPress) { + return false; + } + QKeyEvent* keyEvent = static_cast(event); + if (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) { + QModelIndex selectedIndex = ui->scriptListView->currentIndex(); + if (selectedIndex.isValid()) { + loadScriptFromList(selectedIndex); + } + event->accept(); + return true; + } + return false; + } + + return FramelessDialog::eventFilter(sender, event); +} + +void RunningScriptsWidget::keyPressEvent(QKeyEvent* event) { int loadScriptNumber = -1; switch(event->key()) { - case Qt::Key_Escape: - Application::getInstance()->toggleRunningScriptsWidget(); - break; - case Qt::Key_1: case Qt::Key_2: case Qt::Key_3: @@ -159,7 +199,7 @@ void RunningScriptsWidget::keyPressEvent(QKeyEvent* event) } if (loadScriptNumber >= 0) { if (_recentlyLoadedScripts.size() > loadScriptNumber) { - Application::getInstance()->loadScript(_recentlyLoadedScripts.at(loadScriptNumber)); + Application::getInstance()->loadScript(_recentlyLoadedScripts.at(loadScriptNumber), false, false); } } @@ -199,7 +239,7 @@ void RunningScriptsWidget::stopScript(int row, int column) { } void RunningScriptsWidget::loadScript(int row, int column) { - Application::getInstance()->loadScript(_recentlyLoadedScriptsTable->item(row, column)->toolTip()); + Application::getInstance()->loadScript(_recentlyLoadedScriptsTable->item(row, column)->toolTip(), false, false); } void RunningScriptsWidget::allScriptsStopped() { diff --git a/interface/src/ui/RunningScriptsWidget.h b/interface/src/ui/RunningScriptsWidget.h index 8170cb65b8..7b03898ece 100644 --- a/interface/src/ui/RunningScriptsWidget.h +++ b/interface/src/ui/RunningScriptsWidget.h @@ -37,8 +37,11 @@ signals: void stopScriptName(const QString& name); protected: + virtual bool eventFilter(QObject* sender, QEvent* event); + virtual void keyPressEvent(QKeyEvent* event); virtual void paintEvent(QPaintEvent* event); + virtual void showEvent(QShowEvent* event); public slots: void scriptStopped(const QString& scriptName); @@ -49,7 +52,9 @@ private slots: void loadScript(int row, int column); void allScriptsStopped(); void updateFileFilter(const QString& filter); - void scriptFileSelected(const QModelIndex& index); + void loadScriptFromList(const QModelIndex& index); + void loadSelectedScript(); + void selectFirstInList(); private: Ui::RunningScriptsWidget* ui; From e21a7524c6b1a206910b74ce0cfc453added7ae9 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 21 May 2014 17:03:19 -0700 Subject: [PATCH 10/16] Update runningscripts style --- interface/ui/runningScriptsWidget.ui | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/interface/ui/runningScriptsWidget.ui b/interface/ui/runningScriptsWidget.ui index 747b29abf2..063b2cd3b5 100644 --- a/interface/ui/runningScriptsWidget.ui +++ b/interface/ui/runningScriptsWidget.ui @@ -434,7 +434,7 @@ font-size: 14pt; 0 - 1 + 2 @@ -544,9 +544,15 @@ border-radius: 2px; padding: 4px; background-color: white; + + + filter + + true + @@ -568,8 +574,14 @@ background-color: white; - border: 1px solid rgb(128, 128, 128); -border-radius: 2px; + QListView { + border: 1px solid rgb(128, 128, 128); + border-radius: 2px; +} +QListView::item { + padding-top: 2px; + padding-bottom: 2px; +} QFrame::Box From 0877f9f15930e6fcd531b69e61fb85f40e93ee4a Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 17 Jun 2014 20:19:49 -0700 Subject: [PATCH 11/16] Fix issues with running scripts window on Windows Replace running scripts table with a new widget that uses a proper layout that doesn't rely on hard-coded sizing. Custom painted lines were replaced with a horizontal QFrame line. --- interface/src/ui/RunningScriptsWidget.cpp | 161 +++++++--------------- interface/src/ui/RunningScriptsWidget.h | 8 +- interface/ui/runningScriptsWidget.ui | 97 +++++++++---- 3 files changed, 116 insertions(+), 150 deletions(-) diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index 449b11c89c..b2ee36d1fe 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -27,6 +27,7 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : FramelessDialog(parent, 0, POSITION_LEFT), ui(new Ui::RunningScriptsWidget), + _signalMapper(this), _scriptsModel(this), _proxyModel(this) { ui->setupUi(this); @@ -55,17 +56,9 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &RunningScriptsWidget::updateFileFilter); connect(ui->scriptListView, &QListView::doubleClicked, this, &RunningScriptsWidget::loadScriptFromList); - _runningScriptsTable = new ScriptsTableWidget(ui->runningScriptsTableWidget); - _runningScriptsTable->setColumnCount(2); - _runningScriptsTable->setColumnWidth(0, 245); - _runningScriptsTable->setColumnWidth(1, 22); - connect(_runningScriptsTable, &QTableWidget::cellClicked, this, &RunningScriptsWidget::stopScript); - _recentlyLoadedScriptsTable = new ScriptsTableWidget(ui->recentlyLoadedScriptsTableWidget); _recentlyLoadedScriptsTable->setColumnCount(1); _recentlyLoadedScriptsTable->setColumnWidth(0, 265); - connect(_recentlyLoadedScriptsTable, &QTableWidget::cellClicked, - this, &RunningScriptsWidget::loadScript); connect(ui->hideWidgetButton, &QPushButton::clicked, Application::getInstance(), &Application::toggleRunningScriptsWidget); @@ -75,6 +68,7 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) : this, &RunningScriptsWidget::allScriptsStopped); connect(ui->loadScriptButton, &QPushButton::clicked, Application::getInstance(), &Application::loadDialog); + connect(&_signalMapper, SIGNAL(mapped(QString)), Application::getInstance(), SLOT(stopScript(const QString&))); } RunningScriptsWidget::~RunningScriptsWidget() { @@ -104,45 +98,55 @@ void RunningScriptsWidget::setBoundary(const QRect& rect) { } void RunningScriptsWidget::setRunningScripts(const QStringList& list) { - _runningScriptsTable->setRowCount(list.size()); + setUpdatesEnabled(false); + QLayoutItem* widget; + while ((widget = ui->scrollAreaWidgetContents->layout()->takeAt(0)) != NULL) { + delete widget->widget(); + delete widget; + } + const int CLOSE_ICON_HEIGHT = 12; + for (int i = 0; i < list.size(); i++) { + QWidget* row = new QWidget(ui->scrollAreaWidgetContents); + row->setLayout(new QHBoxLayout(row)); + + QUrl url = QUrl(list.at(i)); + QLabel* name = new QLabel(url.fileName(), row); + QPushButton* closeButton = new QPushButton(row); + closeButton->setFlat(true); + closeButton->setIcon( + QIcon(QPixmap(Application::resourcesPath() + "images/kill-script.svg").scaledToHeight(CLOSE_ICON_HEIGHT))); + closeButton->setSizePolicy(QSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred)); + closeButton->setStyleSheet("border: 0;"); + closeButton->setCursor(Qt::PointingHandCursor); + + connect(closeButton, SIGNAL(clicked()), &_signalMapper, SLOT(map())); + _signalMapper.setMapping(closeButton, url.toString()); + + row->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); + + row->layout()->setContentsMargins(4, 4, 4, 4); + row->layout()->setSpacing(0); + + row->layout()->addWidget(name); + row->layout()->addWidget(closeButton); + + QFrame* line = new QFrame(row); + line->setFrameShape(QFrame::HLine); + line->setStyleSheet("color: #E1E1E1; margin-left: 6px; margin-right: 6px;"); + + ui->scrollAreaWidgetContents->layout()->addWidget(row); + ui->scrollAreaWidgetContents->layout()->addWidget(line); + } + ui->noRunningScriptsLabel->setVisible(list.isEmpty()); - ui->runningScriptsTableWidget->setVisible(!list.isEmpty()); ui->reloadAllButton->setVisible(!list.isEmpty()); ui->stopAllButton->setVisible(!list.isEmpty()); - const int CLOSE_ICON_HEIGHT = 12; - - for (int i = 0; i < list.size(); ++i) { - QTableWidgetItem *scriptName = new QTableWidgetItem; - scriptName->setText(QFileInfo(list.at(i)).fileName()); - scriptName->setToolTip(list.at(i)); - scriptName->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); - QTableWidgetItem *closeIcon = new QTableWidgetItem; - closeIcon->setIcon(QIcon(QPixmap(Application::resourcesPath() + "images/kill-script.svg").scaledToHeight(CLOSE_ICON_HEIGHT))); - - _runningScriptsTable->setItem(i, 0, scriptName); - _runningScriptsTable->setItem(i, 1, closeIcon); - } - - const int RUNNING_SCRIPTS_TABLE_LEFT_MARGIN = 12; - const int RECENTLY_LOADED_TOP_MARGIN = 61; - const int RECENTLY_LOADED_LABEL_TOP_MARGIN = 19; - - int y = ui->runningScriptsTableWidget->y() + RUNNING_SCRIPTS_TABLE_LEFT_MARGIN; - for (int i = 0; i < _runningScriptsTable->rowCount(); ++i) { - y += _runningScriptsTable->rowHeight(i); - } - - ui->runningScriptsTableWidget->resize(ui->runningScriptsTableWidget->width(), y - RUNNING_SCRIPTS_TABLE_LEFT_MARGIN); - _runningScriptsTable->resize(_runningScriptsTable->width(), y - RUNNING_SCRIPTS_TABLE_LEFT_MARGIN); - ui->recentlyLoadedLabel->move(ui->recentlyLoadedLabel->x(), - ui->stopAllButton->y() + ui->stopAllButton->height() + RECENTLY_LOADED_TOP_MARGIN); - ui->recentlyLoadedScriptsTableWidget->move(ui->recentlyLoadedScriptsTableWidget->x(), - ui->recentlyLoadedLabel->y() + RECENTLY_LOADED_LABEL_TOP_MARGIN); - - - createRecentlyLoadedScriptsTable(); + ui->scrollAreaWidgetContents->updateGeometry(); + setUpdatesEnabled(true); + Application::processEvents(); + repaint(); } void RunningScriptsWidget::showEvent(QShowEvent* event) { @@ -187,81 +191,10 @@ void RunningScriptsWidget::keyPressEvent(QKeyEvent *keyEvent) { } } -void RunningScriptsWidget::paintEvent(QPaintEvent* event) { - QPainter painter(this); - painter.setPen(QColor::fromRgb(225, 225, 225)); // #e1e1e1 - - const QPoint& labelPos = ui->runningScriptsArea->mapToParent(ui->currentlyRunningLabel->pos()); - - if (ui->currentlyRunningLabel->isVisible()) { - // line below the 'Currently Running' label - painter.drawLine(36, labelPos.y() + ui->currentlyRunningLabel->height(), - 300, labelPos.y() + ui->currentlyRunningLabel->height()); - } - - if (ui->recentlyLoadedLabel->isVisible()) { - // line below the 'Recently loaded' label - painter.drawLine(36, ui->recentlyLoadedLabel->y() + ui->recentlyLoadedLabel->height(), - 300, ui->recentlyLoadedLabel->y() + ui->recentlyLoadedLabel->height()); - } - - painter.end(); -} - void RunningScriptsWidget::scriptStopped(const QString& scriptName) { - _recentlyLoadedScripts.prepend(scriptName); -} - -void RunningScriptsWidget::stopScript(int row, int column) { - if (column == 1) { // make sure the user has clicked on the close icon - _lastStoppedScript = _runningScriptsTable->item(row, 0)->toolTip(); - emit stopScriptName(_runningScriptsTable->item(row, 0)->toolTip()); - } -} - -void RunningScriptsWidget::loadScript(int row, int column) { - Application::getInstance()->loadScript(_recentlyLoadedScriptsTable->item(row, column)->toolTip(), false, false); + // _recentlyLoadedScripts.prepend(scriptName); } void RunningScriptsWidget::allScriptsStopped() { Application::getInstance()->stopAllScripts(); } - -void RunningScriptsWidget::createRecentlyLoadedScriptsTable() { - if (!_recentlyLoadedScripts.contains(_lastStoppedScript) && !_lastStoppedScript.isEmpty()) { - _recentlyLoadedScripts.prepend(_lastStoppedScript); - _lastStoppedScript = ""; - } - - for (int i = 0; i < _recentlyLoadedScripts.size(); ++i) { - if (Application::getInstance()->getRunningScripts().contains(_recentlyLoadedScripts.at(i))) { - _recentlyLoadedScripts.removeOne(_recentlyLoadedScripts.at(i)); - } - } - - ui->noRecentlyLoadedLabel->setVisible(_recentlyLoadedScripts.isEmpty()); - ui->recentlyLoadedScriptsTableWidget->setVisible(!_recentlyLoadedScripts.isEmpty()); - ui->recentlyLoadedInstruction->setVisible(!_recentlyLoadedScripts.isEmpty()); - - int limit = _recentlyLoadedScripts.size() > 9 ? 9 : _recentlyLoadedScripts.size(); - _recentlyLoadedScriptsTable->setRowCount(limit); - for (int i = 0; i < limit; i++) { - QTableWidgetItem *scriptName = new QTableWidgetItem; - scriptName->setText(QString::number(i + 1) + ". " + QFileInfo(_recentlyLoadedScripts.at(i)).fileName()); - scriptName->setToolTip(_recentlyLoadedScripts.at(i)); - scriptName->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); - - _recentlyLoadedScriptsTable->setItem(i, 0, scriptName); - } - - int y = ui->recentlyLoadedScriptsTableWidget->y() + 15; - for (int i = 0; i < _recentlyLoadedScriptsTable->rowCount(); ++i) { - y += _recentlyLoadedScriptsTable->rowHeight(i); - } - - ui->recentlyLoadedInstruction->setGeometry(36, y, - ui->recentlyLoadedInstruction->width(), - ui->recentlyLoadedInstruction->height()); - - repaint(); -} diff --git a/interface/src/ui/RunningScriptsWidget.h b/interface/src/ui/RunningScriptsWidget.h index 7b03898ece..6810aca487 100644 --- a/interface/src/ui/RunningScriptsWidget.h +++ b/interface/src/ui/RunningScriptsWidget.h @@ -14,6 +14,7 @@ #define hifi_RunningScriptsWidget_h #include +#include #include #include "ScriptsModel.h" @@ -40,7 +41,6 @@ protected: virtual bool eventFilter(QObject* sender, QEvent* event); virtual void keyPressEvent(QKeyEvent* event); - virtual void paintEvent(QPaintEvent* event); virtual void showEvent(QShowEvent* event); public slots: @@ -48,8 +48,6 @@ public slots: void setBoundary(const QRect& rect); private slots: - void stopScript(int row, int column); - void loadScript(int row, int column); void allScriptsStopped(); void updateFileFilter(const QString& filter); void loadScriptFromList(const QModelIndex& index); @@ -58,15 +56,13 @@ private slots: private: Ui::RunningScriptsWidget* ui; + QSignalMapper _signalMapper; QSortFilterProxyModel _proxyModel; ScriptsModel _scriptsModel; - ScriptsTableWidget* _runningScriptsTable; ScriptsTableWidget* _recentlyLoadedScriptsTable; QStringList _recentlyLoadedScripts; QString _lastStoppedScript; QRect _boundary; - - void createRecentlyLoadedScriptsTable(); }; #endif // hifi_RunningScriptsWidget_h diff --git a/interface/ui/runningScriptsWidget.ui b/interface/ui/runningScriptsWidget.ui index 063b2cd3b5..2f51ab7a94 100644 --- a/interface/ui/runningScriptsWidget.ui +++ b/interface/ui/runningScriptsWidget.ui @@ -304,6 +304,9 @@ padding-top: 3px; Qt::Vertical + + QSizePolicy::Fixed + 20 @@ -313,26 +316,73 @@ padding-top: 3px; - - - - 0 - 1 - + + + + Helvetica,Arial,sans-serif + 14 + - - - 284 - 0 - - - - 0 + + Qt::LeftToRight - background: transparent; -font-size: 14pt; + margin: 0; + + QFrame::NoFrame + + + 0 + + + Qt::ScrollBarAlwaysOn + + + Qt::ScrollBarAlwaysOff + + + true + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + 0 + 0 + 269 + 16 + + + + + 0 + 0 + + + + font-size: 14pt; + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + @@ -410,20 +460,7 @@ font: bold 16pt; background: transparent; font-size: 14pt; - - - - - - color: #95a5a6; -font-size: 14pt; - - - (click a script or use the 1-9 keys to load and run it) - - - true - + runningScriptsList From 108fa36d2461777eacfc1c284173424ae8543f7b Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 20 Jun 2014 16:32:42 -0700 Subject: [PATCH 12/16] Disable the ability to load a script multiple times It won't show up correctly in running scripts, and can cause it to end up running in the background unnoticed. Also added an error message for when a script doesn't load. --- interface/src/Application.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 869fdc2770..72b0c79724 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3523,8 +3523,13 @@ void Application::saveScripts() { ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor, bool activateMainWindow) { QUrl scriptUrl(scriptName); const QString& scriptURLString = scriptUrl.toString(); - if(loadScriptFromEditor && _scriptEnginesHash.contains(scriptURLString) && !_scriptEnginesHash[scriptURLString]->isFinished()){ - return _scriptEnginesHash[scriptURLString]; + if (_scriptEnginesHash.contains(scriptURLString)) { + if(loadScriptFromEditor && !_scriptEnginesHash[scriptURLString]->isFinished()) { + return _scriptEnginesHash[scriptURLString]; + } else { + QMessageBox::warning(getWindow(), "Error Loading Script", scriptURLString + " is already running."); + return NULL; + } } ScriptEngine* scriptEngine; @@ -3536,6 +3541,7 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript if (!scriptEngine->hasScript()) { qDebug() << "Application::loadScript(), script failed to load..."; + QMessageBox::warning(getWindow(), "Error Loading Script", scriptURLString + " failed to load."); return NULL; } From 652543cdca28a00de94dff8a848e54e62091311d Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Jun 2014 11:46:35 -0700 Subject: [PATCH 13/16] Update _scriptEngineHash to work with duplicate running scripts --- interface/src/Application.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 72b0c79724..c3e8876a82 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3524,11 +3524,8 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript QUrl scriptUrl(scriptName); const QString& scriptURLString = scriptUrl.toString(); if (_scriptEnginesHash.contains(scriptURLString)) { - if(loadScriptFromEditor && !_scriptEnginesHash[scriptURLString]->isFinished()) { + if (loadScriptFromEditor && !_scriptEnginesHash[scriptURLString]->isFinished()) { return _scriptEnginesHash[scriptURLString]; - } else { - QMessageBox::warning(getWindow(), "Error Loading Script", scriptURLString + " is already running."); - return NULL; } } @@ -3545,7 +3542,7 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript return NULL; } - _scriptEnginesHash.insert(scriptURLString, scriptEngine); + _scriptEnginesHash.insertMulti(scriptURLString, scriptEngine); _runningScriptsWidget->setRunningScripts(getRunningScripts()); } @@ -3617,7 +3614,9 @@ ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScript } void Application::scriptFinished(const QString& scriptName) { - if (_scriptEnginesHash.remove(scriptName)) { + QHash::iterator it = _scriptEnginesHash.find(scriptName); + if (it != _scriptEnginesHash.end()) { + _scriptEnginesHash.erase(it); _runningScriptsWidget->scriptStopped(scriptName); _runningScriptsWidget->setRunningScripts(getRunningScripts()); bumpSettings(); From 89f43acb7faf16f12f166f3cc548eac3ccaac061 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Jun 2014 11:47:14 -0700 Subject: [PATCH 14/16] Add a tooltip with the full path to running scripts --- interface/src/ui/RunningScriptsWidget.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/ui/RunningScriptsWidget.cpp b/interface/src/ui/RunningScriptsWidget.cpp index b2ee36d1fe..136d0a2d38 100644 --- a/interface/src/ui/RunningScriptsWidget.cpp +++ b/interface/src/ui/RunningScriptsWidget.cpp @@ -130,6 +130,8 @@ void RunningScriptsWidget::setRunningScripts(const QStringList& list) { row->layout()->addWidget(name); row->layout()->addWidget(closeButton); + row->setToolTip(url.toString()); + QFrame* line = new QFrame(row); line->setFrameShape(QFrame::HLine); line->setStyleSheet("color: #E1E1E1; margin-left: 6px; margin-right: 6px;"); From f249020d6d028f35bc004e1d6a890be19fcb6491 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Jun 2014 11:50:54 -0700 Subject: [PATCH 15/16] Clean up redundant if statement --- interface/src/Application.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c3e8876a82..e74b5fd58a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3523,10 +3523,10 @@ void Application::saveScripts() { ScriptEngine* Application::loadScript(const QString& scriptName, bool loadScriptFromEditor, bool activateMainWindow) { QUrl scriptUrl(scriptName); const QString& scriptURLString = scriptUrl.toString(); - if (_scriptEnginesHash.contains(scriptURLString)) { - if (loadScriptFromEditor && !_scriptEnginesHash[scriptURLString]->isFinished()) { - return _scriptEnginesHash[scriptURLString]; - } + if (_scriptEnginesHash.contains(scriptURLString) && loadScriptFromEditor + && !_scriptEnginesHash[scriptURLString]->isFinished()) { + + return _scriptEnginesHash[scriptURLString]; } ScriptEngine* scriptEngine; From 3bec59fd3397a7e5e873d5bfbb4b263aafd175bc Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 24 Jun 2014 20:38:46 -0700 Subject: [PATCH 16/16] Fix unindented line --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ec095a4f59..67de203fa2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1286,7 +1286,7 @@ void Application::dropEvent(QDropEvent *event) { void Application::sendPingPackets() { QByteArray pingPacket = NodeList::getInstance()->constructPingPacket(); -controlledBroadcastToNodes(pingPacket, NodeSet() + controlledBroadcastToNodes(pingPacket, NodeSet() << NodeType::VoxelServer << NodeType::ParticleServer << NodeType::ModelServer << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::MetavoxelServer);