Conflicts:
	interface/interface_en.ts
	interface/src/Menu.h
This commit is contained in:
Andrzej Kapolka 2014-03-13 16:56:06 -07:00
commit 95e59d7004
14 changed files with 255 additions and 256 deletions

View file

@ -1,161 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US">
<context>
<name>Application</name>
<message>
<location filename="src/Application.cpp" line="1353"/>
<source>Export Voxels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="1354"/>
<source>Sparse Voxel Octree Files (*.svo)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="3561"/>
<source>Open Script</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="3562"/>
<source>JavaScript Files (*.js)</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ChatWindow</name>
<message>
<location filename="ui/chatWindow.ui" line="14"/>
<location filename="../build/interface/ui_chatWindow.h" line="141"/>
<source>Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/chatWindow.ui" line="41"/>
<location filename="../build/interface/ui_chatWindow.h" line="142"/>
<source>Connecting to XMPP...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/chatWindow.ui" line="62"/>
<location filename="../build/interface/ui_chatWindow.h" line="143"/>
<source> online now:</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<location filename="src/ui/ChatWindow.cpp" line="115"/>
<source>day</source>
<translation>
<numerusform>%n day</numerusform>
<numerusform>%n days</numerusform>
</translation>
</message>
<message numerus="yes">
<location filename="src/ui/ChatWindow.cpp" line="115"/>
<source>hour</source>
<translation>
<numerusform>%n hour</numerusform>
<numerusform>%n hours</numerusform>
</translation>
</message>
<message numerus="yes">
<location filename="src/ui/ChatWindow.cpp" line="115"/>
<source>minute</source>
<translation>
<numerusform>%n minute</numerusform>
<numerusform>%n minutes</numerusform>
</translation>
</message>
<message numerus="yes">
<source>second</source>
<translation type="vanished">
<numerusform>%n second</numerusform>
<numerusform>%n seconds</numerusform>
</translation>
</message>
<message>
<location filename="src/ui/ChatWindow.cpp" line="170"/>
<source>%1 online now:</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Dialog</name>
<message>
<location filename="ui/updateDialog.ui" line="20"/>
<location filename="ui/updateDialog.ui" line="73"/>
<location filename="../build/interface/ui_updateDialog.h" line="137"/>
<location filename="../build/interface/ui_updateDialog.h" line="138"/>
<source>Update Required</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/updateDialog.ui" line="129"/>
<location filename="../build/interface/ui_updateDialog.h" line="140"/>
<source>Download</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/updateDialog.ui" line="151"/>
<location filename="../build/interface/ui_updateDialog.h" line="141"/>
<source>Skip Version</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/updateDialog.ui" line="173"/>
<location filename="../build/interface/ui_updateDialog.h" line="142"/>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Menu</name>
<message>
<location filename="src/Menu.cpp" line="427"/>
<source>Open .ini config file</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Menu.cpp" line="429"/>
<location filename="src/Menu.cpp" line="441"/>
<source>Text files (*.ini)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Menu.cpp" line="439"/>
<source>Save .ini config file</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<location filename="src/ImportDialog.cpp" line="22"/>
<location filename="src/ImportDialog.cpp" line="23"/>
<source>Import Voxels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/ImportDialog.cpp" line="24"/>
<source>Loading ...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/ImportDialog.cpp" line="25"/>
<source>Place voxels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/ImportDialog.cpp" line="26"/>
<source>&lt;b&gt;Import&lt;/b&gt; %1 as voxels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/ImportDialog.cpp" line="27"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View file

@ -27,6 +27,7 @@
#include <QColorDialog>
#include <QDesktopWidget>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QImage>
#include <QKeyEvent>
#include <QMainWindow>
@ -62,6 +63,7 @@
#include <UUID.h>
#include <OctreeSceneStats.h>
#include <LocalVoxelsList.h>
#include <FstReader.h>
#include "Application.h"
#include "ClipboardScriptingInterface.h"
@ -290,7 +292,14 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
ResourceCache::setNetworkAccessManager(_networkAccessManager);
ResourceCache::setRequestLimit(3);
_window->setCentralWidget(_glWidget);
QWidget* centralWidget = new QWidget();
QHBoxLayout* mainLayout = new QHBoxLayout();
mainLayout->setSpacing(0);
mainLayout->setContentsMargins(0, 0, 0, 0);
centralWidget->setLayout(mainLayout);
_glWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
centralWidget->layout()->addWidget(_glWidget);
_window->setCentralWidget(centralWidget);
restoreSizeAndPosition();
@ -3464,7 +3473,10 @@ void Application::reloadAllScripts() {
}
void Application::uploadFST() {
_fstReader.zip();
FstReader reader;
if (reader.zip()) {
reader.send();
}
}
void Application::removeScriptName(const QString& fileNameString) {

View file

@ -28,7 +28,6 @@
#include <ParticleEditPacketSender.h>
#include <ScriptEngine.h>
#include <OctreeQuery.h>
#include <FstReader.h>
#include "Audio.h"
#include "BandwidthMeter.h"
@ -479,8 +478,6 @@ private:
TouchEvent _lastTouchEvent;
Overlays _overlays;
FstReader _fstReader;
};
#endif /* defined(__interface__Application__) */

