From a88872a21f9cf943ef0bb2ce796831f51ff219d0 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 14 Mar 2014 17:41:22 -0700 Subject: [PATCH 1/7] Simple class to download files (sync/async) --- libraries/shared/src/FileDownloader.cpp | 42 +++++++++++++++++++++++++ libraries/shared/src/FileDownloader.h | 35 +++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 libraries/shared/src/FileDownloader.cpp create mode 100644 libraries/shared/src/FileDownloader.h diff --git a/libraries/shared/src/FileDownloader.cpp b/libraries/shared/src/FileDownloader.cpp new file mode 100644 index 0000000000..5d4a82ca00 --- /dev/null +++ b/libraries/shared/src/FileDownloader.cpp @@ -0,0 +1,42 @@ +// +// FileDownloader.cpp +// hifi +// +// Created by Clement Brisset on 3/14/14. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// +// + +#include +#include +#include +#include + +#include "FileDownloader.h" + +FileDownloader::FileDownloader(const QUrl dataURL, QObject* parent) : QObject(parent) { + connect(&_networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(processReply(QNetworkReply*))); + + QNetworkRequest request(dataURL); + _networkAccessManager.get(request); +} + +void FileDownloader::processReply(QNetworkReply *reply) { + if (reply->error() != QNetworkReply::NoError) { + emit done(reply->error()); + return; + } + + _downloadedData = reply->readAll(); + reply->deleteLater(); + + emit done(QNetworkReply::NoError); +} + +QByteArray FileDownloader::download(const QUrl dataURL) { + QEventLoop loop; + FileDownloader downloader(dataURL); + connect(&downloader, SIGNAL(done()), &loop, SLOT(quit())); + loop.exec(); + return downloader.getData(); +} \ No newline at end of file diff --git a/libraries/shared/src/FileDownloader.h b/libraries/shared/src/FileDownloader.h new file mode 100644 index 0000000000..892fd10a96 --- /dev/null +++ b/libraries/shared/src/FileDownloader.h @@ -0,0 +1,35 @@ +// +// FileDownloader.h +// hifi +// +// Created by Clement Brisset on 3/14/14. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// +// + +#ifndef __hifi__FileDownloader__ +#define __hifi__FileDownloader__ + +#include +#include + +class FileDownloader : public QObject { +public: + FileDownloader(const QUrl dataURL, QObject* parent = NULL); + QByteArray getData() const { return _downloadedData; } + + static QByteArray download(const QUrl dataURL); + +signals: + void done(QNetworkReply::NetworkError); + +private slots: + void processReply(QNetworkReply* reply); + +private: + QNetworkAccessManager _networkAccessManager; + QByteArray _downloadedData; +}; + + +#endif /* defined(__hifi__FileDownloader__) */ From 6f50ea0faa45112e4b5ec7b1c17e34eec6dc26cc Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 18 Mar 2014 13:55:14 -0700 Subject: [PATCH 2/7] Improved FileDownloader --- libraries/shared/src/FileDownloader.cpp | 43 +++++++++++++++++++------ libraries/shared/src/FileDownloader.h | 13 ++++++-- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/libraries/shared/src/FileDownloader.cpp b/libraries/shared/src/FileDownloader.cpp index 5d4a82ca00..2b65bbd8df 100644 --- a/libraries/shared/src/FileDownloader.cpp +++ b/libraries/shared/src/FileDownloader.cpp @@ -9,12 +9,15 @@ #include #include -#include #include +#include #include "FileDownloader.h" -FileDownloader::FileDownloader(const QUrl dataURL, QObject* parent) : QObject(parent) { +FileDownloader::FileDownloader(const QUrl dataURL, QObject* parent) : + QObject(parent), + _done(false) +{ connect(&_networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(processReply(QNetworkReply*))); QNetworkRequest request(dataURL); @@ -22,21 +25,41 @@ FileDownloader::FileDownloader(const QUrl dataURL, QObject* parent) : QObject(pa } void FileDownloader::processReply(QNetworkReply *reply) { - if (reply->error() != QNetworkReply::NoError) { - emit done(reply->error()); - return; + if (reply->error() == QNetworkReply::NoError) { + _downloadedData = reply->readAll(); } - _downloadedData = reply->readAll(); reply->deleteLater(); - - emit done(QNetworkReply::NoError); + _done = true; + emit done(reply->error()); } -QByteArray FileDownloader::download(const QUrl dataURL) { +void FileDownloader::waitForFile(int timeout) { + QTimer timer; QEventLoop loop; + connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit())); + connect(this, SIGNAL(done(QNetworkReply::NetworkError)), &loop, SLOT(quit())); + + if (!_done) { + if (timeout > 0) { + timer.start(timeout); + } + loop.exec(); + } +} + +QByteArray FileDownloader::download(const QUrl dataURL, int timeout) { + QTimer timer; + QEventLoop loop; + connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit)); + FileDownloader downloader(dataURL); - connect(&downloader, SIGNAL(done()), &loop, SLOT(quit())); + connect(&downloader, SIGNAL(done(QNetworkReply::NetworkError)), &loop, SLOT(quit())); + + if (timeout > 0) { + timer.start(timeout); + } loop.exec(); + return downloader.getData(); } \ No newline at end of file diff --git a/libraries/shared/src/FileDownloader.h b/libraries/shared/src/FileDownloader.h index 892fd10a96..a2ed0b8ccb 100644 --- a/libraries/shared/src/FileDownloader.h +++ b/libraries/shared/src/FileDownloader.h @@ -12,13 +12,20 @@ #include #include +#include class FileDownloader : public QObject { + Q_OBJECT + public: FileDownloader(const QUrl dataURL, QObject* parent = NULL); - QByteArray getData() const { return _downloadedData; } - static QByteArray download(const QUrl dataURL); + void waitForFile(int timeout = 0); + + QByteArray getData() const { return _downloadedData; } + bool done() { return _done; } + + static QByteArray download(const QUrl dataURL, int timeout = 0); signals: void done(QNetworkReply::NetworkError); @@ -29,6 +36,8 @@ private slots: private: QNetworkAccessManager _networkAccessManager; QByteArray _downloadedData; + + bool _done; }; From 388f8d480a3b59fe791c8b1abd31832ecabf0627 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 18 Mar 2014 13:58:23 -0700 Subject: [PATCH 3/7] Added the model browser --- interface/src/ModelBrowser.cpp | 127 +++++++++++++++++++++++++++++++++ interface/src/ModelBrowser.h | 59 +++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 interface/src/ModelBrowser.cpp create mode 100644 interface/src/ModelBrowser.h diff --git a/interface/src/ModelBrowser.cpp b/interface/src/ModelBrowser.cpp new file mode 100644 index 0000000000..cf401d6b75 --- /dev/null +++ b/interface/src/ModelBrowser.cpp @@ -0,0 +1,127 @@ +// +// ModelBrowser.cpp +// hifi +// +// Created by Clement on 3/17/14. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ModelBrowser.h" + +static const int DOWNLOAD_TIMEOUT = 1000; +static const QString CONTAINER_NAME = "Contents"; +static const QString KEY_NAME = "Key"; + +ModelBrowser::ModelBrowser(QWidget* parent) : + QWidget(parent), + _downloader(QUrl(S3_URL)) +{ +} + +QString ModelBrowser::browse(ModelType modelType) { + _models.clear(); + if (!parseXML(modelType)) { + return QString(); + } + + + QDialog dialog(this); + dialog.setWindowTitle("Browse models"); + + QGridLayout* layout = new QGridLayout(&dialog); + dialog.setLayout(layout); + + QLineEdit* searchBar = new QLineEdit(&dialog); + layout->addWidget(searchBar, 0, 0); + + ListView* listView = new ListView(&dialog); + listView->setEditTriggers(QAbstractItemView::NoEditTriggers); + layout->addWidget(listView, 1, 0); + listView->connect(searchBar, SIGNAL(textChanged(const QString&)), SLOT(keyboardSearch(const QString&))); + dialog.connect(listView, SIGNAL(doubleClicked(const QModelIndex&)), SLOT(accept())); + + QStringListModel* model = new QStringListModel(_models.keys(), listView); + model->sort(0); + listView->setModel(model); + + QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + layout->addWidget(buttons, 2, 0); + dialog.connect(buttons, SIGNAL(accepted()), SLOT(accept())); + dialog.connect(buttons, SIGNAL(rejected()), SLOT(reject())); + + if (dialog.exec() == QDialog::Rejected) { + return QString(); + } + + QString selectedKey = model->data(listView->currentIndex(), Qt::DisplayRole).toString(); + return _models[selectedKey]; +} + +void ModelBrowser::browseHead() { + QString model = browse(Head); + emit selectedHead(model); +} + +void ModelBrowser::browseSkeleton() { + QString model = browse(Skeleton); + emit selectedSkeleton(model); +} + +bool ModelBrowser::parseXML(ModelType modelType) { + _downloader.waitForFile(DOWNLOAD_TIMEOUT); + QString location; + switch (modelType) { + case Head: + location = HEAD_MODELS_LOCATION; + break; + case Skeleton: + location = SKELETON_MODELS_LOCATION; + break; + default: + return false; + } + + QXmlStreamReader xml(_downloader.getData()); + QRegExp rx(location + "[^/]*fst"); + + // Read xml until the end or an error is detected + while(!xml.atEnd() && !xml.hasError()) { + if(xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == CONTAINER_NAME) { + while(!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == CONTAINER_NAME)) { + // If a file is find, process it + if(xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == KEY_NAME) { + xml.readNext(); + if (rx.exactMatch(xml.text().toString())) { + // Add the found file to the list + _models.insert(QFileInfo(xml.text().toString()).baseName(), + S3_URL + "/" + xml.text().toString()); + } + } + xml.readNext(); + } + } + xml.readNext(); + } + + // Error handling + if(xml.hasError()) { + _models.clear(); + QMessageBox::critical(this, + "ModelBrowser::ModelBrowser()", + xml.errorString(), + QMessageBox::Ok); + return false; + } + return true; +} \ No newline at end of file diff --git a/interface/src/ModelBrowser.h b/interface/src/ModelBrowser.h new file mode 100644 index 0000000000..9b7cf51ab3 --- /dev/null +++ b/interface/src/ModelBrowser.h @@ -0,0 +1,59 @@ +// +// ModelBrowser.h +// hifi +// +// Created by Clement on 3/17/14. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// + +#ifndef __hifi__ModelBrowser__ +#define __hifi__ModelBrowser__ + +#include + +#include +#include + +static const QString S3_URL = "http://highfidelity-public.s3-us-west-1.amazonaws.com"; +static const QString HEAD_MODELS_LOCATION = "meshes/"; +static const QString SKELETON_MODELS_LOCATION = "meshes/"; + +enum ModelType { + Head, + Skeleton +}; + +class ModelBrowser : public QWidget { + Q_OBJECT + +public: + ModelBrowser(QWidget* parent = NULL); + + QString browse(ModelType modelType); + +signals: + void selectedHead(QString); + void selectedSkeleton(QString); + +public slots: + void browseHead(); + void browseSkeleton(); + +private: + FileDownloader _downloader; + QHash _models; + + bool parseXML(ModelType modelType); +}; + +class ListView : public QListView { + Q_OBJECT +public: + ListView(QWidget* parent) : QListView(parent) {} + public slots: + void keyboardSearch(const QString& text) { + QAbstractItemView::keyboardSearch(text); + } +}; + +#endif /* defined(__hifi__ModelBrowser__) */ From 0a80f8fcd6b8e124f37cb113d088a5e4155756b9 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 18 Mar 2014 13:59:08 -0700 Subject: [PATCH 4/7] Added browse buttons in the menu --- interface/src/Menu.cpp | 53 ++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index ca059a53da..e0f2ba14ff 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -24,11 +24,12 @@ #include #include #include -#include +#include #include #include #include +#include #include "Application.h" #include "Menu.h" @@ -36,6 +37,7 @@ #include "Util.h" #include "InfoView.h" #include "ui/MetavoxelEditor.h" +#include "ModelBrowser.h" Menu* Menu::_instance = NULL; @@ -692,6 +694,9 @@ void Menu::loginForCurrentDomain() { void Menu::editPreferences() { Application* applicationInstance = Application::getInstance(); + ModelBrowser browser; + + const QString BROWSE_BUTTON_TEXT = "Browse"; QDialog dialog(applicationInstance->getWindow()); dialog.setWindowTitle("Interface Preferences"); @@ -702,17 +707,33 @@ void Menu::editPreferences() { QFormLayout* form = new QFormLayout(); layout->addLayout(form, 1); + + QHBoxLayout headModelLayout; QString faceURLString = applicationInstance->getAvatar()->getHead()->getFaceModel().getURL().toString(); - QLineEdit* faceURLEdit = new QLineEdit(faceURLString); - faceURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); - faceURLEdit->setPlaceholderText(DEFAULT_HEAD_MODEL_URL.toString()); - form->addRow("Face URL:", faceURLEdit); - + QLineEdit headURLEdit(faceURLString); + QPushButton headBrowseButton(BROWSE_BUTTON_TEXT); + connect(&headBrowseButton, SIGNAL(clicked()), &browser, SLOT(browseHead())); + connect(&browser, SIGNAL(selectedHead(QString)), &headURLEdit, SLOT(setText(QString))); + headURLEdit.setReadOnly(true); + headURLEdit.setMinimumWidth(QLINE_MINIMUM_WIDTH); + headURLEdit.setPlaceholderText(DEFAULT_HEAD_MODEL_URL.toString()); + headModelLayout.addWidget(&headURLEdit); + headModelLayout.addWidget(&headBrowseButton); + form->addRow("Head URL:", &headModelLayout); + + QHBoxLayout skeletonModelLayout; QString skeletonURLString = applicationInstance->getAvatar()->getSkeletonModel().getURL().toString(); - QLineEdit* skeletonURLEdit = new QLineEdit(skeletonURLString); - skeletonURLEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH); - skeletonURLEdit->setPlaceholderText(DEFAULT_BODY_MODEL_URL.toString()); - form->addRow("Skeleton URL:", skeletonURLEdit); + QLineEdit skeletonURLEdit(skeletonURLString); + QPushButton SkeletonBrowseButton(BROWSE_BUTTON_TEXT); + connect(&SkeletonBrowseButton, SIGNAL(clicked()), &browser, SLOT(browseSkeleton())); + connect(&browser, SIGNAL(selectedSkeleton(QString)), &skeletonURLEdit, SLOT(setText(QString))); + skeletonURLEdit.setReadOnly(true); + skeletonURLEdit.setMinimumWidth(QLINE_MINIMUM_WIDTH); + skeletonURLEdit.setPlaceholderText(DEFAULT_BODY_MODEL_URL.toString()); + skeletonModelLayout.addWidget(&skeletonURLEdit); + skeletonModelLayout.addWidget(&SkeletonBrowseButton); + form->addRow("Skeleton URL:", &skeletonModelLayout); + QString displayNameString = applicationInstance->getAvatar()->getDisplayName(); QLineEdit* displayNameEdit = new QLineEdit(displayNameString); @@ -774,21 +795,17 @@ void Menu::editPreferences() { int ret = dialog.exec(); if (ret == QDialog::Accepted) { - QUrl faceModelURL(faceURLEdit->text()); - bool shouldDispatchIdentityPacket = false; - if (faceModelURL.toString() != faceURLString) { + if (headURLEdit.text() != faceURLString && !headURLEdit.text().isEmpty()) { // change the faceModelURL in the profile, it will also update this user's BlendFace - applicationInstance->getAvatar()->setFaceModelURL(faceModelURL); + applicationInstance->getAvatar()->setFaceModelURL(QUrl(headURLEdit.text())); shouldDispatchIdentityPacket = true; } - QUrl skeletonModelURL(skeletonURLEdit->text()); - - if (skeletonModelURL.toString() != skeletonURLString) { + if (skeletonURLEdit.text() != skeletonURLString && !skeletonURLEdit.text().isEmpty()) { // change the skeletonModelURL in the profile, it will also update this user's Body - applicationInstance->getAvatar()->setSkeletonModelURL(skeletonModelURL); + applicationInstance->getAvatar()->setSkeletonModelURL(QUrl(skeletonURLEdit.text())); shouldDispatchIdentityPacket = true; } From 1e2dabfd5e04f2d202e9d000b9ae8d9e077de698 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 18 Mar 2014 15:09:54 -0700 Subject: [PATCH 5/7] Changed addresses to new models locations --- interface/src/ModelBrowser.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ModelBrowser.h b/interface/src/ModelBrowser.h index 9b7cf51ab3..42dd65ab27 100644 --- a/interface/src/ModelBrowser.h +++ b/interface/src/ModelBrowser.h @@ -15,8 +15,8 @@ #include static const QString S3_URL = "http://highfidelity-public.s3-us-west-1.amazonaws.com"; -static const QString HEAD_MODELS_LOCATION = "meshes/"; -static const QString SKELETON_MODELS_LOCATION = "meshes/"; +static const QString HEAD_MODELS_LOCATION = "models/heads/"; +static const QString SKELETON_MODELS_LOCATION = "models/skeletons/"; enum ModelType { Head, From 76c2a9fdad11521763fa4a525b569d10e90cca46 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 18 Mar 2014 17:36:05 -0700 Subject: [PATCH 6/7] Modified Browser to be able to dowload all the fst file when there are more than 1000 --- interface/src/Menu.cpp | 11 ++-- interface/src/ModelBrowser.cpp | 105 ++++++++++++++++++++------------- interface/src/ModelBrowser.h | 21 ++++--- 3 files changed, 82 insertions(+), 55 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index e0f2ba14ff..8352adf9f2 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -694,7 +694,8 @@ void Menu::loginForCurrentDomain() { void Menu::editPreferences() { Application* applicationInstance = Application::getInstance(); - ModelBrowser browser; + ModelBrowser headBrowser(Head); + ModelBrowser skeletonBrowser(Skeleton); const QString BROWSE_BUTTON_TEXT = "Browse"; @@ -712,8 +713,8 @@ void Menu::editPreferences() { QString faceURLString = applicationInstance->getAvatar()->getHead()->getFaceModel().getURL().toString(); QLineEdit headURLEdit(faceURLString); QPushButton headBrowseButton(BROWSE_BUTTON_TEXT); - connect(&headBrowseButton, SIGNAL(clicked()), &browser, SLOT(browseHead())); - connect(&browser, SIGNAL(selectedHead(QString)), &headURLEdit, SLOT(setText(QString))); + connect(&headBrowseButton, SIGNAL(clicked()), &headBrowser, SLOT(browse())); + connect(&headBrowser, SIGNAL(selected (QString)), &headURLEdit, SLOT(setText(QString))); headURLEdit.setReadOnly(true); headURLEdit.setMinimumWidth(QLINE_MINIMUM_WIDTH); headURLEdit.setPlaceholderText(DEFAULT_HEAD_MODEL_URL.toString()); @@ -725,8 +726,8 @@ void Menu::editPreferences() { QString skeletonURLString = applicationInstance->getAvatar()->getSkeletonModel().getURL().toString(); QLineEdit skeletonURLEdit(skeletonURLString); QPushButton SkeletonBrowseButton(BROWSE_BUTTON_TEXT); - connect(&SkeletonBrowseButton, SIGNAL(clicked()), &browser, SLOT(browseSkeleton())); - connect(&browser, SIGNAL(selectedSkeleton(QString)), &skeletonURLEdit, SLOT(setText(QString))); + connect(&SkeletonBrowseButton, SIGNAL(clicked()), &skeletonBrowser, SLOT(browse())); + connect(&skeletonBrowser, SIGNAL(selected(QString)), &skeletonURLEdit, SLOT(setText(QString))); skeletonURLEdit.setReadOnly(true); skeletonURLEdit.setMinimumWidth(QLINE_MINIMUM_WIDTH); skeletonURLEdit.setPlaceholderText(DEFAULT_BODY_MODEL_URL.toString()); diff --git a/interface/src/ModelBrowser.cpp b/interface/src/ModelBrowser.cpp index cf401d6b75..e03081273f 100644 --- a/interface/src/ModelBrowser.cpp +++ b/interface/src/ModelBrowser.cpp @@ -19,23 +19,36 @@ #include "ModelBrowser.h" -static const int DOWNLOAD_TIMEOUT = 1000; +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"; -ModelBrowser::ModelBrowser(QWidget* parent) : - QWidget(parent), - _downloader(QUrl(S3_URL)) -{ +ModelBrowser::ModelBrowser(ModelType modelType, QWidget* parent) : QWidget(parent), _type(modelType) { + QUrl url(S3_URL); + QUrlQuery query; + + if (_type == Head) { + query.addQueryItem(PREFIX_PARAMETER_NAME, HEAD_MODELS_LOCATION); + } else if (_type == Skeleton) { + query.addQueryItem(PREFIX_PARAMETER_NAME, SKELETON_MODELS_LOCATION); + } + url.setQuery(query); + + _downloader = new FileDownloader(url); + connect(_downloader, SIGNAL(done(QNetworkReply::NetworkError)), SLOT(downloadFinished())); } -QString ModelBrowser::browse(ModelType modelType) { - _models.clear(); - if (!parseXML(modelType)) { - return QString(); - } - - +ModelBrowser::~ModelBrowser() { + delete _downloader; +} + +void ModelBrowser::downloadFinished() { + parseXML(_downloader->getData()); +} + +void ModelBrowser::browse() { QDialog dialog(this); dialog.setWindowTitle("Browse models"); @@ -61,47 +74,38 @@ QString ModelBrowser::browse(ModelType modelType) { dialog.connect(buttons, SIGNAL(rejected()), SLOT(reject())); if (dialog.exec() == QDialog::Rejected) { - return QString(); + return; } QString selectedKey = model->data(listView->currentIndex(), Qt::DisplayRole).toString(); - return _models[selectedKey]; -} - -void ModelBrowser::browseHead() { - QString model = browse(Head); - emit selectedHead(model); -} - -void ModelBrowser::browseSkeleton() { - QString model = browse(Skeleton); - emit selectedSkeleton(model); -} - -bool ModelBrowser::parseXML(ModelType modelType) { - _downloader.waitForFile(DOWNLOAD_TIMEOUT); - QString location; - switch (modelType) { - case Head: - location = HEAD_MODELS_LOCATION; - break; - case Skeleton: - location = SKELETON_MODELS_LOCATION; - break; - default: - return false; - } - QXmlStreamReader xml(_downloader.getData()); - QRegExp rx(location + "[^/]*fst"); + emit selected(_models[selectedKey]); +} + +bool ModelBrowser::parseXML(QByteArray xmlFile) { + QXmlStreamReader xml(xmlFile); + QRegExp rx(".*fst"); + bool truncated = false; + QString lastKey; // Read xml until the end or an error is detected 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)) { + // Let's check if there is more + 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 a file is find, process it if(xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == KEY_NAME) { xml.readNext(); + lastKey = xml.text().toString(); if (rx.exactMatch(xml.text().toString())) { // Add the found file to the list _models.insert(QFileInfo(xml.text().toString()).baseName(), @@ -123,5 +127,24 @@ bool ModelBrowser::parseXML(ModelType modelType) { QMessageBox::Ok); return false; } + + // If we didn't all the files, download the next ones + if (truncated) { + QUrl url(S3_URL); + QUrlQuery query; + + if (_type == Head) { + query.addQueryItem(PREFIX_PARAMETER_NAME, HEAD_MODELS_LOCATION); + } else if (_type == Skeleton) { + query.addQueryItem(PREFIX_PARAMETER_NAME, SKELETON_MODELS_LOCATION); + } + query.addQueryItem(MARKER_PARAMETER_NAME, lastKey); + url.setQuery(query); + + delete _downloader; + _downloader = new FileDownloader(url); + connect(_downloader, SIGNAL(done(QNetworkReply::NetworkError)), SLOT(downloadFinished())); + } + return true; } \ No newline at end of file diff --git a/interface/src/ModelBrowser.h b/interface/src/ModelBrowser.h index 42dd65ab27..9eb27f5db6 100644 --- a/interface/src/ModelBrowser.h +++ b/interface/src/ModelBrowser.h @@ -27,25 +27,28 @@ class ModelBrowser : public QWidget { Q_OBJECT public: - ModelBrowser(QWidget* parent = NULL); - - QString browse(ModelType modelType); + ModelBrowser(ModelType modelType, QWidget* parent = NULL); + ~ModelBrowser(); signals: - void selectedHead(QString); - void selectedSkeleton(QString); + void selected(QString); public slots: - void browseHead(); - void browseSkeleton(); + void browse(); + +private slots: + void downloadFinished(); private: - FileDownloader _downloader; + ModelType _type; + FileDownloader* _downloader; QHash _models; - bool parseXML(ModelType modelType); + bool parseXML(QByteArray xmlFile); }; + + class ListView : public QListView { Q_OBJECT public: From a80f81c2462954c43340a87818c5e1676f353191 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 18 Mar 2014 17:48:17 -0700 Subject: [PATCH 7/7] typo --- 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 8352adf9f2..da5ca8e17c 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -714,7 +714,7 @@ void Menu::editPreferences() { QLineEdit headURLEdit(faceURLString); QPushButton headBrowseButton(BROWSE_BUTTON_TEXT); connect(&headBrowseButton, SIGNAL(clicked()), &headBrowser, SLOT(browse())); - connect(&headBrowser, SIGNAL(selected (QString)), &headURLEdit, SLOT(setText(QString))); + connect(&headBrowser, SIGNAL(selected(QString)), &headURLEdit, SLOT(setText(QString))); headURLEdit.setReadOnly(true); headURLEdit.setMinimumWidth(QLINE_MINIMUM_WIDTH); headURLEdit.setPlaceholderText(DEFAULT_HEAD_MODEL_URL.toString());