running script window treeview fully works

This commit is contained in:
Thijs Wenker 2015-01-12 00:41:38 +01:00
parent 5a8e00f503
commit 8feb51013b
6 changed files with 161 additions and 62 deletions

View file

@ -11,7 +11,6 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include <typeinfo>
#include <QUrl> #include <QUrl>
#include <QUrlQuery> #include <QUrlQuery>
#include <QXmlStreamReader> #include <QXmlStreamReader>
@ -32,22 +31,21 @@ static const QString IS_TRUNCATED_NAME = "IsTruncated";
static const QString CONTAINER_NAME = "Contents"; static const QString CONTAINER_NAME = "Contents";
static const QString KEY_NAME = "Key"; static const QString KEY_NAME = "Key";
TreeNodeBase::TreeNodeBase(TreeNodeFolder* parent, TreeNodeType type) : TreeNodeBase::TreeNodeBase(TreeNodeFolder* parent, const QString& name, TreeNodeType type) :
_parent(parent), _parent(parent),
_name(name),
_type(type) { _type(type) {
}; };
TreeNodeScript::TreeNodeScript(const QString& filename, const QString& fullPath, ScriptOrigin origin) : TreeNodeScript::TreeNodeScript(const QString& localPath, const QString& fullPath, ScriptOrigin origin) :
TreeNodeBase(NULL, TREE_NODE_TYPE_SCRIPT), TreeNodeBase(NULL, localPath.split("/").last(), TREE_NODE_TYPE_SCRIPT),
_filename(filename), _localPath(localPath),
_fullPath(fullPath), _fullPath(fullPath),
_origin(origin) _origin(origin) {
{
}; };
TreeNodeFolder::TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent) : TreeNodeFolder::TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent) :
TreeNodeBase(parent, TREE_NODE_TYPE_FOLDER), TreeNodeBase(parent, foldername, TREE_NODE_TYPE_FOLDER) {
_foldername(foldername) {
}; };
ScriptsModel::ScriptsModel(QObject* parent) : ScriptsModel::ScriptsModel(QObject* parent) :
@ -57,7 +55,6 @@ ScriptsModel::ScriptsModel(QObject* parent) :
_fsWatcher(), _fsWatcher(),
_treeNodes() _treeNodes()
{ {
_localDirectory.setFilter(QDir::Files | QDir::Readable); _localDirectory.setFilter(QDir::Files | QDir::Readable);
_localDirectory.setNameFilters(QStringList("*.js")); _localDirectory.setNameFilters(QStringList("*.js"));
@ -70,46 +67,56 @@ ScriptsModel::ScriptsModel(QObject* parent) :
reloadRemoteFiles(); reloadRemoteFiles();
} }
TreeNodeBase* ScriptsModel::getTreeNodeFromIndex(const QModelIndex& index) const {
if (index.isValid()) {
return static_cast<TreeNodeBase*>(index.internalPointer());
}
return NULL;
}
QModelIndex ScriptsModel::index(int row, int column, const QModelIndex& parent) const { QModelIndex ScriptsModel::index(int row, int column, const QModelIndex& parent) const {
return QModelIndex(); if (row < 0 || column < 0) {
return QModelIndex();
}
return createIndex(row, column, getFolderNodes(static_cast<TreeNodeFolder*>(getTreeNodeFromIndex(parent))).at(row));
} }
QModelIndex ScriptsModel::parent(const QModelIndex& child) const { QModelIndex ScriptsModel::parent(const QModelIndex& child) const {
return QModelIndex(); TreeNodeFolder* parent = (static_cast<TreeNodeBase*>(child.internalPointer()))->getParent();
if (!parent) {
return QModelIndex();
}
TreeNodeFolder* grandParent = parent->getParent();
int row = getFolderNodes(grandParent).indexOf(parent);
return createIndex(row, 0, parent);
} }
QVariant ScriptsModel::data(const QModelIndex& index, int role) const { QVariant ScriptsModel::data(const QModelIndex& index, int role) const {
/*const QList<TreeNodeScript*>* files = NULL; TreeNodeBase* node = getTreeNodeFromIndex(index);
int row = 0; if (node->getType() == TREE_NODE_TYPE_SCRIPT) {
bool isLocal = index.row() < _localFiles.size(); TreeNodeScript* script = static_cast<TreeNodeScript*>(node);
if (isLocal) { if (role == Qt::DisplayRole) {
files = &_localFiles; return QVariant(script->getName() + (script->getOrigin() == SCRIPT_ORIGIN_LOCAL ? " (local)" : ""));
row = index.row(); } else if (role == ScriptPath) {
} else { return QVariant(script->getFullPath());
files = &_remoteFiles; }
row = index.row() - _localFiles.size(); } else if (node->getType() == TREE_NODE_TYPE_FOLDER) {
TreeNodeFolder* folder = static_cast<TreeNodeFolder*>(node);
if (role == Qt::DisplayRole) {
return QVariant(folder->getName());
}
} }
if (role == Qt::DisplayRole) {
return QVariant((*files)[row]->getFilename() + (isLocal ? " (local)" : ""));
} else if (role == ScriptPath) {
return QVariant((*files)[row]->getFullPath());
}*/
return QVariant(); return QVariant();
} }
int ScriptsModel::rowCount(const QModelIndex& parent) const { int ScriptsModel::rowCount(const QModelIndex& parent) const {
if (parent.isValid()) { return getFolderNodes(static_cast<TreeNodeFolder*>(getTreeNodeFromIndex(parent))).count();
return 0;
}
return 0;// _localFiles.length() + _remoteFiles.length();
} }
int ScriptsModel::columnCount(const QModelIndex& parent) const { int ScriptsModel::columnCount(const QModelIndex& parent) const {
return 1; return 1;
} }
void ScriptsModel::updateScriptsLocation(const QString& newPath) { void ScriptsModel::updateScriptsLocation(const QString& newPath) {
_fsWatcher.removePath(_localDirectory.absolutePath()); _fsWatcher.removePath(_localDirectory.absolutePath());
@ -129,7 +136,9 @@ void ScriptsModel::reloadRemoteFiles() {
_loadingScripts = true; _loadingScripts = true;
for (int i = _treeNodes.size() - 1; i >= 0; i--) { for (int i = _treeNodes.size() - 1; i >= 0; i--) {
TreeNodeBase* node = _treeNodes.at(i); TreeNodeBase* node = _treeNodes.at(i);
if (typeid(*node) == typeid(TreeNodeScript) && static_cast<TreeNodeScript*>(node)->getOrigin() == SCRIPT_ORIGIN_REMOTE) { if (node->getType() == TREE_NODE_TYPE_SCRIPT &&
static_cast<TreeNodeScript*>(node)->getOrigin() == SCRIPT_ORIGIN_REMOTE)
{
delete node; delete node;
_treeNodes.removeAt(i); _treeNodes.removeAt(i);
} }
@ -229,7 +238,6 @@ void ScriptsModel::reloadLocalFiles() {
for (int i = _treeNodes.size() - 1; i >= 0; i--) { for (int i = _treeNodes.size() - 1; i >= 0; i--) {
TreeNodeBase* node = _treeNodes.at(i); TreeNodeBase* node = _treeNodes.at(i);
qDebug() << "deleting local " << i << " " << typeid(*node).name();
if (node->getType() == TREE_NODE_TYPE_SCRIPT && if (node->getType() == TREE_NODE_TYPE_SCRIPT &&
static_cast<TreeNodeScript*>(node)->getOrigin() == SCRIPT_ORIGIN_LOCAL) static_cast<TreeNodeScript*>(node)->getOrigin() == SCRIPT_ORIGIN_LOCAL)
{ {
@ -251,7 +259,6 @@ void ScriptsModel::reloadLocalFiles() {
void ScriptsModel::rebuildTree() { void ScriptsModel::rebuildTree() {
for (int i = _treeNodes.size() - 1; i >= 0; i--) { for (int i = _treeNodes.size() - 1; i >= 0; i--) {
if (_treeNodes.at(i)->getType() == TREE_NODE_TYPE_FOLDER) { if (_treeNodes.at(i)->getType() == TREE_NODE_TYPE_FOLDER) {
delete _treeNodes.at(i); delete _treeNodes.at(i);
_treeNodes.removeAt(i); _treeNodes.removeAt(i);
@ -260,18 +267,37 @@ void ScriptsModel::rebuildTree() {
QHash<QString, TreeNodeFolder*> folders; QHash<QString, TreeNodeFolder*> folders;
for (int i = 0; i < _treeNodes.size(); i++) { for (int i = 0; i < _treeNodes.size(); i++) {
TreeNodeBase* node = _treeNodes.at(i); TreeNodeBase* node = _treeNodes.at(i);
qDebug() << "blup" << i << typeid(*node).name(); if (node->getType() == TREE_NODE_TYPE_SCRIPT) {
if (typeid(*node) == typeid(TreeNodeScript)) {
TreeNodeScript* script = static_cast<TreeNodeScript*>(node); TreeNodeScript* script = static_cast<TreeNodeScript*>(node);
TreeNodeFolder* parent = NULL; TreeNodeFolder* parent = NULL;
QString hash; QString hash;
QStringList pathList = script->getFilename().split(tr("/")); QStringList pathList = script->getLocalPath().split(tr("/"));
pathList.removeLast();
QStringList::const_iterator pathIterator; QStringList::const_iterator pathIterator;
for (pathIterator = pathList.constBegin(); pathIterator != pathList.constEnd(); ++pathIterator) { for (pathIterator = pathList.constBegin(); pathIterator != pathList.constEnd(); ++pathIterator) {
hash.append("/" + *pathIterator); hash.append(*pathIterator + "/");
qDebug() << hash; if (!folders.contains(hash)) {
folders[hash] = new TreeNodeFolder(*pathIterator, parent);
}
parent = folders[hash];
} }
script->setParent(parent);
} }
} }
QHash<QString, TreeNodeFolder*>::const_iterator folderIterator;
for (folderIterator = folders.constBegin(); folderIterator != folders.constEnd(); ++folderIterator) {
_treeNodes.append(*folderIterator);
}
folders.clear(); folders.clear();
} }
QList<TreeNodeBase*> ScriptsModel::getFolderNodes(TreeNodeFolder* parent) const {
QList<TreeNodeBase*> result;
for (int i = 0; i < _treeNodes.size(); i++) {
TreeNodeBase* node = _treeNodes.at(i);
if (node->getParent() == parent) {
result.append(node);
}
}
return result;
}

View file

@ -31,28 +31,29 @@ enum TreeNodeType {
class TreeNodeBase { class TreeNodeBase {
public: public:
const TreeNodeFolder* getParent() { return _parent; } TreeNodeFolder* getParent() const { return _parent; }
void setParent(TreeNodeFolder* parent) { _parent = parent; } void setParent(TreeNodeFolder* parent) { _parent = parent; }
TreeNodeType getType() { return _type; } TreeNodeType getType() { return _type; }
const QString& getName() { return _name; };
private: private:
TreeNodeFolder* _parent; TreeNodeFolder* _parent;
TreeNodeType _type; TreeNodeType _type;
protected: protected:
TreeNodeBase(TreeNodeFolder* parent, TreeNodeType type); QString _name;
TreeNodeBase(TreeNodeFolder* parent, const QString& name, TreeNodeType type);
}; };
class TreeNodeScript : public TreeNodeBase { class TreeNodeScript : public TreeNodeBase {
public: public:
TreeNodeScript(const QString& filename, const QString& fullPath, ScriptOrigin origin); TreeNodeScript(const QString& localPath, const QString& fullPath, ScriptOrigin origin);
const QString& getLocalPath() { return _localPath; }
const QString& getFilename() { return _filename; };
const QString& getFullPath() { return _fullPath; }; const QString& getFullPath() { return _fullPath; };
const ScriptOrigin getOrigin() { return _origin; }; const ScriptOrigin getOrigin() { return _origin; };
private: private:
QString _filename; QString _localPath;
QString _fullPath; QString _fullPath;
ScriptOrigin _origin; ScriptOrigin _origin;
}; };
@ -60,8 +61,6 @@ private:
class TreeNodeFolder : public TreeNodeBase { class TreeNodeFolder : public TreeNodeBase {
public: public:
TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent); TreeNodeFolder(const QString& foldername, TreeNodeFolder* parent);
private:
QString _foldername;
}; };
class ScriptsModel : public QAbstractItemModel { class ScriptsModel : public QAbstractItemModel {
@ -70,9 +69,11 @@ public:
ScriptsModel(QObject* parent = NULL); ScriptsModel(QObject* parent = NULL);
QModelIndex index(int row, int column, const QModelIndex& parent) const; QModelIndex index(int row, int column, const QModelIndex& parent) const;
QModelIndex parent(const QModelIndex& child) const; QModelIndex parent(const QModelIndex& child) const;
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const; int rowCount(const QModelIndex& parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const; int columnCount(const QModelIndex& parent = QModelIndex()) const;
TreeNodeBase* getTreeNodeFromIndex(const QModelIndex& index) const;
QList<TreeNodeBase*> getFolderNodes(TreeNodeFolder* parent) const;
enum Role { enum Role {
ScriptPath = Qt::UserRole, ScriptPath = Qt::UserRole,

View file

@ -0,0 +1,44 @@
//
// ScriptsModelFilter.cpp
// interface/src
//
// Created by Thijs Wenker on 01/11/15.
// Copyright 2015 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 "ScriptsModelFilter.h"
ScriptsModelFilter::ScriptsModelFilter(QObject *parent) :
QSortFilterProxyModel(parent) {
}
bool ScriptsModelFilter::lessThan(const QModelIndex& left, const QModelIndex& right) const {
ScriptsModel* scriptsModel = static_cast<ScriptsModel*>(sourceModel());
TreeNodeBase* leftNode = scriptsModel->getTreeNodeFromIndex(left);
TreeNodeBase* rightNode = scriptsModel->getTreeNodeFromIndex(right);
if (leftNode->getType() != rightNode->getType()) {
return leftNode->getType() == TREE_NODE_TYPE_FOLDER;
}
return leftNode->getName() < rightNode->getName();
}
bool ScriptsModelFilter::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const {
if (!filterRegExp().isEmpty()) {
ScriptsModel* scriptsModel = static_cast<ScriptsModel*>(sourceModel());
TreeNodeBase* node = scriptsModel->getFolderNodes(
static_cast<TreeNodeFolder*>(scriptsModel->getTreeNodeFromIndex(sourceParent))).at(sourceRow);
QModelIndex sourceIndex = sourceModel()->index(sourceRow, this->filterKeyColumn(), sourceParent);
if (node->getType() == TREE_NODE_TYPE_FOLDER) {
int rows = scriptsModel->rowCount(sourceIndex);
for (int i = 0; i < rows; i++) {
if (filterAcceptsRow(i, sourceIndex)) {
return true;
}
}
}
}
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
}

View file

@ -0,0 +1,27 @@
//
// ScriptsModelFilter.h
// interface/src
//
// Created by Thijs Wenker on 01/11/15.
// Copyright 2015 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_ScriptsModelFilter_h
#define hifi_ScriptsModelFilter_h
#include "ScriptsModel.h"
#include <QSortFilterProxyModel>
class ScriptsModelFilter : public QSortFilterProxyModel {
Q_OBJECT
public:
ScriptsModelFilter(QObject *parent = NULL);
protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const;
bool lessThan(const QModelIndex& left, const QModelIndex& right) const;
};
#endif // hifi_ScriptsModelFilter_h

View file

@ -33,7 +33,7 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
Qt::WindowCloseButtonHint), Qt::WindowCloseButtonHint),
ui(new Ui::RunningScriptsWidget), ui(new Ui::RunningScriptsWidget),
_signalMapper(this), _signalMapper(this),
_proxyModel(this), _scriptsModelFilter(this),
_scriptsModel(this) { _scriptsModel(this) {
ui->setupUi(this); ui->setupUi(this);
@ -41,16 +41,16 @@ RunningScriptsWidget::RunningScriptsWidget(QWidget* parent) :
ui->filterLineEdit->installEventFilter(this); ui->filterLineEdit->installEventFilter(this);
connect(&_proxyModel, &QSortFilterProxyModel::modelReset, connect(&_scriptsModelFilter, &QSortFilterProxyModel::modelReset,
this, &RunningScriptsWidget::selectFirstInList); this, &RunningScriptsWidget::selectFirstInList);
QString shortcutText = Menu::getInstance()->getActionForOption(MenuOption::ReloadAllScripts)->shortcut().toString(QKeySequence::NativeText); QString shortcutText = Menu::getInstance()->getActionForOption(MenuOption::ReloadAllScripts)->shortcut().toString(QKeySequence::NativeText);
ui->tipLabel->setText("Tip: Use " + shortcutText + " to reload all scripts."); ui->tipLabel->setText("Tip: Use " + shortcutText + " to reload all scripts.");
_proxyModel.setSourceModel(&_scriptsModel); _scriptsModelFilter.setSourceModel(&_scriptsModel);
_proxyModel.sort(0, Qt::AscendingOrder); _scriptsModelFilter.sort(0, Qt::AscendingOrder);
_proxyModel.setDynamicSortFilter(true); _scriptsModelFilter.setDynamicSortFilter(true);
ui->scriptTreeView->setModel(&_proxyModel); ui->scriptTreeView->setModel(&_scriptsModelFilter);
connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &RunningScriptsWidget::updateFileFilter); connect(ui->filterLineEdit, &QLineEdit::textChanged, this, &RunningScriptsWidget::updateFileFilter);
connect(ui->scriptTreeView, &QTreeView::doubleClicked, this, &RunningScriptsWidget::loadScriptFromList); connect(ui->scriptTreeView, &QTreeView::doubleClicked, this, &RunningScriptsWidget::loadScriptFromList);
@ -70,12 +70,12 @@ RunningScriptsWidget::~RunningScriptsWidget() {
void RunningScriptsWidget::updateFileFilter(const QString& filter) { void RunningScriptsWidget::updateFileFilter(const QString& filter) {
QRegExp regex("^.*" + QRegExp::escape(filter) + ".*$", Qt::CaseInsensitive); QRegExp regex("^.*" + QRegExp::escape(filter) + ".*$", Qt::CaseInsensitive);
_proxyModel.setFilterRegExp(regex); _scriptsModelFilter.setFilterRegExp(regex);
selectFirstInList(); selectFirstInList();
} }
void RunningScriptsWidget::loadScriptFromList(const QModelIndex& index) { void RunningScriptsWidget::loadScriptFromList(const QModelIndex& index) {
QVariant scriptFile = _proxyModel.data(index, ScriptsModel::ScriptPath); QVariant scriptFile = _scriptsModelFilter.data(index, ScriptsModel::ScriptPath);
Application::getInstance()->loadScript(scriptFile.toString()); Application::getInstance()->loadScript(scriptFile.toString());
} }
@ -165,8 +165,8 @@ void RunningScriptsWidget::showEvent(QShowEvent* event) {
} }
void RunningScriptsWidget::selectFirstInList() { void RunningScriptsWidget::selectFirstInList() {
if (_proxyModel.rowCount() > 0) { if (_scriptsModelFilter.rowCount() > 0) {
ui->scriptTreeView->setCurrentIndex(_proxyModel.index(0, 0)); ui->scriptTreeView->setCurrentIndex(_scriptsModelFilter.index(0, 0));
} }
} }

View file

@ -18,6 +18,7 @@
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include "ScriptsModel.h" #include "ScriptsModel.h"
#include "ScriptsModelFilter.h"
#include "ScriptsTableWidget.h" #include "ScriptsTableWidget.h"
namespace Ui { namespace Ui {
@ -54,7 +55,7 @@ private slots:
private: private:
Ui::RunningScriptsWidget* ui; Ui::RunningScriptsWidget* ui;
QSignalMapper _signalMapper; QSignalMapper _signalMapper;
QSortFilterProxyModel _proxyModel; ScriptsModelFilter _scriptsModelFilter;
ScriptsModel _scriptsModel; ScriptsModel _scriptsModel;
ScriptsTableWidget* _recentlyLoadedScriptsTable; ScriptsTableWidget* _recentlyLoadedScriptsTable;
QStringList _recentlyLoadedScripts; QStringList _recentlyLoadedScripts;