View file

@ -11,18 +11,26 @@
#include "GLCanvas.h"
#include <QMimeData>
#include <QUrl>
#include <QMainWindow>
GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer, QGL::NoStencilBuffer)) {
GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer, QGL::NoStencilBuffer)),
_throttleRendering(false),
_idleRenderInterval(100)
{
}
void GLCanvas::initializeGL() {
Application::getInstance()->initializeGL();
setAttribute(Qt::WA_AcceptTouchEvents);
setAcceptDrops(true);
connect(Application::getInstance(), SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(activeChanged(Qt::ApplicationState)));
connect(&_frameTimer, SIGNAL(timeout()), this, SLOT(throttleRender()));
}
void GLCanvas::paintGL() {
Application::getInstance()->paintGL();
if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) {
Application::getInstance()->paintGL();
}
}
void GLCanvas::resizeGL(int width, int height) {
@ -49,6 +57,38 @@ void GLCanvas::mouseReleaseEvent(QMouseEvent* event) {
Application::getInstance()->mouseReleaseEvent(event);
}
void GLCanvas::activeChanged(Qt::ApplicationState state) {
switch (state) {
case Qt::ApplicationActive:
// If we're active, stop the frame timer and the throttle.
_frameTimer.stop();
_throttleRendering = false;
break;
case Qt::ApplicationSuspended:
case Qt::ApplicationHidden:
// If we're hidden or are about to suspend, don't render anything.
_throttleRendering = false;
_frameTimer.stop();
break;
default:
// Otherwise, throttle.
if (!_throttleRendering) {
_frameTimer.start(_idleRenderInterval);
_throttleRendering = true;
}
break;
}
}
void GLCanvas::throttleRender() {
_frameTimer.start(_idleRenderInterval);
if (!Application::getInstance()->getWindow()->isMinimized()) {
Application::getInstance()->paintGL();
}
}
int updateTime = 0;
bool GLCanvas::event(QEvent* event) {
switch (event->type()) {

View file

@ -10,13 +10,19 @@
#define __hifi__GLCanvas__
#include <QGLWidget>
#include <QTimer>
/// customized canvas that simply forwards requests/events to the singleton application
class GLCanvas : public QGLWidget {
Q_OBJECT
public:
GLCanvas();
protected:
QTimer _frameTimer;
bool _throttleRendering;
int _idleRenderInterval;
virtual void initializeGL();
virtual void paintGL();
virtual void resizeGL(int width, int height);
@ -34,6 +40,10 @@ protected:
virtual void dragEnterEvent(QDragEnterEvent *event);
virtual void dropEvent(QDropEvent* event);
private slots:
void activeChanged(Qt::ApplicationState state);
void throttleRender();
};
#endif /* defined(__hifi__GLCanvas__) */

View file

@ -129,7 +129,10 @@ Menu::Menu() :
this,
SLOT(goTo()));
addDisabledActionAndSeparator(fileMenu, "Upload/Browse");
addActionToQMenuAndActionHash(fileMenu, MenuOption::UploaderAvatarHead, 0, Application::getInstance(), SLOT(uploadFST()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::UploaderAvatarSkeleton, 0, Application::getInstance(), SLOT(uploadFST()));
addDisabledActionAndSeparator(fileMenu, "Settings");
addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsImport, 0, this, SLOT(importSettings()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::SettingsExport, 0, this, SLOT(exportSettings()));
@ -161,7 +164,6 @@ Menu::Menu() :
QMenu* toolsMenu = addMenu("Tools");
addActionToQMenuAndActionHash(toolsMenu, MenuOption::MetavoxelEditor, 0, this, SLOT(showMetavoxelEditor()));
addActionToQMenuAndActionHash(toolsMenu, MenuOption::FstUploader, 0, Application::getInstance(), SLOT(uploadFST()));
_chatAction = addActionToQMenuAndActionHash(toolsMenu,
MenuOption::Chat,
@ -1044,22 +1046,20 @@ void Menu::showChat() {
if (!_chatWindow) {
_chatWindow = new ChatWindow();
QMainWindow* mainWindow = Application::getInstance()->getWindow();
_chatWindow->setGeometry(mainWindow->width() - _chatWindow->width(),
mainWindow->geometry().y(),
_chatWindow->width(),
mainWindow->height());
QBoxLayout* boxLayout = static_cast<QBoxLayout*>(mainWindow->centralWidget()->layout());
boxLayout->addWidget(_chatWindow, 0, Qt::AlignRight);
} else {
if (!_chatWindow->isVisible()) {
_chatWindow->show();
}
}
if (!_chatWindow->isVisible()) {
_chatWindow->show();
}
_chatWindow->raise();
}
void Menu::toggleChat() {
#ifdef HAVE_QXMPP
_chatAction->setEnabled(XmppClient::getInstance().getXMPPClient().isConnected());
if (!_chatAction->isEnabled() && _chatWindow) {
_chatWindow->close();
_chatWindow->hide();
}
#endif
}

View file

@ -243,7 +243,6 @@ namespace MenuOption {
const QString FirstPerson = "First Person";
const QString FrameTimer = "Show Timer";
const QString FrustumRenderMode = "Render Mode";
const QString FstUploader = "Upload .fst file";
const QString Fullscreen = "Fullscreen";
const QString FullscreenMirror = "Fullscreen Mirror";
const QString GlowMode = "Cycle Glow Mode";
@ -292,6 +291,8 @@ namespace MenuOption {
const QString StopAllScripts = "Stop All Scripts";
const QString TestPing = "Test Ping";
const QString TransmitterDrive = "Transmitter Drive";
const QString UploaderAvatarHead = "Upload Avatar Head";
const QString UploaderAvatarSkeleton = "Upload Avatar Skeleton";
const QString Visage = "Visage";
const QString Quit = "Quit";
const QString Voxels = "Voxels";

View file

@ -28,7 +28,7 @@ const int NUM_MESSAGES_TO_TIME_STAMP = 20;
const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?))://\\S+)");
ChatWindow::ChatWindow() :
QDialog(Application::getInstance()->getGLWidget(), Qt::CustomizeWindowHint),
QWidget(),
ui(new Ui::ChatWindow),
numMessagesAfterLastTimeStamp(0)
{
@ -39,7 +39,6 @@ ChatWindow::ChatWindow() :
ui->messagePlainTextEdit->installEventFilter(this);
setAttribute(Qt::WA_DeleteOnClose);
#ifdef HAVE_QXMPP
const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient();
if (xmppClient.isConnected()) {
@ -72,8 +71,18 @@ ChatWindow::~ChatWindow() {
delete ui;
}
void ChatWindow::reject() {
hide();
void ChatWindow::keyPressEvent(QKeyEvent* event) {
QWidget::keyPressEvent(event);
if (event->key() == Qt::Key_Escape) {
hide();
}
}
void ChatWindow::showEvent(QShowEvent* event) {
QWidget::showEvent(event);
if (!event->spontaneous()) {
ui->messagePlainTextEdit->setFocus();
}
}
bool ChatWindow::eventFilter(QObject* sender, QEvent* event) {

View file

@ -9,9 +9,9 @@
#ifndef __interface__ChatWindow__
#define __interface__ChatWindow__
#include <QDialog>
#include <QDateTime>
#include <QTimer>
#include <QWidget>
#include <Application.h>
@ -26,14 +26,15 @@ namespace Ui {
class ChatWindow;
}
class ChatWindow : public QDialog {
class ChatWindow : public QWidget {
Q_OBJECT
public:
ChatWindow();
~ChatWindow();
virtual void reject();
virtual void keyPressEvent(QKeyEvent *event);
virtual void showEvent(QShowEvent* event);
protected:
bool eventFilter(QObject* sender, QEvent* event);

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ChatWindow</class>
<widget class="QDialog" name="ChatWindow">
<widget class="QWidget" name="ChatWindow">
<property name="geometry">
<rect>
<x>0</x>
@ -10,9 +10,18 @@
<height>608</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>400</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Chat</string>
</property>
<property name="styleSheet">
<string notr="true">font-family: Helvetica, Arial, sans-serif;</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
@ -100,7 +109,7 @@
<item>
<widget class="QScrollArea" name="messagesScrollArea">
<property name="styleSheet">
<string notr="true">margin-top: 12px; font-family: Helvetica, Arial, sans-serif;</string>
<string notr="true">margin-top: 12px;</string>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
@ -114,7 +123,7 @@
<x>0</x>
<y>0</y>
<width>358</width>
<height>452</height>
<height>464</height>
</rect>
</property>
<property name="styleSheet">
@ -154,6 +163,12 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>60</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px;</string>
</property>

View file

@ -13,6 +13,7 @@
#include <QtCore/QStringList>
#include <QtCore/QUrlQuery>
#include <QtNetwork/QNetworkRequest>
#include <QHttpMultiPart>
#include "NodeList.h"
#include "PacketHeaders.h"
@ -99,21 +100,25 @@ void AccountManager::setAuthURL(const QUrl& authURL) {
}
void AccountManager::authenticatedRequest(const QString& path, QNetworkAccessManager::Operation operation,
const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray) {
const JSONCallbackParameters& callbackParams,
const QByteArray& dataByteArray,
QHttpMultiPart* dataMultiPart) {
QMetaObject::invokeMethod(this, "invokedRequest",
Q_ARG(const QString&, path),
Q_ARG(QNetworkAccessManager::Operation, operation),
Q_ARG(const JSONCallbackParameters&, callbackParams),
Q_ARG(const QByteArray&, dataByteArray));
Q_ARG(const QByteArray&, dataByteArray),
Q_ARG(QHttpMultiPart*, dataMultiPart));
}
void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::Operation operation,
const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray) {
const JSONCallbackParameters& callbackParams,
const QByteArray& dataByteArray, QHttpMultiPart* dataMultiPart) {
if (!_networkAccessManager) {
_networkAccessManager = new QNetworkAccessManager(this);
}
if (hasValidAccessToken()) {
QNetworkRequest authenticatedRequest;
@ -140,11 +145,18 @@ void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::
case QNetworkAccessManager::PostOperation:
case QNetworkAccessManager::PutOperation:
authenticatedRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
if (operation == QNetworkAccessManager::PostOperation) {
networkReply = _networkAccessManager->post(authenticatedRequest, dataByteArray);
if (dataMultiPart) {
if (operation == QNetworkAccessManager::PostOperation) {
networkReply = _networkAccessManager->post(authenticatedRequest, dataMultiPart);
} else {
networkReply = _networkAccessManager->put(authenticatedRequest, dataMultiPart);
}
} else {
networkReply = _networkAccessManager->put(authenticatedRequest, dataByteArray);
if (operation == QNetworkAccessManager::PostOperation) {
networkReply = _networkAccessManager->post(authenticatedRequest, dataByteArray);
} else {
networkReply = _networkAccessManager->put(authenticatedRequest, dataByteArray);
}
}
break;

View file

@ -39,7 +39,8 @@ public:
void authenticatedRequest(const QString& path,
QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation,
const JSONCallbackParameters& callbackParams = JSONCallbackParameters(),
const QByteArray& dataByteArray = QByteArray());
const QByteArray& dataByteArray = QByteArray(),
QHttpMultiPart* dataMultiPart = NULL);
const QUrl& getAuthURL() const { return _authURL; }
void setAuthURL(const QUrl& authURL);
@ -77,7 +78,9 @@ private:
void operator=(AccountManager const& other); // not implemented
Q_INVOKABLE void invokedRequest(const QString& path, QNetworkAccessManager::Operation operation,
const JSONCallbackParameters& callbackParams, const QByteArray& dataByteArray);
const JSONCallbackParameters& callbackParams,
const QByteArray& dataByteArray,
QHttpMultiPart* dataMultiPart);
QUrl _authURL;
QNetworkAccessManager* _networkAccessManager;

View file

@ -10,16 +10,36 @@
#include <QDebug>
#include <QFile>
#include <QTextStream>
#include <QDir>
#include <QFileDialog>
#include <QStandardPaths>
#include <QHttpMultiPart>
#include <QVariant>
#include "AccountManager.h"
#include "FstReader.h"
FstReader::FstReader() {
static const QString NAME_FIELD = "name";
static const QString FILENAME_FIELD = "filename";
static const QString TEXDIR_FIELD = "texdir";
static const QString LOD_FIELD = "lod";
static const QString MODEL_URL = "/api/v1/models";
static const int MAX_SIZE = 10 * 1024 * 1024; // 10 MB
FstReader::FstReader() :
_lodCount(-1),
_texturesCount(-1),
_readyToSend(false),
_dataMultiPart(new QHttpMultiPart(QHttpMultiPart::FormDataType))
{
}
FstReader::~FstReader() {
delete _dataMultiPart;
}
bool FstReader::zip() {
// File Dialog
@ -34,12 +54,18 @@ bool FstReader::zip() {
qDebug() << "[ERROR] Could not open FST file : " << fst.fileName();
return false;
}
// Compress and copy the fst
if (!compressFile(QFileInfo(fst).filePath(), _zipDir.path() + "/" + QFileInfo(fst).fileName())) {
return false;
}
_totalSize += QFileInfo(fst).size();
if (!addPart(_zipDir.path() + "/" + QFileInfo(fst).fileName(),
QString("fst"))) {
return false;
}
qDebug() << "Reading FST file : " << QFileInfo(fst).filePath();
QTemporaryDir tempRootDir(_zipDir.path() + "/" + QFileInfo(fst).baseName());
QDir rootDir(tempRootDir.path());
// Let's read through the FST file
QTextStream stream(&fst);
QList<QString> line;
@ -49,59 +75,75 @@ bool FstReader::zip() {
continue;
}
if (_totalSize > MAX_SIZE) {
qDebug() << "[ERROR] Model too big, over " << MAX_SIZE << " Bytes.";
return false;
}
// according to what is read, we modify the command
if (line.first() == filenameField) {
QFileInfo fbx(QFileInfo(fst).path() + "/" + line.at(1));
if (line.first() == NAME_FIELD) {
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;"
" name=\"model_name\"");
textPart.setBody(line[1].toUtf8());
_dataMultiPart->append(textPart);
} else if (line.first() == FILENAME_FIELD) {
QFileInfo fbx(QFileInfo(fst).path() + "/" + line[1]);
if (!fbx.exists() || !fbx.isFile()) { // Check existence
qDebug() << "[ERROR] FBX file " << fbx.absoluteFilePath() << " doesn't exist.";
return false;
} else if (fbx.size() > MAX_FBX_SIZE) { // Check size
qDebug() << "[ERROR] FBX file " << fbx.absoluteFilePath() << " too big, over " << MAX_FBX_SIZE << " MB.";
return false;
} else { // Compress and copy
compressFile(fbx.filePath(),
rootDir.path() + "/" + line.at(1));
}
} else if (line.first() == texdirField) { // Check existence
QFileInfo texdir(QFileInfo(fst).path() + "/" + line.at(1));
// Compress and copy
if (!compressFile(fbx.filePath(), _zipDir.path() + "/" + line[1])) {
return false;
}
_totalSize += fbx.size();
if (!addPart(_zipDir.path() + "/" + line[1], "fbx")) {
return false;
}
} else if (line.first() == TEXDIR_FIELD) { // Check existence
QFileInfo texdir(QFileInfo(fst).path() + "/" + line[1]);
if (!texdir.exists() || !texdir.isDir()) {
qDebug() << "[ERROR] Texture directory " << texdir.absolutePath() << " doesn't exist.";
return false;
}
QDir newTexdir(rootDir.canonicalPath() + "/" + line.at(1));
if (!newTexdir.exists() && !rootDir.mkpath(line.at(1))) { // Create texdir
qDebug() << "[ERROR] Couldn't create " << line.at(1) << ".";
if (!addTextures(texdir)) { // Recursive compress and copy
return false;
}
if (!addTextures(texdir, newTexdir)) { // Recursive compress and copy
return false;
}
} else if (line.first() == lodField) {
QFileInfo lod(QFileInfo(fst).path() + "/" + line.at(1));
} else if (line.first() == LOD_FIELD) {
QFileInfo lod(QFileInfo(fst).path() + "/" + line[1]);
if (!lod.exists() || !lod.isFile()) { // Check existence
qDebug() << "[ERROR] FBX file " << lod.absoluteFilePath() << " doesn't exist.";
return false;
} else if (lod.size() > MAX_FBX_SIZE) { // Check size
qDebug() << "[ERROR] FBX file " << lod.absoluteFilePath() << " too big, over " << MAX_FBX_SIZE << " MB.";\
}
// Compress and copy
if (!compressFile(lod.filePath(), _zipDir.path() + "/" + line[1])) {
return false;
}
_totalSize += lod.size();
if (!addPart(_zipDir.path() + "/" + line[1], QString("lod%1").arg(++_lodCount))) {
return false;
} else { // Compress and copy
compressFile(lod.filePath(), rootDir.path() + "/" + line.at(1));
}
}
}
// Compress and copy the fst
compressFile(fst.fileName(),
rootDir.path() + "/" + QFileInfo(fst).fileName());
_readyToSend = true;
return true;
}
bool FstReader::send() {
if (!_readyToSend) {
return false;
}
tempRootDir.setAutoRemove(false);
AccountManager::getInstance().authenticatedRequest(MODEL_URL, QNetworkAccessManager::PostOperation, JSONCallbackParameters(), QByteArray(), _dataMultiPart);
return true;
}
bool FstReader::addTextures(QFileInfo& texdir, QDir newTexdir) {
bool FstReader::addTextures(const QFileInfo& texdir) {
QStringList filter;
filter << "*.png" << "*.tiff" << "*.jpg" << "*.jpeg";
filter << "*.png" << "*.tif" << "*.jpg" << "*.jpeg";
QFileInfoList list = QDir(texdir.filePath()).entryInfoList(filter,
QDir::Files |
@ -110,19 +152,17 @@ bool FstReader::addTextures(QFileInfo& texdir, QDir newTexdir) {
QDir::NoSymLinks);
foreach (QFileInfo info, list) {
if (info.isFile()) {
if (info.size() > MAX_TEXTURE_SIZE) {
qDebug() << "[ERROR] Texture " << info.absoluteFilePath()
<< "too big, file over " << MAX_TEXTURE_SIZE << " Bytes.";
// Compress and copy
if (!compressFile(info.filePath(), _zipDir.path() + "/" + info.fileName())) {
return false;
}
_totalSize += info.size();
if (!addPart(_zipDir.path() + "/" + info.fileName(),
QString("texture%1").arg(++_texturesCount))) {
return false;
}
compressFile(info.canonicalFilePath(), newTexdir.path() + "/" + info.fileName());
} else if (info.isDir()) {
if (newTexdir.mkdir(info.fileName())) {
qDebug() << "[ERROR] Couldn't create texdir.";
return false;
}
QDir texdirChild(newTexdir.canonicalPath() + "/" + info.fileName());
if (!addTextures(info, QDir(info.canonicalFilePath()))) {
if (!addTextures(info)) {
return false;
}
} else {
@ -153,7 +193,24 @@ bool FstReader::compressFile(const QString &inFileName, const QString &outFileNa
}
bool FstReader::addPart(const QString &path, const QString& name) {
QFile* file = new QFile(path);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << "[ERROR] Couldn't open " << file->fileName();
return false;
}
QHttpPart part;
part.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;"
" name=\"" + name.toUtf8() + "\";"
" filename=\"" + QFileInfo(*file).fileName().toUtf8() + "\"");
part.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream");
part.setBodyDevice(file);
_dataMultiPart->append(part);
file->setParent(_dataMultiPart);
return true;
}

View file

@ -10,28 +10,31 @@
#ifndef __hifi__FstReader__
#define __hifi__FstReader__
#include <QString>
#include <QList>
#include <QTemporaryDir>
static const QString filenameField = "filename";
static const QString texdirField = "texdir";
static const QString lodField = "lod";
static const int MAX_FBX_SIZE = 1024 * 1024; // 1 MB
static const int MAX_TEXTURE_SIZE = 1024 * 1024; // 1 MB
class QHttpMultiPart;
class FstReader {
public:
FstReader();
~FstReader();
bool zip();
bool send();
private:
QTemporaryDir _zipDir;
int _lodCount;
int _texturesCount;
int _totalSize;
bool _readyToSend;
bool addTextures(QFileInfo& texdir, QDir newTexdir);
QHttpMultiPart* _dataMultiPart;
bool addTextures(const QFileInfo& texdir);
bool compressFile(const QString& inFileName, const QString& outFileName);
bool addPart(const QString& path, const QString& name);
};
#endif /* defined(__hifi__FstReader__) */