From 855f6fcf598c1eae6a866bff69fd78f9d1b4923d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 12 Mar 2014 11:46:41 -0700 Subject: [PATCH 01/16] Moved Avatar upload to file Menu --- interface/src/Menu.cpp | 6 ++++-- interface/src/Menu.h | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index f0d4d8c133..26747aad86 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -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, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 380fe2d3b7..1e5ada9e84 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -242,7 +242,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"; @@ -291,6 +290,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 Quit = "Quit"; const QString Voxels = "Voxels"; const QString VoxelMode = "Cycle Voxel Mode"; From b9ee60ba41107635d4cdc370b0d62e7d3c7fbd35 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 12 Mar 2014 11:47:47 -0700 Subject: [PATCH 02/16] FstReader not a member anymore --- interface/src/Application.cpp | 6 +++++- interface/src/Application.h | 3 --- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 13e3d36fad..8e64ba4d04 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -62,6 +62,7 @@ #include #include #include +#include #include "Application.h" #include "ClipboardScriptingInterface.h" @@ -3432,7 +3433,10 @@ void Application::reloadAllScripts() { } void Application::uploadFST() { - _fstReader.zip(); + FstReader reader; + if(reader.zip()) { + reader.send(); + } } void Application::removeScriptName(const QString& fileNameString) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 70b7347654..5b1f2e8c03 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -28,7 +28,6 @@ #include #include #include -#include #include "Audio.h" #include "BandwidthMeter.h" @@ -472,8 +471,6 @@ private: TouchEvent _lastTouchEvent; Overlays _overlays; - - FstReader _fstReader; }; #endif /* defined(__interface__Application__) */ From 3aa534d47c3a99d40626fa425b25708f5336ac56 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 12 Mar 2014 11:48:41 -0700 Subject: [PATCH 03/16] Added the send method --- libraries/shared/src/FstReader.cpp | 80 +++++++++++++++--------------- libraries/shared/src/FstReader.h | 17 +++++-- 2 files changed, 54 insertions(+), 43 deletions(-) diff --git a/libraries/shared/src/FstReader.cpp b/libraries/shared/src/FstReader.cpp index fa2aebb2fe..d94f036af0 100644 --- a/libraries/shared/src/FstReader.cpp +++ b/libraries/shared/src/FstReader.cpp @@ -17,7 +17,6 @@ #include "FstReader.h" FstReader::FstReader() { - } @@ -37,8 +36,7 @@ bool FstReader::zip() { qDebug() << "Reading FST file : " << QFileInfo(fst).filePath(); - QTemporaryDir tempRootDir(_zipDir.path() + "/" + QFileInfo(fst).baseName()); - QDir rootDir(tempRootDir.path()); + QDir rootDir(_zipDir.path()); // Let's read through the FST file QTextStream stream(&fst); @@ -50,56 +48,66 @@ bool FstReader::zip() { } // according to what is read, we modify the command - if (line.first() == filenameField) { - QFileInfo fbx(QFileInfo(fst).path() + "/" + line.at(1)); + if (line.first() == nameField) { + _modelName = line[1]; + } else if (line.first() == filenameField) { + 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)); + _fbxFile = rootDir.path() + "/" + line[1]; + _totalSize += fbx.size(); + compressFile(fbx.filePath(), _fbxFile); } } else if (line.first() == texdirField) { // Check existence - QFileInfo texdir(QFileInfo(fst).path() + "/" + line.at(1)); + 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) << "."; - return false; - } - if (!addTextures(texdir, newTexdir)) { // Recursive compress and copy + if (!addTextures(texdir)) { // Recursive compress and copy return false; } } else if (line.first() == lodField) { - QFileInfo lod(QFileInfo(fst).path() + "/" + line.at(1)); + 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.";\ - return false; + //return false; } else { // Compress and copy - compressFile(lod.filePath(), rootDir.path() + "/" + line.at(1)); + _lodFiles.push_back(rootDir.path() + "/" + line[1]); + _totalSize += lod.size(); + compressFile(lod.filePath(), _lodFiles.back()); } } } // Compress and copy the fst - compressFile(fst.fileName(), - rootDir.path() + "/" + QFileInfo(fst).fileName()); - - tempRootDir.setAutoRemove(false); + _fstFile = rootDir.path() + "/" + QFileInfo(fst).fileName(); + _totalSize += QFileInfo(fst).size(); + compressFile(fst.fileName(), _fstFile); return true; } -bool FstReader::addTextures(QFileInfo& texdir, QDir newTexdir) { +bool FstReader::send() { + QString command = QString("curl -F \"model_name=%1\"").arg(_modelName); + + command += QString(" -F \"fst=@%1\" -F \"fbx=@%2\"").arg(_fstFile, _fbxFile); + for (int i = 0; i < _lodFiles.size(); ++i) { + command += QString(" -F \"lod%1=@%2\"").arg(i).arg(_lodFiles[i]); + } + for (int i = 0; i < _textureFiles.size(); ++i) { + command += QString(" -F \"lod%1=@%2\"").arg(i).arg(_textureFiles[i]); + } + command += " http://localhost:3000/api/v1/models/?access_token\\=017894b7312316a2b5025613fcc58c13bc701da9b797cca34b60aae9d1c53acb --trace-ascii /dev/stdout"; + + qDebug() << "[DEBUG] " << command; + + return true; +} + +bool FstReader::addTextures(QFileInfo& texdir) { QStringList filter; filter << "*.png" << "*.tiff" << "*.jpg" << "*.jpeg"; @@ -110,19 +118,11 @@ 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."; - return false; - } - compressFile(info.canonicalFilePath(), newTexdir.path() + "/" + info.fileName()); + _textureFiles.push_back(_zipDir.path() + "/" + info.fileName()); + _totalSize += info.size(); + compressFile(info.canonicalFilePath(), _textureFiles.back()); } 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 { diff --git a/libraries/shared/src/FstReader.h b/libraries/shared/src/FstReader.h index 44cd3f95cd..c5816ea415 100644 --- a/libraries/shared/src/FstReader.h +++ b/libraries/shared/src/FstReader.h @@ -14,23 +14,34 @@ #include #include + +static const QString nameField = "name"; 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 +static const int MAX_SIZE = 1024 * 1024; // 1 MB class FstReader { public: FstReader(); bool zip(); + bool send(); private: QTemporaryDir _zipDir; - bool addTextures(QFileInfo& texdir, QDir newTexdir); + QString _modelName; + QString _fstFile; + QString _fbxFile; + QStringList _lodFiles; + QStringList _textureFiles; + + int _totalSize; + + + bool addTextures(QFileInfo& texdir); bool compressFile(const QString& inFileName, const QString& outFileName); }; From 9c61f12926719adff0d7305f77461daa52b3faee Mon Sep 17 00:00:00 2001 From: Geenz Date: Wed, 12 Mar 2014 19:10:26 -0400 Subject: [PATCH 04/16] Support for an idle render time step. The basics of this is, if the application has changed its active state then we only call paintGL every N milliseconds. Currently the default time step is 100 milliseconds. --- interface/src/GLCanvas.cpp | 29 +++++++++++++++++++++++++++-- interface/src/GLCanvas.h | 8 ++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 7bc79e56d8..a098af7fbe 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -12,17 +12,21 @@ #include #include -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(), &Application::focusChanged, this, &GLCanvas::activeChanged); + connect(&_frameTimer, &QTimer::timeout, this, &GLCanvas::throttleRender); } void GLCanvas::paintGL() { - Application::getInstance()->paintGL(); + if (!_throttleRendering) { + Application::getInstance()->paintGL(); + } } void GLCanvas::resizeGL(int width, int height) { @@ -49,6 +53,27 @@ void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { Application::getInstance()->mouseReleaseEvent(event); } +void GLCanvas::activeChanged() +{ + if (!isActiveWindow()) + { + if (!_throttleRendering) + { + _frameTimer.start(_idleRenderInterval); + _throttleRendering = true; + } + } else { + _frameTimer.stop(); + _throttleRendering = false; + } +} + +void GLCanvas::throttleRender() +{ + _frameTimer.start(_idleRenderInterval); + Application::getInstance()->paintGL(); +} + int updateTime = 0; bool GLCanvas::event(QEvent* event) { switch (event->type()) { diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index 0f0cb5c7d0..7e4a4d0334 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -10,6 +10,7 @@ #define __hifi__GLCanvas__ #include +#include /// customized canvas that simply forwards requests/events to the singleton application class GLCanvas : public QGLWidget { @@ -17,6 +18,10 @@ public: GLCanvas(); protected: + QTimer _frameTimer; + bool _throttleRendering; + int _idleRenderInterval; + virtual void initializeGL(); virtual void paintGL(); virtual void resizeGL(int width, int height); @@ -34,6 +39,9 @@ protected: virtual void dragEnterEvent(QDragEnterEvent *event); virtual void dropEvent(QDropEvent* event); + + void activeChanged(); + void throttleRender(); }; #endif /* defined(__hifi__GLCanvas__) */ From e27af75ad2b00b8c6eab3b802a0b4850f9bad49c Mon Sep 17 00:00:00 2001 From: Geenz Date: Wed, 12 Mar 2014 20:49:58 -0400 Subject: [PATCH 05/16] Use QApplication::applicationState to detect if we're in the background. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit May want to expand upon this at some point; if we’re hidden we most definitely *do not* want to render anything --- interface/src/GLCanvas.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index a098af7fbe..dc76858e1b 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -53,12 +53,9 @@ void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { Application::getInstance()->mouseReleaseEvent(event); } -void GLCanvas::activeChanged() -{ - if (!isActiveWindow()) - { - if (!_throttleRendering) - { +void GLCanvas::activeChanged() { + if (Application::applicationState() != Qt::ApplicationActive) { + if (!_throttleRendering) { _frameTimer.start(_idleRenderInterval); _throttleRendering = true; } From 292f37154bab0feaf189fe3eef169119303b0f59 Mon Sep 17 00:00:00 2001 From: Geenz Date: Wed, 12 Mar 2014 21:08:55 -0400 Subject: [PATCH 06/16] Use the applicationStateChanged signal. --- interface/src/GLCanvas.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index dc76858e1b..52fd91130c 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -19,7 +19,7 @@ void GLCanvas::initializeGL() { Application::getInstance()->initializeGL(); setAttribute(Qt::WA_AcceptTouchEvents); setAcceptDrops(true); - connect(Application::getInstance(), &Application::focusChanged, this, &GLCanvas::activeChanged); + connect(Application::getInstance(), &Application::applicationStateChanged, this, &GLCanvas::activeChanged); connect(&_frameTimer, &QTimer::timeout, this, &GLCanvas::throttleRender); } From d580f177a3f93cbbc5158c637e396248be5dd8cc Mon Sep 17 00:00:00 2001 From: Geenz Date: Wed, 12 Mar 2014 21:17:54 -0400 Subject: [PATCH 07/16] Refactor if..else into a switch. Also support the hidden and suspended states. --- interface/src/GLCanvas.cpp | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 52fd91130c..f2a88fea6d 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -54,14 +54,27 @@ void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { } void GLCanvas::activeChanged() { - if (Application::applicationState() != Qt::ApplicationActive) { - if (!_throttleRendering) { - _frameTimer.start(_idleRenderInterval); - _throttleRendering = true; - } - } else { - _frameTimer.stop(); - _throttleRendering = false; + switch (Application::applicationState()) { + 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; } } From 442ca145da90a46620eb3495afc541b2aff382e8 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Thu, 13 Mar 2014 14:07:21 +0200 Subject: [PATCH 08/16] Hid the chat window rather than close it in order to preserve sent messages. --- interface/interface_en.ts | 8 ++++---- interface/src/Menu.cpp | 2 ++ interface/src/ui/ChatWindow.cpp | 7 +++++++ interface/src/ui/ChatWindow.h | 2 ++ interface/ui/chatWindow.ui | 4 ++-- 5 files changed, 17 insertions(+), 6 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 72e5ee3d3e..1d962393d7 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -45,7 +45,7 @@ - + day %n day @@ -53,7 +53,7 @@ - + hour %n hour @@ -61,7 +61,7 @@ - + minute %n minute @@ -76,7 +76,7 @@ - + %1 online now: diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 95b94bdcbf..00ae0a3772 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1043,6 +1043,8 @@ void Menu::showChat() { mainWindow->geometry().y(), _chatWindow->width(), mainWindow->height()); + } + if (!_chatWindow->isVisible()) { _chatWindow->show(); } _chatWindow->raise(); diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 3a1c26ee35..d4f257c0f7 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -50,6 +50,7 @@ ChatWindow::ChatWindow() : startTimerForTimeStamps(); } else { ui->numOnlineLabel->hide(); + ui->closeButton->hide(); ui->usersWidget->hide(); ui->messagesScrollArea->hide(); ui->messagePlainTextEdit->hide(); @@ -71,6 +72,10 @@ ChatWindow::~ChatWindow() { delete ui; } +void ChatWindow::reject() { + hide(); +} + bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { Q_UNUSED(sender); @@ -136,9 +141,11 @@ void ChatWindow::startTimerForTimeStamps() { void ChatWindow::connected() { ui->connectingToXMPPLabel->hide(); ui->numOnlineLabel->show(); + ui->closeButton->show(); ui->usersWidget->show(); ui->messagesScrollArea->show(); ui->messagePlainTextEdit->show(); + ui->messagePlainTextEdit->setFocus(); #ifdef HAVE_QXMPP const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); connect(publicChatRoom, SIGNAL(participantsChanged()), this, SLOT(participantsChanged())); diff --git a/interface/src/ui/ChatWindow.h b/interface/src/ui/ChatWindow.h index 9250da8933..57da4da45d 100644 --- a/interface/src/ui/ChatWindow.h +++ b/interface/src/ui/ChatWindow.h @@ -33,6 +33,8 @@ public: ChatWindow(); ~ChatWindow(); + virtual void reject(); + protected: bool eventFilter(QObject* sender, QEvent* event); diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index 9959c638b2..ecb4d79c41 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -185,10 +185,10 @@ closeButton clicked() ChatWindow - accept() + hide() - 342 + 390 42 From 2e119fa0fe24152e95472f4928ee187f6c51effc Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 13 Mar 2014 11:41:15 -0400 Subject: [PATCH 09/16] Skip rendering when we're minimized. --- interface/src/GLCanvas.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index f2a88fea6d..bf99608c07 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -11,6 +11,7 @@ #include "GLCanvas.h" #include #include +#include GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer, QGL::NoStencilBuffer)), _throttleRendering(false), _idleRenderInterval(100) { } @@ -24,7 +25,7 @@ void GLCanvas::initializeGL() { } void GLCanvas::paintGL() { - if (!_throttleRendering) { + if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) { Application::getInstance()->paintGL(); } } @@ -78,10 +79,11 @@ void GLCanvas::activeChanged() { } } -void GLCanvas::throttleRender() -{ +void GLCanvas::throttleRender() { _frameTimer.start(_idleRenderInterval); - Application::getInstance()->paintGL(); + if (!Application::getInstance()->getWindow()->isMinimized()) { + Application::getInstance()->paintGL(); + } } int updateTime = 0; From b2a29cb84f282b6eae3b3f4d6ce81509b43c7dec Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 13 Mar 2014 10:56:19 -0700 Subject: [PATCH 10/16] Fixes for Linux build. --- interface/CMakeLists.txt | 6 +----- interface/interface_en.ts | 8 ++++---- interface/src/Application.cpp | 2 -- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 1cb0344f86..f39e7d7e50 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -230,11 +230,7 @@ if (APPLE) RUNTIME DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/install" COMPONENT Runtime ) else (APPLE) - # remove and then copy the resources files beside the executable - add_custom_command(TARGET ${TARGET_NAME} POST_BUILD - COMMAND "${CMAKE_COMMAND}" -E remove_directory - $/resources - ) + # copy the resources files beside the executable add_custom_command(TARGET ${TARGET_NAME} POST_BUILD COMMAND "${CMAKE_COMMAND}" -E copy_directory "${PROJECT_SOURCE_DIR}/resources" diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 1d962393d7..80433032dc 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -4,22 +4,22 @@ Application - + Export Voxels - + Sparse Voxel Octree Files (*.svo) - + Open Script - + JavaScript Files (*.js) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8091e58545..96129e0161 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -121,8 +121,6 @@ void messageHandler(QtMsgType type, const QMessageLogContext& context, const QSt QString& Application::resourcesPath() { #ifdef Q_OS_MAC static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/../Resources/"; -#elif defined Q_OS_LINUX - static QString staticResourcePath = "resources/"; #else static QString staticResourcePath = QCoreApplication::applicationDirPath() + "/resources/"; #endif From e5b5778caf2ba2e9b80edd17e25ed4a414211359 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Mar 2014 15:04:22 -0700 Subject: [PATCH 11/16] Upload FST --- libraries/shared/src/AccountManager.cpp | 31 ++++-- libraries/shared/src/AccountManager.h | 7 +- libraries/shared/src/FstReader.cpp | 141 +++++++++++++++++------- libraries/shared/src/FstReader.h | 26 ++--- 4 files changed, 138 insertions(+), 67 deletions(-) diff --git a/libraries/shared/src/AccountManager.cpp b/libraries/shared/src/AccountManager.cpp index 7915a60690..6517d080ed 100644 --- a/libraries/shared/src/AccountManager.cpp +++ b/libraries/shared/src/AccountManager.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "NodeList.h" #include "PacketHeaders.h" @@ -30,6 +31,7 @@ Q_DECLARE_METATYPE(OAuthAccessToken) Q_DECLARE_METATYPE(DataServerAccountInfo) Q_DECLARE_METATYPE(QNetworkAccessManager::Operation) Q_DECLARE_METATYPE(JSONCallbackParameters) +Q_DECLARE_METATYPE(QHttpMultiPart) const QString ACCOUNTS_GROUP = "accounts"; @@ -99,21 +101,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 +146,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; diff --git a/libraries/shared/src/AccountManager.h b/libraries/shared/src/AccountManager.h index ee821fa43c..bfe84f392e 100644 --- a/libraries/shared/src/AccountManager.h +++ b/libraries/shared/src/AccountManager.h @@ -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; diff --git a/libraries/shared/src/FstReader.cpp b/libraries/shared/src/FstReader.cpp index d94f036af0..0e99a7b2f4 100644 --- a/libraries/shared/src/FstReader.cpp +++ b/libraries/shared/src/FstReader.cpp @@ -10,15 +10,38 @@ #include #include #include -#include #include #include +#include +#include + +#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() { + if (_dataMultiPart) { + delete _dataMultiPart; + } +} bool FstReader::zip() { // File Dialog @@ -33,11 +56,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(); - - QDir rootDir(_zipDir.path()); - // Let's read through the FST file QTextStream stream(&fst); QList line; @@ -47,20 +77,34 @@ 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() == nameField) { - _modelName = line[1]; - } else if (line.first() == filenameField) { + if (line.first() == NAME_FIELD) { + QHttpPart textPart; + textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;" + " name=\"model_name\""); + //textPart.setRawHeader("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 { // Compress and copy - _fbxFile = rootDir.path() + "/" + line[1]; - _totalSize += fbx.size(); - compressFile(fbx.filePath(), _fbxFile); } - } else if (line.first() == texdirField) { // Check existence + // 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."; @@ -69,47 +113,41 @@ bool FstReader::zip() { if (!addTextures(texdir)) { // Recursive compress and copy return false; } - } else if (line.first() == lodField) { + } 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 { // Compress and copy - _lodFiles.push_back(rootDir.path() + "/" + line[1]); - _totalSize += lod.size(); - compressFile(lod.filePath(), _lodFiles.back()); + return false; + } + // 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; } } } - // Compress and copy the fst - _fstFile = rootDir.path() + "/" + QFileInfo(fst).fileName(); - _totalSize += QFileInfo(fst).size(); - compressFile(fst.fileName(), _fstFile); - + _readyToSend = true; return true; } bool FstReader::send() { - QString command = QString("curl -F \"model_name=%1\"").arg(_modelName); - - command += QString(" -F \"fst=@%1\" -F \"fbx=@%2\"").arg(_fstFile, _fbxFile); - for (int i = 0; i < _lodFiles.size(); ++i) { - command += QString(" -F \"lod%1=@%2\"").arg(i).arg(_lodFiles[i]); + if (!_readyToSend) { + return false; } - for (int i = 0; i < _textureFiles.size(); ++i) { - command += QString(" -F \"lod%1=@%2\"").arg(i).arg(_textureFiles[i]); - } - command += " http://localhost:3000/api/v1/models/?access_token\\=017894b7312316a2b5025613fcc58c13bc701da9b797cca34b60aae9d1c53acb --trace-ascii /dev/stdout"; - qDebug() << "[DEBUG] " << command; + AccountManager::getInstance().authenticatedRequest(MODEL_URL, QNetworkAccessManager::PostOperation, JSONCallbackParameters(), QByteArray(), _dataMultiPart); + _dataMultiPart = NULL; return true; } -bool FstReader::addTextures(QFileInfo& texdir) { +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 | @@ -118,9 +156,15 @@ bool FstReader::addTextures(QFileInfo& texdir) { QDir::NoSymLinks); foreach (QFileInfo info, list) { if (info.isFile()) { - _textureFiles.push_back(_zipDir.path() + "/" + info.fileName()); + // Compress and copy + if (!compressFile(info.filePath(), _zipDir.path() + "/" + info.fileName())) { + return false; + } _totalSize += info.size(); - compressFile(info.canonicalFilePath(), _textureFiles.back()); + if (!addPart(_zipDir.path() + "/" + info.fileName(), + QString("texture%1").arg(++_texturesCount))) { + return false; + } } else if (info.isDir()) { if (!addTextures(info)) { return false; @@ -153,7 +197,26 @@ 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); + + qDebug() << QFileInfo(*file).fileName().toUtf8(); + + return true; +} diff --git a/libraries/shared/src/FstReader.h b/libraries/shared/src/FstReader.h index c5816ea415..aab42bd967 100644 --- a/libraries/shared/src/FstReader.h +++ b/libraries/shared/src/FstReader.h @@ -10,39 +10,31 @@ #ifndef __hifi__FstReader__ #define __hifi__FstReader__ -#include -#include #include - -static const QString nameField = "name"; -static const QString filenameField = "filename"; -static const QString texdirField = "texdir"; -static const QString lodField = "lod"; - -static const int MAX_SIZE = 1024 * 1024; // 1 MB +class QHttpMultiPart; class FstReader { public: FstReader(); + ~FstReader(); bool zip(); bool send(); private: QTemporaryDir _zipDir; - - QString _modelName; - QString _fstFile; - QString _fbxFile; - QStringList _lodFiles; - QStringList _textureFiles; - + int _lodCount; + int _texturesCount; int _totalSize; + bool _readyToSend; + + QHttpMultiPart* _dataMultiPart; - bool addTextures(QFileInfo& texdir); + 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__) */ From 423f26f669db865b41de3fdb10da79a639b254fd Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 13 Mar 2014 15:26:02 -0700 Subject: [PATCH 12/16] Review comments --- interface/src/Application.cpp | 2 +- libraries/shared/src/AccountManager.cpp | 1 - libraries/shared/src/FstReader.cpp | 8 +------- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0bc8b0f22d..aed212c692 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3462,7 +3462,7 @@ void Application::reloadAllScripts() { void Application::uploadFST() { FstReader reader; - if(reader.zip()) { + if (reader.zip()) { reader.send(); } } diff --git a/libraries/shared/src/AccountManager.cpp b/libraries/shared/src/AccountManager.cpp index 6517d080ed..bb32896ca0 100644 --- a/libraries/shared/src/AccountManager.cpp +++ b/libraries/shared/src/AccountManager.cpp @@ -31,7 +31,6 @@ Q_DECLARE_METATYPE(OAuthAccessToken) Q_DECLARE_METATYPE(DataServerAccountInfo) Q_DECLARE_METATYPE(QNetworkAccessManager::Operation) Q_DECLARE_METATYPE(JSONCallbackParameters) -Q_DECLARE_METATYPE(QHttpMultiPart) const QString ACCOUNTS_GROUP = "accounts"; diff --git a/libraries/shared/src/FstReader.cpp b/libraries/shared/src/FstReader.cpp index 0e99a7b2f4..d82ddf68a3 100644 --- a/libraries/shared/src/FstReader.cpp +++ b/libraries/shared/src/FstReader.cpp @@ -38,9 +38,7 @@ FstReader::FstReader() : } FstReader::~FstReader() { - if (_dataMultiPart) { - delete _dataMultiPart; - } + delete _dataMultiPart; } bool FstReader::zip() { @@ -87,7 +85,6 @@ bool FstReader::zip() { QHttpPart textPart; textPart.setHeader(QNetworkRequest::ContentDispositionHeader, "form-data;" " name=\"model_name\""); - //textPart.setRawHeader("name", "\"model_name\""); textPart.setBody(line[1].toUtf8()); _dataMultiPart->append(textPart); } else if (line.first() == FILENAME_FIELD) { @@ -141,7 +138,6 @@ bool FstReader::send() { AccountManager::getInstance().authenticatedRequest(MODEL_URL, QNetworkAccessManager::PostOperation, JSONCallbackParameters(), QByteArray(), _dataMultiPart); - _dataMultiPart = NULL; return true; } @@ -213,8 +209,6 @@ bool FstReader::addPart(const QString &path, const QString& name) { _dataMultiPart->append(part); file->setParent(_dataMultiPart); - qDebug() << QFileInfo(*file).fileName().toUtf8(); - return true; } From 4523ae742e0b2d018a443a13265106f16b39d0be Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 13 Mar 2014 18:51:14 -0400 Subject: [PATCH 13/16] =?UTF-8?q?Tweak=20in=20code=20styling=20per=20Brad?= =?UTF-8?q?=E2=80=99s=20feedback,=20along=20with=20using=20SIGNAL=20and=20?= =?UTF-8?q?SLOT=20instead=20of=20function=20pointers=20directly.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- interface/src/GLCanvas.cpp | 13 ++++++++----- interface/src/GLCanvas.h | 6 ++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index bf99608c07..249f7a373d 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -13,15 +13,18 @@ #include #include -GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer, QGL::NoStencilBuffer)), _throttleRendering(false), _idleRenderInterval(100) { +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(), &Application::applicationStateChanged, this, &GLCanvas::activeChanged); - connect(&_frameTimer, &QTimer::timeout, this, &GLCanvas::throttleRender); + connect(Application::getInstance(), SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(activeChanged(Qt::ApplicationState))); + connect(&_frameTimer, SIGNAL(timeout()), this, SLOT(throttleRender())); } void GLCanvas::paintGL() { @@ -54,8 +57,8 @@ void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { Application::getInstance()->mouseReleaseEvent(event); } -void GLCanvas::activeChanged() { - switch (Application::applicationState()) { +void GLCanvas::activeChanged(Qt::ApplicationState state) { + switch (state) { case Qt::ApplicationActive: // If we're active, stop the frame timer and the throttle. _frameTimer.stop(); diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index 7e4a4d0334..e6dcc38977 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -14,6 +14,7 @@ /// customized canvas that simply forwards requests/events to the singleton application class GLCanvas : public QGLWidget { + Q_OBJECT public: GLCanvas(); protected: @@ -39,8 +40,9 @@ protected: virtual void dragEnterEvent(QDragEnterEvent *event); virtual void dropEvent(QDropEvent* event); - - void activeChanged(); + +private slots: + void activeChanged(Qt::ApplicationState state); void throttleRender(); }; From 881ecb07cd3268d2622d9a8249e09018132e8cdd Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Thu, 13 Mar 2014 23:00:01 +0200 Subject: [PATCH 14/16] Changed the font of the entire chat window to Helvetica/Arial. --- interface/interface_en.ts | 10 +++++----- interface/ui/chatWindow.ui | 13 +++++++++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 80433032dc..b6e35f3f5f 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -28,19 +28,19 @@ ChatWindow - + Chat - - + + Connecting to XMPP... - - + + online now: diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index ecb4d79c41..22f2dcd5dd 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -13,6 +13,9 @@ Chat + + font-family: Helvetica, Arial, sans-serif; + 0 @@ -100,7 +103,7 @@ - margin-top: 12px; font-family: Helvetica, Arial, sans-serif; + margin-top: 12px; Qt::ScrollBarAlwaysOff @@ -114,7 +117,7 @@ 0 0 358 - 452 + 464 @@ -154,6 +157,12 @@ 0 + + + 0 + 60 + + border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px; From 55d0835ba1645256d9ba83bfe7403ee82518fed0 Mon Sep 17 00:00:00 2001 From: Geenz Date: Thu, 13 Mar 2014 19:08:18 -0400 Subject: [PATCH 15/16] Indentation! --- interface/src/GLCanvas.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 249f7a373d..b68c4fdacd 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -14,8 +14,8 @@ #include GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer, QGL::NoStencilBuffer)), - _throttleRendering(false), - _idleRenderInterval(100) + _throttleRendering(false), + _idleRenderInterval(100) { } From 85a15a2284513d2a0a3481dc5aaf7ddcd8af1251 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Fri, 14 Mar 2014 00:43:02 +0200 Subject: [PATCH 16/16] Moved the chat from a window to a built-in panel. --- interface/interface_en.ts | 30 +++++++++++++++--------------- interface/src/Application.cpp | 10 +++++++++- interface/src/Menu.cpp | 16 +++++++--------- interface/src/ui/ChatWindow.cpp | 17 +++++++++++++---- interface/src/ui/ChatWindow.h | 7 ++++--- interface/ui/chatWindow.ui | 8 +++++++- 6 files changed, 55 insertions(+), 33 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index b6e35f3f5f..23ea3cc3ba 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -4,22 +4,22 @@ Application - + Export Voxels - + Sparse Voxel Octree Files (*.svo) - + Open Script - + JavaScript Files (*.js) @@ -27,25 +27,25 @@ ChatWindow - + Chat - + Connecting to XMPP... - + online now: - + day %n day @@ -53,7 +53,7 @@ - + hour %n hour @@ -61,7 +61,7 @@ - + minute %n minute @@ -76,7 +76,7 @@ - + %1 online now: @@ -113,18 +113,18 @@ Menu - + Open .ini config file - - + + Text files (*.ini) - + Save .ini config file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index aed212c692..b08f8f77f1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -291,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(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 71e24e2382..c92d550fd6 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1041,22 +1041,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(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 } diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index d4f257c0f7..103f045cfa 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -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) { diff --git a/interface/src/ui/ChatWindow.h b/interface/src/ui/ChatWindow.h index 57da4da45d..fbf9fc0859 100644 --- a/interface/src/ui/ChatWindow.h +++ b/interface/src/ui/ChatWindow.h @@ -9,9 +9,9 @@ #ifndef __interface__ChatWindow__ #define __interface__ChatWindow__ -#include #include #include +#include #include @@ -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); diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index 22f2dcd5dd..1106fca3cd 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -1,7 +1,7 @@ ChatWindow - + 0 @@ -10,6 +10,12 @@ 608 + + + 400 + 0 + + Chat