summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2017-11-30 14:59:14 +0200
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2017-12-14 10:21:56 +0000
commit165f46660a422e65372856da6200fbc36e76151d (patch)
tree5e70c4ba1b221b009e124a674898b607c6ea9df5
parentec09ffb64837c45b39faff5133a1e770e5d739c4 (diff)
Remove widgets from viewer
Also includes other improvements to viewer application. Task-number: QT3DS-75 Task-number: QT3DS-687 Task-number: QT3DS-689 Change-Id: I6a5054b4b821d652f536f2c7eaa1bb4c508250c3 Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io> Reviewed-by: Janne Koskinen <janne.p.koskinen@qt.io> Reviewed-by: Antti Määttä <antti.maatta@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
-rw-r--r--doc/src/04-viewer/2-commandline.qdoc14
-rw-r--r--src/Viewer/Qt3DViewer/Qt3DViewer.pro11
-rw-r--r--src/Viewer/Qt3DViewer/Viewer.qrc18
-rw-r--r--src/Viewer/Qt3DViewer/main.cpp157
-rw-r--r--src/Viewer/Qt3DViewer/mainwindow.cpp670
-rw-r--r--src/Viewer/Qt3DViewer/mainwindow.h115
-rw-r--r--src/Viewer/Qt3DViewer/mainwindow.ui221
-rw-r--r--src/Viewer/Qt3DViewer/qml/StyledButton.qml52
-rw-r--r--src/Viewer/Qt3DViewer/qml/StyledMenu.qml95
-rw-r--r--src/Viewer/Qt3DViewer/qml/StyledMenuButton.qml71
-rw-r--r--src/Viewer/Qt3DViewer/qml/StyledMenuItem.qml159
-rw-r--r--src/Viewer/Qt3DViewer/qml/StyledMenuSeparator.qml (renamed from src/Viewer/Qt3DViewer/viewer.qml)20
-rw-r--r--src/Viewer/Qt3DViewer/qml/main.qml542
-rw-r--r--src/Viewer/Qt3DViewer/remotedeploymentreceiver.cpp40
-rw-r--r--src/Viewer/Qt3DViewer/remotedeploymentreceiver.h8
-rw-r--r--src/Viewer/Qt3DViewer/resources/images/ViewerDoc.icobin370070 -> 0 bytes
-rw-r--r--src/Viewer/Qt3DViewer/resources/images/arrow.pngbin0 -> 523 bytes
-rw-r--r--src/Viewer/Qt3DViewer/resources/images/arrow@2x.pngbin0 -> 600 bytes
-rw-r--r--src/Viewer/Qt3DViewer/resources/images/check.pngbin0 -> 502 bytes
-rw-r--r--src/Viewer/Qt3DViewer/resources/images/check@2x.pngbin0 -> 638 bytes
-rw-r--r--src/Viewer/Qt3DViewer/resources/images/icon_256x256.pngbin10229 -> 0 bytes
-rw-r--r--src/Viewer/Qt3DViewer/resources/images/icon_256x256@2x.pngbin22963 -> 0 bytes
-rw-r--r--src/Viewer/Qt3DViewer/resources/wordlist/wordlist.txt81
-rw-r--r--src/Viewer/Qt3DViewer/style_android.qss130
-rw-r--r--src/Viewer/Qt3DViewer/viewer.cpp359
-rw-r--r--src/Viewer/Qt3DViewer/viewer.h120
26 files changed, 1584 insertions, 1299 deletions
diff --git a/doc/src/04-viewer/2-commandline.qdoc b/doc/src/04-viewer/2-commandline.qdoc
index d3ab65bb..d9b4985c 100644
--- a/doc/src/04-viewer/2-commandline.qdoc
+++ b/doc/src/04-viewer/2-commandline.qdoc
@@ -80,6 +80,20 @@ The following command line options are supported:
\li --seq-outfile <file>
\li Output file name base for the image sequence.
The default value is derived from the presentation file name.
+ \row
+ \li --connect <port>
+ \li If this parameter is specified, the viewer is started in connection mode.
+ The default value is 36000.
+ \row
+ \li --fullscreen
+ \li Starts the viewer in fullscreen mode.
+ \row
+ \li --maximized
+ \li Starts the viewer in maximized mode.
+ \row
+ \li --windowgeometry <geometry>
+ \li Specifies the initial window geometry using the X11-syntax.
+ For example: \c{1000x800+50+50}
\endtable
Example - Creating a one minute 4k image sequence of a presentation:
diff --git a/src/Viewer/Qt3DViewer/Qt3DViewer.pro b/src/Viewer/Qt3DViewer/Qt3DViewer.pro
index a7f95931..1fe9a59b 100644
--- a/src/Viewer/Qt3DViewer/Qt3DViewer.pro
+++ b/src/Viewer/Qt3DViewer/Qt3DViewer.pro
@@ -2,31 +2,28 @@ include($$PWD/../../Runtime/commoninclude.pri)
TEMPLATE = app
TARGET = Qt3DViewer
-QT += widgets opengl qml quickwidgets quickcontrols2 studio3d-private
+QT += qml quickcontrols2 studio3d-private
INCLUDEPATH += $$PWD/../qmlviewer
-FORMS += mainwindow.ui
RESOURCES += Viewer.qrc
-RC_FILE += Viewer.rc
+RC_ICONS = resources/images/3D-studio-viewer.ico
ICON = resources/images/viewer.icns
SOURCES += \
- $$PWD/../qmlviewer/Qt3DSViewPlugin.cpp \
$$PWD/../qmlviewer/Qt3DSView.cpp \
$$PWD/../qmlviewer/Qt3DSRenderer.cpp \
$$PWD/../qmlviewer/q3dspresentationitem.cpp \
main.cpp \
- mainwindow.cpp \
+ viewer.cpp \
remotedeploymentreceiver.cpp
HEADERS += \
- $$PWD/../qmlviewer/Qt3DSViewPlugin.h \
$$PWD/../qmlviewer/Qt3DSView.h \
$$PWD/../qmlviewer/Qt3DSRenderer.h \
$$PWD/../qmlviewer/q3dspresentationitem.h \
- mainwindow.h \
+ viewer.h \
remotedeploymentreceiver.h
LIBS += \
diff --git a/src/Viewer/Qt3DViewer/Viewer.qrc b/src/Viewer/Qt3DViewer/Viewer.qrc
index 72650fb2..c808dca5 100644
--- a/src/Viewer/Qt3DViewer/Viewer.qrc
+++ b/src/Viewer/Qt3DViewer/Viewer.qrc
@@ -1,12 +1,14 @@
<RCC>
<qresource prefix="/">
- <file>resources/images/icon_256x256.png</file>
- <file>resources/images/icon_256x256@2x.png</file>
- <file>viewer.qml</file>
- <file alias="style.qss">../../Authoring/Studio/style.qss</file>
- <file alias="images/arrow_down.png">../../Authoring/Studio/images/arrow_down.png</file>
- <file alias="images/arrow_up.png">../../Authoring/Studio/images/arrow_up.png</file>
- <file alias="images/separator.png">../../Authoring/Studio/images/separator.png</file>
- <file>style_android.qss</file>
+ <file alias="images/arrow.png">resources/images/arrow.png</file>
+ <file alias="images/arrow@2x.png">resources/images/arrow@2x.png</file>
+ <file alias="images/check.png">resources/images/check.png</file>
+ <file alias="images/check@2x.png">resources/images/check@2x.png</file>
+ <file>qml/main.qml</file>
+ <file>qml/StyledMenu.qml</file>
+ <file>qml/StyledMenuButton.qml</file>
+ <file>qml/StyledMenuItem.qml</file>
+ <file>qml/StyledMenuSeparator.qml</file>
+ <file>qml/StyledButton.qml</file>
</qresource>
</RCC>
diff --git a/src/Viewer/Qt3DViewer/main.cpp b/src/Viewer/Qt3DViewer/main.cpp
index d8665545..8469a350 100644
--- a/src/Viewer/Qt3DViewer/main.cpp
+++ b/src/Viewer/Qt3DViewer/main.cpp
@@ -28,19 +28,22 @@
**
****************************************************************************/
-#include "mainwindow.h"
+#include "viewer.h"
-#include <QtWidgets/qapplication.h>
+#include <QtGui/qguiapplication.h>
+#include <QtGui/qtouchdevice.h>
+#include <QtGui/qscreen.h>
#include <QtCore/qcommandlineparser.h>
#include <QtCore/qfile.h>
+#include <QtCore/qtimer.h>
#include <QtStudio3D/q3dssurfaceviewer.h>
#include <QtStudio3D/private/q3dsimagesequencegenerator_p.h>
+#include <QtQml/qqmlapplicationengine.h>
+#include <QtQml/qqmlengine.h>
+#include <QtQml/qqmlcontext.h>
int main(int argc, char *argv[])
{
- // To enable QOpenGLWidget to work on macOS, we must set the default
- // QSurfaceFormat before QApplication is created. Otherwise context-sharing
- // fails and QOpenGLWidget breaks.
#if defined(Q_OS_MACOS)
QSurfaceFormat openGLFormat;
openGLFormat.setRenderableType(QSurfaceFormat::OpenGL);
@@ -56,13 +59,14 @@ int main(int argc, char *argv[])
QCoreApplication::setOrganizationDomain("qt.io");
QCoreApplication::setApplicationName("Qt 3D Viewer");
- QApplication a(argc, argv);
+ QGuiApplication a(argc, argv);
QCommandLineParser parser;
parser.addHelpOption();
- parser.addPositionalArgument("file",
- QCoreApplication::translate("main", "The presentation file to open."),
- QCoreApplication::translate("main", "[file]"));
+ parser.addPositionalArgument(
+ "file",
+ QCoreApplication::translate("main", "The presentation file to open."),
+ QCoreApplication::translate("main", "[file]"));
parser.addOption({"sequence",
QCoreApplication::translate("main",
@@ -87,8 +91,8 @@ int main(int argc, char *argv[])
QCoreApplication::translate("main", "fps"), QString::number(60)});
parser.addOption({"seq-interval",
QCoreApplication::translate("main",
- "Time interval between frames in the sequence\n"
- "in milliseconds. The seq-fps argument is ignored\n"
+ "Time interval between frames in\n"
+ "the sequence in milliseconds. The seq-fps argument is ignored"
"if this argument is used."),
QCoreApplication::translate("main", "ms"), QString::number(0)});
parser.addOption({"seq-width",
@@ -111,6 +115,24 @@ int main(int argc, char *argv[])
"Output filename base for the image sequence.\n"
"The default value is derived from the presentation filename."),
QCoreApplication::translate("main", "file"), QStringLiteral("")});
+ parser.addOption({"connect",
+ QCoreApplication::translate("main",
+ "If this parameter is specified, the viewer\n"
+ "is started in connection mode.\n"
+ "The default value is 36000."),
+ QCoreApplication::translate("main", "port"), QString::number(36000)});
+ parser.addOption({"fullscreen",
+ QCoreApplication::translate("main",
+ "Starts the viewer in fullscreen mode.\n")});
+ parser.addOption({"maximized",
+ QCoreApplication::translate("main",
+ "Starts the viewer in maximized mode.")});
+ parser.addOption({"windowgeometry",
+ QCoreApplication::translate("main",
+ "Specifies the initial\n"
+ "window geometry using the X11-syntax.\n"
+ "For example: 1000x800+50+50"),
+ QCoreApplication::translate("main", "geometry"), QStringLiteral("")});
parser.process(a);
const QStringList files = parser.positionalArguments();
@@ -127,7 +149,83 @@ int main(int argc, char *argv[])
Q3DSImageSequenceGenerator *generator = nullptr;
- MainWindow w(generateSequence);
+ Viewer viewer(generateSequence);
+
+ // Figure out control size multiplier for devices using touch screens to ensure all controls
+ // have minimum usable size.
+ qreal sizeMultiplier = 1.0;
+ const auto touchDevices = QTouchDevice::devices();
+ if (touchDevices.size() > 0) {
+ // Find out the actual screen logical pixel size. Typically touch devices we care about
+ // only have a single screen, so we just check primary screen.
+ const auto screens = QGuiApplication::screens();
+ if (screens.size() > 0) {
+ QScreen *screen = screens.at(0);
+ qreal dpi = screen->physicalDotsPerInch() / screen->devicePixelRatio();
+ sizeMultiplier = dpi / 40.0; // divider chosen empirically
+ }
+ }
+
+ QQmlApplicationEngine engine;
+ // Set import paths so that standalone installation works
+ QString extraImportPath1(QStringLiteral("%1/qml"));
+#ifdef Q_OS_MACOS
+ QString extraImportPath2(QStringLiteral("%1/../../../../qml"));
+#else
+ QString extraImportPath2(QStringLiteral("%1/../qml"));
+#endif
+ engine.addImportPath(extraImportPath1.arg(QGuiApplication::applicationDirPath()));
+ engine.addImportPath(extraImportPath2.arg(QGuiApplication::applicationDirPath()));
+
+ QQmlContext *ctx = engine.rootContext();
+ ctx->setContextProperty(QStringLiteral("_menuBackgroundColor"), QColor("#404244"));
+ ctx->setContextProperty(QStringLiteral("_menuSelectionColor"), QColor("#46a2da"));
+ ctx->setContextProperty(QStringLiteral("_menuBorderColor"), QColor("#727476"));
+ ctx->setContextProperty(QStringLiteral("_dialogBorderColor"), QColor("#404244"));
+ ctx->setContextProperty(QStringLiteral("_dialogBackgroundColor"), QColor("#2e2f30"));
+ ctx->setContextProperty(QStringLiteral("_dialogFieldColor"), QColor("#404244"));
+ ctx->setContextProperty(QStringLiteral("_dialogFieldBorderColor"), QColor("#262829"));
+ ctx->setContextProperty(QStringLiteral("_textColor"), QColor("#ffffff"));
+ ctx->setContextProperty(QStringLiteral("_disabledColor"), QColor("#727476"));
+ ctx->setContextProperty(QStringLiteral("_fontSize"), int(12 * sizeMultiplier));
+ ctx->setContextProperty(QStringLiteral("_controlBaseHeight"), int(24 * sizeMultiplier));
+ ctx->setContextProperty(QStringLiteral("_controlBaseWidth"), int(80 * sizeMultiplier));
+ ctx->setContextProperty(QStringLiteral("_controlPadding"), int(12 * sizeMultiplier));
+ ctx->setContextProperty(QStringLiteral("_viewerHelper"), &viewer);
+ qmlRegisterUncreatableType<Viewer>(
+ "Qt3DStudioViewer", 1, 0, "ViewerHelper",
+ QCoreApplication::translate("main",
+ "Creation of ViewerHelper not allowed from QML"));
+ engine.load(QUrl(QLatin1String("qrc:/qml/main.qml")));
+ Q_ASSERT(engine.rootObjects().size() > 0);
+ QWindow *appWindow = qobject_cast<QWindow *>(engine.rootObjects().at(0));
+ Q_ASSERT(appWindow);
+ viewer.setQmlRootObject(appWindow);
+
+ if (parser.isSet(QStringLiteral("windowgeometry"))) {
+ int width = 1280;
+ int height = 768;
+ int x = 50;
+ int y = 50;
+ QString geometryStr = parser.value(QStringLiteral("windowgeometry"));
+ const QStringList splitPlus = geometryStr.split(QLatin1Char('+'));
+ if (splitPlus.size() > 0) {
+ const QStringList splitX = splitPlus[0].split(QLatin1Char('x'));
+ if (splitX.size() >= 2) {
+ width = splitX[0].toInt();
+ height = splitX[1].toInt();
+ }
+ if (splitPlus.size() >= 3) {
+ x = splitPlus[1].toInt();
+ y = splitPlus[2].toInt();
+ }
+ }
+ appWindow->setGeometry(x, y, width, height);
+ }
+ if (parser.isSet(QStringLiteral("fullscreen")))
+ appWindow->setVisibility(QWindow::FullScreen);
+ else if (parser.isSet(QStringLiteral("maximized")))
+ appWindow->setVisibility(QWindow::Maximized);
if (generateSequence) {
if (files.count() != 1) {
@@ -136,10 +234,10 @@ int main(int argc, char *argv[])
}
generator = new Q3DSImageSequenceGenerator;
QObject::connect(generator, &Q3DSImageSequenceGenerator::progress,
- &w, &MainWindow::generatorProgress);
+ &viewer, &Viewer::generatorProgress);
QObject::connect(generator, &Q3DSImageSequenceGenerator::finished,
- &w, &MainWindow::generatorFinished);
- w.setGeneratorDetails(files.first());
+ &viewer, &Viewer::generatorFinished);
+ viewer.setGeneratorDetails(files.first());
generator->generateImageSequence(
files.first(),
parser.value("seq-start").toDouble(),
@@ -151,21 +249,22 @@ int main(int argc, char *argv[])
parser.value("seq-outpath"),
parser.value("seq-outfile"));
} else if (!files.isEmpty()) {
- w.loadFile(files.first());
+ // Load the presentation after window has been exposed to give QtQuick time to construct
+ // the application window properly
+ QTimer *exposeTimer = new QTimer(appWindow);
+ QObject::connect(exposeTimer, &QTimer::timeout, [&](){
+ if (appWindow->isExposed()) {
+ exposeTimer->stop();
+ exposeTimer->deleteLater();
+ viewer.loadFile(files.first());
+ }
+ });
+ exposeTimer->start(0);
+ } else if (parser.isSet(QStringLiteral("connect"))) {
+ viewer.setContentView(Viewer::ConnectView);
+ viewer.setConnectPort(parser.value(QStringLiteral("connect")).toInt());
+ viewer.connectRemote();
}
- w.show();
-#ifndef Q_OS_ANDROID
- QFile styleFile(":/style.qss");
-#else
- // We need a different stylesheet for Android, or the controls are too small, and some of
- // them aren't displayed correctly (see QTBUG-41773)
- QFile styleFile(":/style_android.qss");
-#endif
- styleFile.open(QFile::ReadOnly);
-
- QString style(styleFile.readAll());
- a.setStyleSheet(style);
-
return a.exec();
}
diff --git a/src/Viewer/Qt3DViewer/mainwindow.cpp b/src/Viewer/Qt3DViewer/mainwindow.cpp
deleted file mode 100644
index 3c2972b7..00000000
--- a/src/Viewer/Qt3DViewer/mainwindow.cpp
+++ /dev/null
@@ -1,670 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 - 2016 NVIDIA Corporation.
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt 3D Studio.
-**
-** $QT_BEGIN_LICENSE:GPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 or (at your option) any later version
-** approved by the KDE Free Qt Foundation. The licenses are as published by
-** the Free Software Foundation and appearing in the file LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QKeyEvent>
-#include <QDebug>
-#include <QSettings>
-#include <QFileDialog>
-#include <QFileInfo>
-#include <QMimeData>
-#include <QMessageBox>
-#include <QShortcut>
-#include <QWindow>
-#include <QVariant>
-#include <QGLFormat>
-#include <QQmlEngine>
-#include <QQmlComponent>
-#include <QtStudio3D/private/q3dsviewersettings_p.h>
-#include <QtGui/qguiapplication.h>
-#include <QtCore/qtimer.h>
-
-#include "Qt3DSView.h"
-#include "q3dspresentationitem.h"
-
-#include "mainwindow.h"
-#include "ui_mainwindow.h"
-
-MainWindow::MainWindow(bool generatorMode, QWidget *parent)
- : QMainWindow(parent)
- , ui(new Ui::MainWindow)
- , m_studio3D(0)
- , m_connectionInfo(0)
- , m_remoteDeploymentReceiver(0)
- , m_generatorMode(generatorMode)
-{
- ui->setupUi(this);
-
- if (!m_generatorMode) {
- resize(1280, 720);
- ui->actionOpen->setShortcut(QKeySequence::Open);
- QList<QKeySequence> shortcuts;
- shortcuts.push_back(QKeySequence(QKeySequence::Quit));
- shortcuts.push_back(QKeySequence("CTRL+Q"));
- ui->actionQuit->setShortcuts(shortcuts);
- ui->actionReload->setShortcut(QKeySequence::Refresh);
-
- QStringList strArg = QApplication::arguments();
- if (strArg.size() >= 2) {
- QFileInfo theFilePath(strArg[1]);
- if (theFilePath.exists()) {
- m_openFileDir = theFilePath.path();
- QSettings().setValue("DirectoryOfLastOpen", m_openFileDir);
- }
- }
-
-#ifdef Q_OS_ANDROID
- m_openFileDir = QStringLiteral("/sdcard/qt3dviewer"); // Add default folder for Android
-#else
- // Allow drops. Not usable for Android.
- setAcceptDrops(true);
-#endif
-
- addAction(ui->actionFull_Screen);
- addAction(ui->actionShowOnScreenStats);
- addAction(ui->actionBorder);
- addAction(ui->actionToggle_Scale_Mode);
- addAction(ui->actionToggle_Shade_Mode);
- } else {
- ui->menuBar->clear();
- ui->menuBar->addAction(ui->actionQuit);
- resize(700, 100);
- }
-
- // Set import paths so that standalone installation works
- QString extraImportPath1(QStringLiteral("%1/qml"));
-#ifdef Q_OS_MACOS
- QString extraImportPath2(QStringLiteral("%1/../../../../qml"));
-#else
- QString extraImportPath2(QStringLiteral("%1/../qml"));
-#endif
- ui->quickWidget->engine()->addImportPath(
- extraImportPath1.arg(QGuiApplication::applicationDirPath()));
- ui->quickWidget->engine()->addImportPath(
- extraImportPath2.arg(QGuiApplication::applicationDirPath()));
-
- ui->quickWidget->setSource(QUrl("qrc:/viewer.qml"));
-
- if (m_generatorMode)
- setupGeneratorUI();
-
- updateUI();
-}
-
-MainWindow::~MainWindow()
-{
-}
-
-void MainWindow::on_actionToggle_Scale_Mode_triggered()
-{
- switch (viewer()->viewerSettings()->scaleMode())
- {
- case Q3DSViewerSettings::ScaleModeCenter:
- viewer()->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
- break;
- case Q3DSViewerSettings::ScaleModeFill:
- viewer()->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeFit);
- break;
- case Q3DSViewerSettings::ScaleModeFit:
- viewer()->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeCenter);
- break;
- }
- updateUI();
-}
-
-void MainWindow::on_actionToggle_Shade_Mode_triggered()
-{
- switch (viewer()->viewerSettings()->shadeMode())
- {
- case Q3DSViewerSettings::ShadeModeShaded:
- viewer()->viewerSettings()->setShadeMode(Q3DSViewerSettings::ShadeModeShadedWireframe);
- break;
- case Q3DSViewerSettings::ShadeModeShadedWireframe:
- viewer()->viewerSettings()->setShadeMode(Q3DSViewerSettings::ShadeModeShaded);
- break;
- }
- updateUI();
-}
-
-void MainWindow::on_actionBorder_triggered()
-{
- Q3DSView *view = viewer();
- if (!view)
- return;
-
- QColor matte = view->viewerSettings()->matteColor();
- if (matte == QColor(Qt::black) || !matte.isValid())
- view->viewerSettings()->setMatteColor(QColor(50, 50, 50));
- else
- view->viewerSettings()->setMatteColor(Qt::black);
-
- updateUI();
-}
-
-void MainWindow::on_actionFull_Screen_triggered()
-{
- if (ui->actionFull_Screen->isChecked()) {
- showFullScreen();
- ui->menuBar->hide();
- } else {
- showNormal();
- ui->menuBar->show();
- }
-}
-
-void MainWindow::on_actionShowOnScreenStats_triggered()
-{
- Q3DSView *view = viewer();
- if (!view)
- return;
-
- view->viewerSettings()->setShowRenderStats(!view->viewerSettings()->isShowRenderStats());
- updateUI();
-}
-
-void MainWindow::on_actionQuit_triggered()
-{
- delete m_studio3D;
- m_studio3D = 0;
- close();
-}
-
-void MainWindow::on_actionOpen_triggered()
-{
- QSettings settings;
- if (m_openFileDir.size() == 0) {
- m_openFileDir
- = settings.value("DirectoryOfLastOpen", QString("")).toString();
- }
-
- QString filename = QFileDialog::getOpenFileName(
- this, tr("Open File or Project"), m_openFileDir,
- tr("All supported formats (*.uip *.uia *.uiab);;Studio UI Presentation "
- "(*.uip);;Application file (*.uia);;Binary Application (*.uiab)"),
- NULL, QFileDialog::DontUseNativeDialog);
-
- if (filename.size() == 0)
- return;
-
- QFileInfo theInfo(filename);
- m_openFileDir = theInfo.path();
- settings.setValue("DirectoryOfLastOpen", m_openFileDir);
-
- loadFile(filename);
-}
-
-void MainWindow::on_actionConnect_triggered()
-{
- if (m_remoteDeploymentReceiver) {
- delete m_remoteDeploymentReceiver;
- m_remoteDeploymentReceiver = 0;
- delete m_connectionInfo;
- m_connectionInfo = 0;
- if (m_studio3D)
- m_studio3D->setVisible(true);
-
- updateUI();
- return;
- }
-
- m_remoteDeploymentReceiver = new RemoteDeploymentReceiver(this);
- if (m_remoteDeploymentReceiver->canceled()) {
- delete m_remoteDeploymentReceiver;
- m_remoteDeploymentReceiver = 0;
- ui->actionConnect->setChecked(false);
- return;
- }
-
- if (!m_remoteDeploymentReceiver->startServer()) {
- QString msg = "Unable to connect to remote project.\n";
- QMessageBox::warning(this, "Connection Error", msg, QMessageBox::Close);
- delete m_remoteDeploymentReceiver;
- m_remoteDeploymentReceiver = 0;
- updateUI();
- return;
- }
-
- int port = m_remoteDeploymentReceiver->serverPort();
- QString message;
- QTextStream stream(&message);
- stream << "Connection Info\n"
- << "Address: " << m_remoteDeploymentReceiver->hostAddress().toString() << "\n"
- << "Port: " + QString::number(port);
-
- QQmlEngine *engine = ui->quickWidget->engine();
- QQuickItem *root = ui->quickWidget->rootObject();
-
- QByteArray qml = "import QtQuick 2.7\n"
- "import QtQuick.Controls 2.2\n"
- "Label {\n"
- " color: \"White\"\n"
- " horizontalAlignment: Text.AlignHCenter\n"
- " verticalAlignment: Text.AlignVCenter\n"
- " anchors.fill: parent\n"
- " font.pixelSize: 42\n"
- "}";
-
- QQmlComponent component(engine);
- component.setData(qml, QUrl());
-
- if (component.isError()) {
- qCritical() << "error" << component.errors();
- return;
- }
-
- m_connectionInfo = qobject_cast<QQuickItem *>(component.create());
- m_connectionInfo->setProperty("text", message);
-
- QQmlEngine::setObjectOwnership(m_connectionInfo, QQmlEngine::CppOwnership);
- m_connectionInfo->setParentItem(root);
- m_connectionInfo->setParent(engine);
-
- connect(m_remoteDeploymentReceiver, &RemoteDeploymentReceiver::remoteConnected,
- this, &MainWindow::remoteConnected);
-
- connect(m_remoteDeploymentReceiver, &RemoteDeploymentReceiver::remoteDisconnected,
- this, &MainWindow::remoteDisconnected);
-
- connect(m_remoteDeploymentReceiver, &RemoteDeploymentReceiver::projectChanging,
- this, &MainWindow::remoteProjectChanging);
-
- connect(m_remoteDeploymentReceiver, &RemoteDeploymentReceiver::projectChanged,
- this, &MainWindow::loadRemoteDeploymentReceiver);
-
- updateUI();
-}
-
-void MainWindow::on_actionReload_triggered()
-{
- if (Q3DSView *view = viewer()) {
- view->reset();
- updateUI();
- }
-}
-
-Q3DSView *MainWindow::viewer() const
-{
- return m_studio3D;
-}
-
-void MainWindow::loadFile(const QString &filename)
-{
- QFileInfo fileInfo(filename);
- if (!fileInfo.exists())
- return;
-
- QUrl sourceUrl = QUrl::fromLocalFile(fileInfo.absoluteFilePath());
-
- if (m_studio3D) {
- viewer()->presentation()->setSource(sourceUrl);
- viewer()->reset();
- return;
- }
- delete m_errorInfo;
- m_errorInfo = nullptr;
-
- QQmlEngine *engine = ui->quickWidget->engine();
- QQuickItem *root = ui->quickWidget->rootObject();
-
- QByteArray qml = "import QtStudio3D 1.0\n"
- "Studio3D {\n"
- " id: studio3D\n"
- " anchors.fill: parent\n"
- " focus: true\n"
- "}";
-
- QQmlComponent component(engine);
- component.setData(qml, QUrl());
-
- if (component.isError()) {
- qDebug() << "error" << component.errors();
- return;
- }
-
- m_studio3D = static_cast<Q3DSView *>(component.create());
- connect(m_studio3D, &Q3DSView::errorChanged, this, &MainWindow::onErrorChanged,
- Qt::QueuedConnection);
- viewer()->presentation()->setSource(sourceUrl);
-
- QQmlEngine::setObjectOwnership(m_studio3D, QQmlEngine::CppOwnership);
- m_studio3D->setParentItem(root);
- m_studio3D->setParent(engine);
-
-#ifdef Q_OS_ANDROID
- // We have custom mouse event handling in android
- viewer()->setIgnoreEvents(true, false, false);
-#endif
-
- updateUI();
-}
-
-void MainWindow::on_actionCenter_triggered()
-{
- if (Q3DSView *view = viewer()) {
- view->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeCenter);
- updateUI();
- }
-}
-
-void MainWindow::on_actionScale_To_Fit_triggered()
-{
- if (Q3DSView *view = viewer()) {
- view->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeFit);
- updateUI();
- }
-}
-
-void MainWindow::on_actionScale_To_Fill_triggered()
-{
- if (Q3DSView *view = viewer()) {
- view->viewerSettings()->setScaleMode(Q3DSViewerSettings::ScaleModeFill);
- updateUI();
- }
-}
-
-QString MainWindow::convertMimeDataToFilename(const QMimeData *mimeData)
-{
- if (mimeData->hasUrls()) {
- for (const QUrl &url : mimeData->urls()) {
- QString str = url.toLocalFile();
- if (str.isEmpty() == false) {
- if ((QFileInfo(str).suffix() == "uip")
- || (QFileInfo(str).suffix() == "uia")
- || (QFileInfo(str).suffix() == "uiab"))
- {
- return str;
- }
- }
- }
- }
- return QString();
-}
-
-void MainWindow::setupGeneratorUI()
-{
- QQmlEngine *engine = ui->quickWidget->engine();
- QQuickItem *root = ui->quickWidget->rootObject();
-
- QByteArray qml = "import QtQuick 2.7\n"
- "import QtQuick.Controls 2.2\n"
- "Item {\n"
- " property alias mainText: mainLabel.text\n"
- " property alias detailsText: detailsLabel.text\n"
- " anchors.fill: parent\n"
- " Label {\n"
- " id: mainLabel\n"
- " color: \"White\"\n"
- " horizontalAlignment: Text.AlignHCenter\n"
- " verticalAlignment: Text.AlignVCenter\n"
- " anchors.top: parent.top\n"
- " anchors.left: parent.left\n"
- " anchors.right: parent.right\n"
- " height: parent.height / 2\n"
- " font.pixelSize: width / 40\n"
- " text: \"Image sequence generation initializing...\"\n"
- " }\n"
- " Label {\n"
- " id: detailsLabel\n"
- " color: \"White\"\n"
- " horizontalAlignment: Text.AlignHCenter\n"
- " verticalAlignment: Text.AlignTop\n"
- " anchors.top: mainLabel.bottom\n"
- " anchors.left: parent.left\n"
- " anchors.right: parent.right\n"
- " height: parent.height / 2\n"
- " font.pixelSize: width / 50\n"
- " }\n"
- "}";
-
- QQmlComponent component(engine);
- component.setData(qml, QUrl());
-
- if (component.isError()) {
- qCritical() << "Error setting up generator UI:" << component.errors();
- return;
- }
-
- m_generatorInfo = qobject_cast<QQuickItem *>(component.create());
-
- QQmlEngine::setObjectOwnership(m_generatorInfo, QQmlEngine::CppOwnership);
- m_generatorInfo->setParentItem(root);
- m_generatorInfo->setParent(engine);
-}
-
-void MainWindow::dragEnterEvent(QDragEnterEvent *event)
-{
- if (convertMimeDataToFilename(event->mimeData()).isEmpty() == false)
- event->acceptProposedAction();
-}
-
-void MainWindow::dropEvent(QDropEvent *event)
-{
- QString fileName = convertMimeDataToFilename(event->mimeData());
- if (fileName.isEmpty() == false)
- loadFile(fileName);
-}
-
-void MainWindow::showEvent(QShowEvent *event)
-{
- QMainWindow::showEvent(event);
- if (!m_generatorMode) {
- QSettings settings(QCoreApplication::organizationName(),
- QCoreApplication::applicationName());
- restoreGeometry(settings.value("mainWindowGeometry").toByteArray());
- restoreState(settings.value("mainWindowState").toByteArray());
- }
- updateUI();
-}
-
-void MainWindow::closeEvent(QCloseEvent *event)
-{
- if (!m_generatorMode) {
- QSettings settings(QCoreApplication::organizationName(),
- QCoreApplication::applicationName());
- settings.setValue("mainWindowGeometry", saveGeometry());
- settings.setValue("mainWindowState", saveState());
- }
- QMainWindow::closeEvent(event);
-}
-
-#ifdef Q_OS_ANDROID
-void MainWindow::mousePressEvent(QMouseEvent *event)
-{
- m_swipeStart = event->pos();
-
- Q3DSView *view = viewer();
- if (view)
- view->presentation()->mousePressEvent(event);
-
- event->accept();
-}
-
-void MainWindow::mouseReleaseEvent(QMouseEvent *event)
-{
- Q3DSView *view = viewer();
- if (view)
- view->presentation()->mouseReleaseEvent(event);
-
- event->accept();
-}
-
-void MainWindow::mouseMoveEvent(QMouseEvent *event)
-{
- // Fake swipe down event, as SwipeGesture doesn't work (unless you use 3 fingers..)
- int swipeLength = height() / 10;
- if (ui->actionFull_Screen->isChecked() && event->pos().y() > m_swipeStart.y() + swipeLength) {
- ui->actionFull_Screen->setChecked(false);
- on_actionFull_Screen_triggered();
- }
-
- Q3DSView *view = viewer();
- if (view)
- view->presentation()->mouseMoveEvent(event);
-
- event->accept();
-}
-#endif
-
-void MainWindow::updateUI()
-{
- ui->actionConnect->setChecked(m_remoteDeploymentReceiver);
-
- bool displayConnection = m_remoteDeploymentReceiver
- && !m_remoteDeploymentReceiver->isProjectDeployed();
-
- if (m_connectionInfo)
- m_connectionInfo->setVisible(displayConnection);
-
- if (m_studio3D)
- m_studio3D->setVisible(!displayConnection);
-
- Q3DSView *view = viewer();
- if (!view)
- return;
-
- Q3DSViewerSettings::ScaleMode scaleMode = view->viewerSettings()->scaleMode();
- ui->actionCenter->setChecked(scaleMode == Q3DSViewerSettings::ScaleModeCenter);
- ui->actionScale_To_Fit->setChecked(scaleMode == Q3DSViewerSettings::ScaleModeFit);
- ui->actionScale_To_Fill->setChecked(scaleMode == Q3DSViewerSettings::ScaleModeFill);
-
- QColor matte = view->viewerSettings()->matteColor();
- ui->actionBorder->setChecked(matte.isValid() && matte != QColor(Qt::black));
- ui->actionShowOnScreenStats->setChecked(view->viewerSettings()->isShowRenderStats());
-}
-
-void MainWindow::loadRemoteDeploymentReceiver()
-{
- Q_ASSERT(m_remoteDeploymentReceiver);
- const QString remote = m_remoteDeploymentReceiver->fileName();
- loadFile(remote);
- updateUI();
-}
-
-void MainWindow::remoteProjectChanging()
-{
- updateUI();
-}
-
-void MainWindow::remoteConnected()
-{
- m_connectionInfo->setProperty("text", "Remote Connected");
- updateUI();
-}
-
-void MainWindow::remoteDisconnected()
-{
- m_connectionInfo->setProperty("text", "Remote Disconnected");
- updateUI();
-}
-
-void MainWindow::onErrorChanged(const QString &error)
-{
- if (error.isEmpty()) {
- delete m_errorInfo;
- m_errorInfo = nullptr;
- } else {
- if (!m_errorInfo) {
- QQmlEngine *engine = ui->quickWidget->engine();
- QQuickItem *root = ui->quickWidget->rootObject();
-
- QByteArray qml = "import QtQuick 2.7\n"
- "import QtQuick.Controls 2.2\n"
- "Label {\n"
- " color: \"White\"\n"
- " horizontalAlignment: Text.AlignHCenter\n"
- " verticalAlignment: Text.AlignVCenter\n"
- " anchors.fill: parent\n"
- " font.pixelSize: width / 80\n"
- "}";
-
- QQmlComponent component(engine);
- component.setData(qml, QUrl());
-
- if (component.isError()) {
- qCritical() << "Error setting up error UI:" << component.errors();
- return;
- }
-
- m_errorInfo = qobject_cast<QQuickItem *>(component.create());
- m_errorInfo->setParentItem(root);
- m_errorInfo->setParent(engine);
- QQmlEngine::setObjectOwnership(m_errorInfo, QQmlEngine::CppOwnership);
- }
- m_errorInfo->setProperty("text", m_studio3D->error());
-
- delete m_studio3D;
- m_studio3D = nullptr;
- }
-}
-
-void MainWindow::generatorProgress(int totalFrames, int frameCount)
-{
- QString progressString;
- if (frameCount >= totalFrames) {
- progressString =
- QCoreApplication::translate(
- "main", "Image sequence generation done! (%2 frames generated)")
- .arg(totalFrames);
- } else {
- progressString =
- QCoreApplication::translate("main", "Image sequence generation progress: %1 / %2")
- .arg(frameCount).arg(totalFrames);
- }
- m_generatorInfo->setProperty("mainText", progressString);
-}
-
-void MainWindow::generatorFinished(bool success, const QString &details)
-{
- if (success) {
- m_generatorInfo->setProperty("detailsText", details);
- } else {
- QString mainString =
- QCoreApplication::translate("main", "Image sequence generation failed:");
- m_generatorInfo->setProperty("mainText", mainString);
- m_generatorInfo->setProperty("detailsText", details);
- }
-}
-
-void MainWindow::updateProgress(int percent)
-{
- QString progress = QStringLiteral("Receiving (");
- progress.append(QString::number(percent));
- progress.append("%)");
- // Don't wait for 100%, as it'll already start loading and text isn't updated anymore
- if (percent >= 99)
- m_connectionInfo->setProperty("text", QStringLiteral("Loading"));
- else
- m_connectionInfo->setProperty("text", progress);
- updateUI();
-}
-
-void MainWindow::setGeneratorDetails(const QString &filename)
-{
- m_generatorInfo->setProperty("detailsText", filename);
-}
diff --git a/src/Viewer/Qt3DViewer/mainwindow.h b/src/Viewer/Qt3DViewer/mainwindow.h
deleted file mode 100644
index 6a9f0612..00000000
--- a/src/Viewer/Qt3DViewer/mainwindow.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2013 - 2016 NVIDIA Corporation.
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt 3D Studio.
-**
-** $QT_BEGIN_LICENSE:GPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 or (at your option) any later version
-** approved by the KDE Free Qt Foundation. The licenses are as published by
-** the Free Software Foundation and appearing in the file LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
-
-#include <QtWidgets/QMainWindow>
-#include <QtQuickWidgets/QQuickWidget>
-
-#include "remotedeploymentreceiver.h"
-
-QT_BEGIN_NAMESPACE
-namespace Ui {
-class MainWindow;
-}
-class QMimeData;
-class Q3DSView;
-QT_END_NAMESPACE
-
-class MainWindow : public QMainWindow
-{
- Q_OBJECT
-
-public:
- explicit MainWindow(bool generatorMode, QWidget *parent = nullptr);
- ~MainWindow();
-
- void loadFile(const QString &filename);
- void loadProject(const QByteArray &data);
- void updateProgress(int percent);
- void setGeneratorDetails(const QString &filename);
-
-protected:
- void dragEnterEvent(QDragEnterEvent *event) override;
- void dropEvent(QDropEvent *event) override;
- void showEvent(QShowEvent *event) override;
- void closeEvent(QCloseEvent *event) override;
-#ifdef Q_OS_ANDROID
- void mousePressEvent(QMouseEvent *event) override;
- void mouseReleaseEvent(QMouseEvent *event) override;
- void mouseMoveEvent(QMouseEvent *event) override;
-#endif
-
-private:
- Q3DSView *viewer() const;
- QString convertMimeDataToFilename(const QMimeData *mimeData);
- void setupGeneratorUI();
-
-public Q_SLOTS:
- void generatorProgress(int totalFrames, int frameCount);
- void generatorFinished(bool success, const QString &details);
-
-private Q_SLOTS:
- void on_actionToggle_Scale_Mode_triggered();
- void on_actionToggle_Shade_Mode_triggered();
- void on_actionBorder_triggered();
- void on_actionFull_Screen_triggered();
- void on_actionShowOnScreenStats_triggered();
- void on_actionQuit_triggered();
- void on_actionOpen_triggered();
- void on_actionConnect_triggered();
- void on_actionReload_triggered();
- void on_actionCenter_triggered();
- void on_actionScale_To_Fit_triggered();
- void on_actionScale_To_Fill_triggered();
-
- void updateUI();
-
- void loadRemoteDeploymentReceiver();
- void remoteProjectChanging();
- void remoteConnected();
- void remoteDisconnected();
- void onErrorChanged(const QString &error);
-
-private:
- Ui::MainWindow *ui;
- Q3DSView *m_studio3D = nullptr;
- QQuickItem *m_connectionInfo = nullptr;
- QString m_openFileDir;
- bool m_embeddedMode;
- QPoint m_swipeStart;
- RemoteDeploymentReceiver *m_remoteDeploymentReceiver = nullptr;
- bool m_generatorMode;
- QQuickItem *m_generatorInfo = nullptr;
- QQuickItem *m_errorInfo = nullptr;
-};
-
-#endif // MAINWINDOW_H
diff --git a/src/Viewer/Qt3DViewer/mainwindow.ui b/src/Viewer/Qt3DViewer/mainwindow.ui
deleted file mode 100644
index cddbff72..00000000
--- a/src/Viewer/Qt3DViewer/mainwindow.ui
+++ /dev/null
@@ -1,221 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>1042</width>
- <height>556</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>Qt 3D Viewer</string>
- </property>
- <property name="windowIcon">
- <iconset resource="Viewer.qrc">
- <normaloff>:/resources/images/icon_256x256.png</normaloff>:/resources/images/icon_256x256.png</iconset>
- </property>
- <property name="styleSheet">
- <string notr="true"/>
- </property>
- <widget class="QWidget" name="centralWidget">
- <layout class="QGridLayout" name="gridLayout">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item row="0" column="0">
- <widget class="QQuickWidget" name="quickWidget">
- <property name="resizeMode">
- <enum>QQuickWidget::SizeRootObjectToView</enum>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QMenuBar" name="menuBar">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>1042</width>
- <height>21</height>
- </rect>
- </property>
- <widget class="QMenu" name="menuFile">
- <property name="title">
- <string>File</string>
- </property>
- <addaction name="actionOpen"/>
- <addaction name="actionConnect"/>
- <addaction name="actionReload"/>
- <addaction name="separator"/>
- <addaction name="actionQuit"/>
- </widget>
- <widget class="QMenu" name="menuView">
- <property name="title">
- <string>View</string>
- </property>
- <widget class="QMenu" name="menuScale_Mode">
- <property name="toolTip">
- <string>Set application scale mode (-scalemode [center,fit,fill] command line parameter)</string>
- </property>
- <property name="title">
- <string>Scale Mode</string>
- </property>
- <addaction name="actionCenter"/>
- <addaction name="actionScale_To_Fit"/>
- <addaction name="actionScale_To_Fill"/>
- </widget>
- <addaction name="actionBorder"/>
- <addaction name="menuScale_Mode"/>
- <addaction name="actionFull_Screen"/>
- <addaction name="actionShowOnScreenStats"/>
- </widget>
- <addaction name="menuFile"/>
- <addaction name="menuView"/>
- </widget>
- <action name="actionQuit">
- <property name="text">
- <string>Quit</string>
- </property>
- <property name="shortcut">
- <string>Ctrl+Q</string>
- </property>
- </action>
- <action name="actionFull_Screen">
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>Full Screen</string>
- </property>
- <property name="shortcut">
- <string>F11</string>
- </property>
- </action>
- <action name="actionBorder">
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>Show Matte</string>
- </property>
- <property name="shortcut">
- <string>Ctrl+D</string>
- </property>
- </action>
- <action name="actionShowOnScreenStats">
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>Show Render Statistics</string>
- </property>
- <property name="shortcut">
- <string>F1</string>
- </property>
- <property name="visible">
- <bool>true</bool>
- </property>
- </action>
- <action name="actionOpen">
- <property name="text">
- <string>Open...</string>
- </property>
- <property name="shortcut">
- <string>Ctrl+O</string>
- </property>
- </action>
- <action name="actionConnect">
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>Connect</string>
- </property>
- </action>
- <action name="actionReload">
- <property name="text">
- <string>Reload</string>
- </property>
- </action>
- <action name="actionCenter">
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>Center</string>
- </property>
- <property name="toolTip">
- <string>Center content and use design dimensions</string>
- </property>
- </action>
- <action name="actionScale_To_Fit">
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>Scale To Fit</string>
- </property>
- <property name="toolTip">
- <string>Fit content to available space but maintain aspect ratio</string>
- </property>
- </action>
- <action name="actionScale_To_Fill">
- <property name="checkable">
- <bool>true</bool>
- </property>
- <property name="text">
- <string>Scale To Fill</string>
- </property>
- <property name="toolTip">
- <string>Use entire screen space for content, changing aspect ratio as necessary</string>
- </property>
- </action>
- <action name="actionToggle_Scale_Mode">
- <property name="text">
- <string>Toggle Scale Mode</string>
- </property>
- <property name="toolTip">
- <string>Toggle between the various scale modes</string>
- </property>
- <property name="shortcut">
- <string>Ctrl+Shift+S</string>
- </property>
- </action>
- <action name="actionToggle_Shade_Mode">
- <property name="text">
- <string>Toggle Shade Mode</string>
- </property>
- <property name="shortcut">
- <string>Ctrl+Shift+W</string>
- </property>
- </action>
- </widget>
- <layoutdefault spacing="6" margin="11"/>
- <customwidgets>
- <customwidget>
- <class>QQuickWidget</class>
- <extends>QWidget</extends>
- <header>QtQuickWidgets/QQuickWidget</header>
- </customwidget>
- </customwidgets>
- <resources>
- <include location="Viewer.qrc"/>
- </resources>
- <connections/>
-</ui>
diff --git a/src/Viewer/Qt3DViewer/qml/StyledButton.qml b/src/Viewer/Qt3DViewer/qml/StyledButton.qml
new file mode 100644
index 00000000..400179de
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/qml/StyledButton.qml
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtQuick.Controls 2.2
+
+Button {
+ id: control
+ implicitWidth: _controlBaseWidth
+ implicitHeight: _controlBaseHeight
+
+ contentItem: Text {
+ width: _controlBaseWidth
+ text: control.text
+ height: _controlBaseHeight
+ font.pixelSize: _fontSize
+ color: _textColor
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+ background: Rectangle {
+ color: control.down ? _menuSelectionColor : _dialogFieldColor
+ border.color: _dialogFieldBorderColor
+ radius: 2
+ }
+}
diff --git a/src/Viewer/Qt3DViewer/qml/StyledMenu.qml b/src/Viewer/Qt3DViewer/qml/StyledMenu.qml
new file mode 100644
index 00000000..6275dbc6
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/qml/StyledMenu.qml
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtQuick.Controls 2.2
+
+Menu {
+ id: control
+
+ property alias hovered: menuArea.containsMouse
+
+ width: contentItem.width + leftPadding + rightPadding
+ height: contentItem.height + topPadding + bottomPadding
+ padding: 1 // For background border
+ x: 0
+ y: parent.height
+ closePolicy: Popup.CloseOnPressOutsideParent | Popup.CloseOnEscape
+
+ contentItem: MouseArea {
+ id: menuArea
+ hoverEnabled: true
+ height: list.height
+ width: list.width
+ ListView {
+ id: list
+ boundsBehavior: Flickable.StopAtBounds
+ clip: true
+ model: control.contentModel
+ currentIndex: control.currentIndex
+ highlightRangeMode: ListView.ApplyRange
+ highlightMoveDuration: 0
+ Component.onCompleted: {
+ var maxItemWidth = 0;
+ var maxShortcutWidth = 0;
+ var totalHeight = 0
+ var extraWidth = 0
+ var i;
+ for (i = control.contentData.length - 1; i >= 0; --i) {
+ if (control.contentData[i].itemWidth !== undefined) {
+ maxItemWidth = Math.max(maxItemWidth, control.contentData[i].itemWidth);
+ maxShortcutWidth = Math.max(maxShortcutWidth,
+ control.contentData[i].shortcutWidth);
+ }
+ totalHeight += control.contentData[i].height
+ }
+ maxItemWidth += _controlPadding // minimum item spacer
+ for (i = control.contentData.length - 1; i >= 0; --i) {
+ if (control.contentData[i].itemSpacerWidth !== undefined) {
+ control.contentData[i].itemSpacerWidth
+ = maxItemWidth - control.contentData[i].itemWidth;
+ control.contentData[i].shortcutSpacerWidth
+ = maxShortcutWidth - control.contentData[i].shortcutWidth;
+ }
+ }
+ width = maxItemWidth + maxShortcutWidth + extraWidth
+ + control.contentData[0].leftPadding + control.contentData[0].rightPadding
+ + control.contentData[0].arrowWidth + control.contentData[0].checkMarkWidth;
+ height = totalHeight
+ }
+ }
+ }
+
+ background: Rectangle {
+ width: control.width
+ height: control.height
+ color: _menuBackgroundColor
+ border.color: _menuBorderColor
+ }
+}
diff --git a/src/Viewer/Qt3DViewer/qml/StyledMenuButton.qml b/src/Viewer/Qt3DViewer/qml/StyledMenuButton.qml
new file mode 100644
index 00000000..b5290c3d
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/qml/StyledMenuButton.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtQuick.Controls 2.2
+
+Button {
+ id: control
+
+ property Menu menu: null
+ property ApplicationWindow window: null
+
+ onPressed: {
+ if (menu.visible)
+ menu.close();
+ else
+ menu.open();
+ }
+
+ onHoveredChanged: {
+ if (hovered && window.menuOpen) {
+ window.closeMenus();
+ menu.open();
+ }
+ }
+
+ hoverEnabled: true
+ width: contentItem.contentWidth + leftPadding + rightPadding
+ leftPadding: _controlPadding
+ rightPadding: _controlPadding
+ height: _controlBaseHeight
+ contentItem: Text {
+ text: control.text
+ font.pixelSize: _fontSize
+ opacity: enabled ? 1.0 : 0.3
+ color: _textColor
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ }
+ background: Rectangle {
+ opacity: enabled ? 1 : 0.3
+ color: control.down || control.hovered
+ ? _menuSelectionColor : _menuBackgroundColor
+ }
+}
diff --git a/src/Viewer/Qt3DViewer/qml/StyledMenuItem.qml b/src/Viewer/Qt3DViewer/qml/StyledMenuItem.qml
new file mode 100644
index 00000000..79049a90
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/qml/StyledMenuItem.qml
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtQuick.Controls 2.2
+
+MenuItem {
+ id: control
+
+ property alias shortcut: shortcut.sequence
+ property string shortcutText
+ property alias itemSpacerWidth: itemSpacer.width
+ property alias shortcutSpacerWidth: shortcutSpacer.width
+ property alias itemWidth: itemLabel.width
+ property alias shortcutWidth: shortcutLabel.width
+ property bool showArrow: false
+ property int arrowWidth: arrow.width
+ property int checkMarkWidth: checkMark.width
+ property bool showCheckMark: false
+ property Menu arrowMenu: null
+
+ hoverEnabled: true
+ width: contentItem.width + leftPadding + rightPadding
+ height: contentItem.height + topPadding + bottomPadding
+ padding: 0
+ leftPadding: 0
+ rightPadding: 0
+
+ MouseArea {
+ anchors.fill: parent
+ onPressed: {
+ if (showArrow) {
+ if (!arrowMenu.visible) {
+ arrowMenuDelay.stop();
+ arrowMenu.open();
+ }
+ } else {
+ mouse.accepted = false;
+ }
+ }
+ }
+
+ onHoveredChanged: {
+ if (showArrow)
+ arrowMenuDelay.start();
+ }
+
+ Timer {
+ id: arrowMenuDelay
+ interval: 500
+ repeat: false
+ onTriggered: {
+ if (arrowMenu.visible) {
+ if (!control.hovered && !arrowMenu.hovered)
+ arrowMenu.close();
+ } else {
+ if (control.hovered)
+ arrowMenu.open();
+ }
+ }
+ }
+
+ Shortcut {
+ id: shortcut
+ context: Qt.ApplicationShortcut
+ onActivated: control.triggered()
+ }
+
+ contentItem: Row {
+ width: checkMark.width + itemLabel.width + itemSpacer.width
+ + shortcutLabel.width + shortcutSpacer.width + arrow.width
+ height: _controlBaseHeight
+ Item {
+ id: checkMark
+ width: 16
+ height: _controlBaseHeight
+ Image {
+ anchors.fill: parent
+ visible: control.showCheckMark
+ fillMode: Image.Pad
+ source: "qrc:/images/check.png"
+ }
+ }
+ Label {
+ id: itemLabel
+ text: control.text
+ font.pixelSize: _fontSize
+ horizontalAlignment: Text.AlignLeft
+ color: control.enabled ? _textColor : _disabledColor
+ verticalAlignment: Text.AlignVCenter
+ clip: true
+ width: contentWidth
+ height: _controlBaseHeight
+ }
+ Item {
+ id: itemSpacer
+ width: _controlPadding
+ height: _controlBaseHeight
+ }
+ Label {
+ id: shortcutLabel
+ text: shortcut.nativeText === "" ? control.shortcutText : shortcut.nativeText
+ font.pixelSize: _fontSize
+ horizontalAlignment: Text.AlignLeft
+ color: control.enabled ? _textColor : _disabledColor
+ verticalAlignment: Text.AlignVCenter
+ clip: true
+ width: contentWidth
+ height: _controlBaseHeight
+ }
+ Item {
+ id: shortcutSpacer
+ width: 0
+ height: _controlBaseHeight
+ }
+ Item {
+ id: arrow
+ width: 16
+ height: _controlBaseHeight
+ Image {
+ anchors.fill: parent
+ visible: control.showArrow
+ fillMode: Image.Pad
+ source: "qrc:/images/arrow.png"
+ }
+ }
+ }
+ background: Rectangle {
+ width: control.width
+ height: control.height
+ color: control.hovered ? _menuSelectionColor : _menuBackgroundColor
+ }
+}
diff --git a/src/Viewer/Qt3DViewer/viewer.qml b/src/Viewer/Qt3DViewer/qml/StyledMenuSeparator.qml
index 32025907..344d6678 100644
--- a/src/Viewer/Qt3DViewer/viewer.qml
+++ b/src/Viewer/Qt3DViewer/qml/StyledMenuSeparator.qml
@@ -27,13 +27,21 @@
**
****************************************************************************/
-
import QtQuick 2.7
import QtQuick.Controls 2.2
-import QtStudio3D 1.0
-Rectangle {
- id: window
- visible: true
- color: "black"
+MenuSeparator {
+ id: control
+ padding: 0
+ topPadding: 0
+ bottomPadding: 0
+ leftPadding: 0
+ rightPadding: 0
+ width: parent.width
+ height: 1
+ contentItem: Rectangle {
+ width: control.width - control.leftPadding - control.rightPadding
+ height: 1
+ color: _menuBorderColor
+ }
}
diff --git a/src/Viewer/Qt3DViewer/qml/main.qml b/src/Viewer/Qt3DViewer/qml/main.qml
new file mode 100644
index 00000000..c983246c
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/qml/main.qml
@@ -0,0 +1,542 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.7
+import QtQuick.Controls 2.2
+import QtQuick.Dialogs 1.2
+import Qt3DStudioViewer 1.0
+import QtStudio3D 1.0
+import QtQuick.Window 2.2
+
+ApplicationWindow {
+ id: window
+ width: 1280
+ height: 768
+ visible: true
+ title: qsTr("Qt 3D Studio Viewer")
+
+ property bool menuOpen: fileMenu.visible || viewMenu.visible
+ property Item loadedContent: contentLoader ? contentLoader.item : null
+ property string error
+ property int previousVisibility
+
+ property color matteColor: Qt.rgba(0, 0, 0, 1)
+ property bool showRenderStats: false
+ property int scaleMode: ViewerSettings.ScaleModeCenter
+
+ function closeMenus() {
+ fileMenu.close();
+ scaleMenu.close();
+ viewMenu.close();
+ }
+
+ Component.onCompleted: {
+ _viewerHelper.restoreWindowState(window);
+ previousVisibility = visibility;
+ }
+
+ onClosing: {
+ _viewerHelper.storeWindowState(window);
+ }
+
+ MouseArea {
+ property int swipeStart: 0
+
+ anchors.fill: parent
+ z: 10
+
+ onPressed: {
+ if (window.visibility === Window.FullScreen)
+ swipeStart = mouse.y;
+ _viewerHelper.handleMousePress(mouse.x, mouse.y, mouse.button, mouse.buttons,
+ mouse.modifiers);
+ mouse.accepted = true;
+ }
+ onReleased: {
+ _viewerHelper.handleMouseRelease(mouse.x, mouse.y, mouse.button, mouse.buttons,
+ mouse.modifiers);
+ mouse.accepted = true;
+ }
+ onPositionChanged: {
+ // Swipe down to exit fullscreen mode
+ if (window.visibility === Window.FullScreen && mouse.y > swipeStart + (height / 8)) {
+ window.visibility = window.previousVisibility;
+ } else {
+ _viewerHelper.handleMouseMove(mouse.x, mouse.y, mouse.button, mouse.buttons,
+ mouse.modifiers);
+ }
+ }
+ }
+
+ DropArea {
+ anchors.fill: parent
+ onEntered: {
+ if (drag.hasUrls) {
+ var filename = _viewerHelper.convertUrlListToFilename(drag.urls);
+ if (filename === "")
+ drag.accepted = false;
+ }
+ }
+ onDropped: {
+ if (drop.hasUrls) {
+ var filename = _viewerHelper.convertUrlListToFilename(drop.urls);
+ if (filename === "")
+ drag.accepted = false;
+ else
+ _viewerHelper.loadFile(filename);
+ }
+ }
+ }
+
+ Loader {
+ id: contentLoader
+ anchors.fill: parent
+ sourceComponent: {
+ switch (_viewerHelper.contentView) {
+ case ViewerHelper.StudioView:
+ return studioContent;
+ case ViewerHelper.ConnectView:
+ return connectContent;
+ case ViewerHelper.SequenceView:
+ return sequenceContent;
+ default:
+ return emptyContent;
+ }
+ }
+ Timer {
+ id: asyncContentChanger
+ repeat: false
+ interval: 0
+ property int view: ViewerHelper.DefaultView
+ function changeView(newView) {
+ view = newView;
+ start();
+ }
+
+ onTriggered: {
+ _viewerHelper.contentView = view;
+ }
+ }
+ }
+
+ Component {
+ id: emptyContent
+ Rectangle {
+ color: "black"
+ Label {
+ anchors.fill: parent
+ text: window.error
+ color: _textColor
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ font.pixelSize: width / 80
+ }
+ }
+ }
+
+ Component {
+ id: studioContent
+ Studio3D {
+ id: studio3D
+
+ property alias hiderVisible: hider.visible
+
+ focus: true
+ ViewerSettings {
+ matteColor: window.matteColor
+ showRenderStats: window.showRenderStats
+ scaleMode: window.scaleMode
+ }
+
+ // Hider item keeps the Studio3D hidden until it starts running and we reset the
+ // animation time to the start
+ Rectangle {
+ id: hider
+ color: "black"
+ anchors.fill: parent
+ }
+
+ Timer {
+ id: revealTimer
+ repeat: false
+ interval: 0
+ onTriggered: {
+ hider.visible = false;
+ }
+ }
+
+ onRunningChanged: {
+ if (running) {
+ // Successfully opened a presentation, update the open folder
+ _viewerHelper.openFolder = presentation.source.toString();
+ // Force the animation to start from the beginning, as the first frame render
+ // can take some time as shaders are compiled on-demand
+ // Localization note: "Scene" needs to be the same as the default "Scene"
+ // element name generated in the Studio application.
+ presentation.goToTime(qsTr("Scene"), 0);
+ revealTimer.start();
+ }
+ }
+ onErrorChanged: {
+ if (error.length > 0) {
+ window.error = error;
+ asyncContentChanger.changeView(ViewerHelper.DefaultView);
+ }
+ }
+ }
+ }
+
+ Component {
+ id: connectContent
+ Rectangle {
+ color: "black"
+ Label {
+ anchors.fill: parent
+ text: _viewerHelper.connectText
+ color: _textColor
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ font.pixelSize: width / 40
+ }
+ }
+ }
+
+ Component {
+ id: sequenceContent
+ Rectangle {
+ property alias mainText: mainLabel.text
+ property alias detailsText: detailsLabel.text
+ color: "black"
+ Item {
+ anchors.fill: parent
+ Label {
+ id: mainLabel
+ color: _textColor
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignBottom
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottomMargin: _controlPadding
+ height: parent.height / 2
+ font.pixelSize: width / 40
+ text: qsTr("Image sequence generation initializing...")
+ }
+ Label {
+ id: detailsLabel
+ color: _textColor
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignTop
+ anchors.top: mainLabel.bottom
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.topMargin: _controlPadding
+ height: parent.height / 2
+ font.pixelSize: width / 50
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ id: ipEntry
+ visible: false
+ color: _dialogBackgroundColor
+ border.color: _dialogBorderColor
+ y: (parent.height - height) / 2
+ x: (parent.width - width) / 2
+ width: connectionEntry.width + (2 * _controlPadding)
+ height: connectionEntry.height + (2 * _controlPadding)
+
+ onVisibleChanged: {
+ if (visible) {
+ connectText.forceActiveFocus();
+ connectText.selectAll();
+ }
+ }
+
+ Grid {
+ id: connectionEntry
+ spacing: _controlPadding
+ columns: 2
+ y: _controlPadding
+ x: _controlPadding
+ Label {
+ id: ipEntryLabel
+ width: _controlBaseWidth
+ height: _controlBaseHeight
+ text: qsTr("Enter IP port:")
+ color: _textColor
+ font.pixelSize: _fontSize
+ verticalAlignment: Text.AlignVCenter
+ padding: _controlPadding / 2
+ }
+ TextField {
+ id: connectText
+ width: _controlBaseWidth
+ height: _controlBaseHeight
+ font.pixelSize: _fontSize
+ color: _textColor
+ selectByMouse: true
+ padding: _controlPadding / 6
+ enabled: ipEntry.visible
+ text: _viewerHelper.connectPort
+ validator: IntValidator {
+ bottom: 1
+ top: 65535
+ }
+
+ onAccepted: {
+ if (ipEntry.visible) {
+ _viewerHelper.contentView = ViewerHelper.ConnectView;
+ _viewerHelper.connectPort = Number(text);
+ _viewerHelper.connectRemote();
+ ipEntry.visible = false;
+ }
+ }
+
+ background: Rectangle {
+ id: textBackground
+ color: _dialogFieldColor
+ border.width: 1
+ border.color: _dialogFieldBorderColor
+ radius: 2
+ }
+ }
+ StyledButton {
+ id: connectButton
+ width: _controlBaseWidth
+ text: qsTr("Connect")
+ onClicked: {
+ _viewerHelper.contentView = ViewerHelper.ConnectView;
+ _viewerHelper.connectRemote();
+ ipEntry.visible = false;
+ }
+ }
+ StyledButton {
+ id: cancelButton
+ width: _controlBaseWidth
+ text: qsTr("Cancel")
+ onClicked: {
+ ipEntry.visible = false;
+ }
+ }
+ }
+ }
+
+ Component {
+ id: fileDialogComponent
+ FileDialog {
+ id: fileDialog
+ title: qsTr("Choose Presentation or Project")
+ folder: _viewerHelper.openFolder
+ nameFilters: [qsTr("All supported formats (*.uip *.uia *.uiab)"),
+ qsTr("Studio UI Presentation (*.uip)"),
+ qsTr("Application file (*.uia)"),
+ qsTr("Binary Application (*.uiab)")]
+ onAccepted: {
+ _viewerHelper.contentView = ViewerHelper.StudioView;
+ contentLoader.item.presentation.setSource(fileUrls[0]);
+ }
+ }
+ }
+
+ header: Rectangle {
+ height: _controlBaseHeight
+ color: _menuBackgroundColor
+ visible: window.visibility !== Window.FullScreen
+
+ Row {
+ anchors.fill: parent
+ StyledMenuButton {
+ id: fileButton
+ text: qsTr("File")
+ menu: fileMenu
+ window: window
+
+ StyledMenu {
+ id: fileMenu
+ StyledMenuItem {
+ text: qsTr("Open...")
+ shortcut: StandardKey.Open
+ enabled: _viewerHelper.contentView !== ViewerHelper.SequenceView
+ onTriggered: {
+ if (enabled) {
+ fileDialogLoader.sourceComponent = fileDialogComponent;
+ fileDialogLoader.item.open();
+ }
+ }
+ Loader {
+ id: fileDialogLoader
+ sourceComponent: Item {}
+ }
+ }
+ StyledMenuItem {
+ text: qsTr("Connect")
+ shortcut: "F9"
+ enabled: _viewerHelper.contentView !== ViewerHelper.SequenceView
+ showCheckMark: _viewerHelper.connected
+ onTriggered: {
+ if (enabled)
+ ipEntry.visible = !ipEntry.visible;
+ }
+ }
+ StyledMenuItem {
+ text: qsTr("Reload")
+ enabled: _viewerHelper.contentView === ViewerHelper.StudioView
+ shortcut: "F5"
+ onTriggered: {
+ if (enabled) {
+ contentLoader.item.hiderVisible = true;
+ contentLoader.item.reset();
+ }
+ }
+ }
+ StyledMenuSeparator {}
+ StyledMenuItem {
+ text: qsTr("Quit")
+ shortcut: "Ctrl+Q"
+ onTriggered: {
+ window.close();
+ }
+ }
+ }
+ }
+ StyledMenuButton {
+ id: viewButton
+ text: qsTr("View")
+ menu: viewMenu
+ window: window
+
+ StyledMenu {
+ id: viewMenu
+ StyledMenuItem {
+ text: qsTr("Show Matte")
+ shortcut: "F6"
+ enabled: _viewerHelper.contentView === ViewerHelper.StudioView
+ onTriggered: {
+ if (enabled) {
+ if (window.matteColor === Qt.rgba(0, 0, 0, 1)) {
+ window.matteColor = Qt.rgba(0.2, 0.2, 0.2, 1);
+ showCheckMark = true;
+ } else {
+ window.matteColor = Qt.rgba(0, 0, 0, 1);
+ showCheckMark = false;
+ }
+ }
+ }
+ }
+ StyledMenuItem {
+ id: scaleMenuItem
+ text: qsTr("Scale Mode")
+ showArrow: true
+ arrowMenu: scaleMenu
+ enabled: _viewerHelper.contentView === ViewerHelper.StudioView
+ StyledMenu {
+ id: scaleMenu
+ x: parent.width
+ y: 0
+ function clearChecks() {
+ scaleCenter.showCheckMark = false;
+ scaleFit.showCheckMark = false;
+ scaleFill.showCheckMark = false;
+ }
+
+ StyledMenuItem {
+ id: scaleCenter
+ text: qsTr("Center")
+ shortcut: "F2"
+ showCheckMark: true
+ enabled: _viewerHelper.contentView === ViewerHelper.StudioView
+ onTriggered: {
+ if (enabled) {
+ scaleMenu.clearChecks();
+ window.scaleMode = ViewerSettings.ScaleModeCenter;
+ showCheckMark = true;
+ }
+ }
+ }
+ StyledMenuItem {
+ id: scaleFit
+ text: qsTr("Scale to Fit")
+ shortcut: "F3"
+ enabled: _viewerHelper.contentView === ViewerHelper.StudioView
+ onTriggered: {
+ if (enabled) {
+ scaleMenu.clearChecks();
+ window.scaleMode = ViewerSettings.ScaleModeFit;
+ showCheckMark = true;
+ }
+ }
+ }
+ StyledMenuItem {
+ id: scaleFill
+ text: qsTr("Scale to Fill")
+ shortcut: "F4"
+ enabled: _viewerHelper.contentView === ViewerHelper.StudioView
+ onTriggered: {
+ if (enabled) {
+ scaleMenu.clearChecks();
+ window.scaleMode = ViewerSettings.ScaleModeFill;
+ showCheckMark = true;
+ }
+ }
+ }
+ }
+ }
+ StyledMenuItem {
+ text: qsTr("Show Render Statistics")
+ shortcut: "F1"
+ enabled: _viewerHelper.contentView === ViewerHelper.StudioView
+ onTriggered: {
+ if (enabled) {
+ window.showRenderStats =
+ !contentLoader.item.viewerSettings.showRenderStats;
+ showCheckMark = window.showRenderStats;
+ }
+ }
+ }
+ StyledMenuSeparator {}
+ StyledMenuItem {
+ text: qsTr("Full Screen")
+ shortcut: "F11"
+ onTriggered: {
+ if (window.visibility !== Window.FullScreen) {
+ window.previousVisibility = window.visibility
+ window.visibility = Window.FullScreen;
+ } else {
+ window.visibility = window.previousVisibility;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/Viewer/Qt3DViewer/remotedeploymentreceiver.cpp b/src/Viewer/Qt3DViewer/remotedeploymentreceiver.cpp
index afe05030..81fb488c 100644
--- a/src/Viewer/Qt3DViewer/remotedeploymentreceiver.cpp
+++ b/src/Viewer/Qt3DViewer/remotedeploymentreceiver.cpp
@@ -28,34 +28,19 @@
****************************************************************************/
#include "remotedeploymentreceiver.h"
-#include "mainwindow.h"
+#include "viewer.h"
#include <QtNetwork>
-#include <QtWidgets/qinputdialog.h>
-RemoteDeploymentReceiver::RemoteDeploymentReceiver(QWidget *parent)
+RemoteDeploymentReceiver::RemoteDeploymentReceiver(int serverPort, QObject *parent)
: QObject(parent)
- , m_mainWindow(parent)
, m_tcpServer(0)
, m_connection(0)
, m_temporaryDir(0)
- , m_serverPort(36000)
+ , m_serverPort(serverPort)
, m_projectDeployed(false)
- , m_canceled(false)
{
m_incoming.setVersion(QDataStream::Qt_5_8);
-
- QInputDialog inputPort;
- inputPort.setLabelText(tr("Enter IP Port:"));
- inputPort.setInputMode(QInputDialog::IntInput);
- inputPort.setIntMinimum(0);
- inputPort.setIntMaximum(65536);
- inputPort.setIntValue(m_serverPort);
- inputPort.setWindowFlags(Qt::Popup);
- // We don't have to worry about cancel with this, as the dialog is always recreated when
- // initializing the connection.
- connect(&inputPort, &QInputDialog::intValueSelected, this, &RemoteDeploymentReceiver::setPort);
- m_canceled = (inputPort.exec() != 1);
}
RemoteDeploymentReceiver::~RemoteDeploymentReceiver()
@@ -69,18 +54,18 @@ void RemoteDeploymentReceiver::setPort(int value)
m_serverPort = value;
}
-bool RemoteDeploymentReceiver::startServer()
+QString RemoteDeploymentReceiver::startServer()
{
if (m_tcpServer)
- return true;
+ return QString();
m_tcpServer = new QTcpServer(this);
if (!m_tcpServer->listen(QHostAddress::Any, m_serverPort)) {
- qWarning() << "Can't start the remote connection: "
- << m_tcpServer->errorString();
+ QString error = tr("Can't start the remote connection: '%1'")
+ .arg(m_tcpServer->errorString());
delete m_tcpServer;
m_tcpServer = 0;
- return false;
+ return error;
}
QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
@@ -100,7 +85,7 @@ bool RemoteDeploymentReceiver::startServer()
m_serverPort = m_tcpServer->serverPort();
connect(m_tcpServer, SIGNAL(newConnection()),
this, SLOT(acceptRemoteConnection()));
- return true;
+ return QString();
}
void RemoteDeploymentReceiver::acceptRemoteConnection()
@@ -143,8 +128,11 @@ void RemoteDeploymentReceiver::readProject()
int totalBytes = 0;
m_incoming >> totalBytes;
- qobject_cast<MainWindow *>(m_mainWindow)->updateProgress(
- 100 * ((double)m_connection->bytesAvailable() / (double)totalBytes));
+ Viewer *viewer = qobject_cast<Viewer *>(parent());
+ if (viewer && totalBytes != 0) {
+ viewer->updateProgress(
+ 100 * ((double)m_connection->bytesAvailable() / (double)totalBytes));
+ }
if (m_connection->bytesAvailable() < totalBytes) {
m_incoming.rollbackTransaction();
diff --git a/src/Viewer/Qt3DViewer/remotedeploymentreceiver.h b/src/Viewer/Qt3DViewer/remotedeploymentreceiver.h
index 51b485ae..95744808 100644
--- a/src/Viewer/Qt3DViewer/remotedeploymentreceiver.h
+++ b/src/Viewer/Qt3DViewer/remotedeploymentreceiver.h
@@ -35,16 +35,15 @@
#include <QtCore/qdatastream.h>
#include <QtCore/qtemporarydir.h>
#include <QtNetwork/qtcpserver.h>
-#include <QtWidgets/qwidget.h>
class RemoteDeploymentReceiver : public QObject
{
Q_OBJECT
public:
- explicit RemoteDeploymentReceiver(QWidget *parent);
+ explicit RemoteDeploymentReceiver(int serverPort, QObject *parent);
~RemoteDeploymentReceiver();
- bool startServer();
+ QString startServer();
QHostAddress hostAddress() const { return m_hostAddress; }
int serverPort() const { return m_serverPort; }
@@ -52,7 +51,6 @@ public:
bool isConnected() const { return m_connection; }
bool isProjectDeployed() const { return m_connection && m_projectDeployed; }
QString fileName() const { return m_projectFile; }
- bool canceled() const { return m_canceled; }
Q_SIGNALS:
void projectChanged();
@@ -67,7 +65,6 @@ private Q_SLOTS:
void setPort(int value);
private:
- QWidget *m_mainWindow = nullptr;
QTcpServer *m_tcpServer = nullptr;
QTcpSocket *m_connection = nullptr;
QHostAddress m_hostAddress;
@@ -76,7 +73,6 @@ private:
QString m_projectFile;
bool m_projectDeployed;
int m_serverPort;
- bool m_canceled;
};
#endif // REMOTEDEPLOYMENTRECEIVER_H
diff --git a/src/Viewer/Qt3DViewer/resources/images/ViewerDoc.ico b/src/Viewer/Qt3DViewer/resources/images/ViewerDoc.ico
deleted file mode 100644
index 02779b0d..00000000
--- a/src/Viewer/Qt3DViewer/resources/images/ViewerDoc.ico
+++ /dev/null
Binary files differ
diff --git a/src/Viewer/Qt3DViewer/resources/images/arrow.png b/src/Viewer/Qt3DViewer/resources/images/arrow.png
new file mode 100644
index 00000000..40ebda88
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/resources/images/arrow.png
Binary files differ
diff --git a/src/Viewer/Qt3DViewer/resources/images/arrow@2x.png b/src/Viewer/Qt3DViewer/resources/images/arrow@2x.png
new file mode 100644
index 00000000..1a21ee06
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/resources/images/arrow@2x.png
Binary files differ
diff --git a/src/Viewer/Qt3DViewer/resources/images/check.png b/src/Viewer/Qt3DViewer/resources/images/check.png
new file mode 100644
index 00000000..5c1ef70a
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/resources/images/check.png
Binary files differ
diff --git a/src/Viewer/Qt3DViewer/resources/images/check@2x.png b/src/Viewer/Qt3DViewer/resources/images/check@2x.png
new file mode 100644
index 00000000..ed730bfe
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/resources/images/check@2x.png
Binary files differ
diff --git a/src/Viewer/Qt3DViewer/resources/images/icon_256x256.png b/src/Viewer/Qt3DViewer/resources/images/icon_256x256.png
deleted file mode 100644
index 0c7bf48b..00000000
--- a/src/Viewer/Qt3DViewer/resources/images/icon_256x256.png
+++ /dev/null
Binary files differ
diff --git a/src/Viewer/Qt3DViewer/resources/images/icon_256x256@2x.png b/src/Viewer/Qt3DViewer/resources/images/icon_256x256@2x.png
deleted file mode 100644
index 29a8ed75..00000000
--- a/src/Viewer/Qt3DViewer/resources/images/icon_256x256@2x.png
+++ /dev/null
Binary files differ
diff --git a/src/Viewer/Qt3DViewer/resources/wordlist/wordlist.txt b/src/Viewer/Qt3DViewer/resources/wordlist/wordlist.txt
deleted file mode 100644
index 59afadae..00000000
--- a/src/Viewer/Qt3DViewer/resources/wordlist/wordlist.txt
+++ /dev/null
@@ -1,81 +0,0 @@
-_ENV
-_VERSION
-assert
-break
-calculateBoundingbox
-calculateGlobalTransform
-collectgarbage
-dofile
-else
-elseif
-error
-fireEvent
-fireEventOnPresentation
-fireFlowEvent
-function
-getAttribute
-getChildren
-getcurrentSlide
-getElapsedTime
-getElement
-getElementType
-getfenv
-getmetatable
-getMousePosition
-getScreenInfo
-getTime
-goToBackSlide
-goToNextSlide
-goToPreviousSlide
-goToSlide
-goToTime
-hasAttribute
-io.stderr
-io.stdin
-io.stdout
-ipairs
-load
-loadfile
-loadstring
-local
-math.huge
-math.pi
-measureText
-module
-next
-output
-package.config
-package.cpath
-package.loaded
-package.loaders
-package.path
-package.preload
-package.searchers
-pairs
-payse
-pcall
-play
-print
-rawequal
-rawget
-rawlen
-rawset
-registerForChange
-registerForEvent
-repeat
-require
-return
-select
-self
-setAttribute
-setfenv
-setmetatable
-then
-tonumber
-tostring
-type
-unpack
-unregisterForEvent
-until
-while
-xpcall \ No newline at end of file
diff --git a/src/Viewer/Qt3DViewer/style_android.qss b/src/Viewer/Qt3DViewer/style_android.qss
deleted file mode 100644
index bd92364b..00000000
--- a/src/Viewer/Qt3DViewer/style_android.qss
+++ /dev/null
@@ -1,130 +0,0 @@
-/* General coloring and font size */
-QWidget {
- color: #ffffff;
- background: #2e2f30;
- font-size: 20px;
- border: 0px;
-}
-
-/* Scrollbar */
-QScrollBar:horizontal {
- border: 1px solid #262829;
- background: #404244;
- height: 40px;
-}
-
-QScrollBar::handle:horizontal {
- background: #727476;
-}
-
-QScrollBar::add-line:horizontal,
-QScrollBar::sub-line:horizontal {
- width: 0px;
-}
-
-QScrollBar:vertical {
- border: 1px solid #262829;
- background: #404244;
- width: 40px;
-}
-
-QScrollBar::handle:vertical {
- background: #727476;
-}
-
-QScrollBar::add-line:vertical,
-QScrollBar::sub-line:vertical {
- height: 0px;
-}
-
-/* Toolbar */
-QToolBar {
- min-height: 40px;
- max-height: 40px;
-}
-
-QToolButton:!checked {
- background-color: #404244;
- margin-bottom: 9px;
-}
-
-QToolButton:checked {
- background-color: #262829;
- margin-bottom: 9px;
-}
-
-QToolButton:pressed {
- background-color: #46a2da;
- margin-bottom: 9px;
-}
-
-/* Dialog widgets */
-QComboBox,
-QLineEdit {
- background: #404244;
- border: 1px solid #262829;
- border-radius: 2;
- height: 40px;
- padding: 3px;
- margin-bottom: 9px;
-}
-
-QSpinBox {
- background: #404244;
- border: 11px solid #262829;
- border-radius: 2;
- height: 60px;
- padding: -10px;
-}
-
-QSpinBox::up-button {
- background: #404244;
- width: 40px;
- padding: 10px;
- border: 0px;
- margin-top: -10px;
- margin-right: -10px;
-}
-
-QSpinBox::down-button
-{
- background: #404244;
- width: 40px;
- padding: 10px;
- border: 0px;
- margin-bottom: -10px;
- margin-right: -10px;
-}
-
-QComboBox::drop-down {
- background: #404244;
- width: 40px;
- border: 0px;
-}
-
-QComboBox::down-arrow,
-QSpinBox::down-arrow {
- image: url(:/images/arrow_down.png);
-}
-
-QSpinBox::up-arrow {
- image: url(:/images/arrow_up.png);
-}
-
-QPushButton {
- background: #404244;
- border: 1px solid #262829;
- border-radius: 2;
- padding: 3px 10px 3px 10px;
- min-height: 40px;
- min-width: 75px;
- margin-bottom: 9px;
-}
-
-QPushButton::pressed {
- background-color: #46a2da;
-}
-
-QFileDialog {
- min-width: 850px;
-}
diff --git a/src/Viewer/Qt3DViewer/viewer.cpp b/src/Viewer/Qt3DViewer/viewer.cpp
new file mode 100644
index 00000000..871f9654
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/viewer.cpp
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qsettings.h>
+#include <QtCore/qfileinfo.h>
+#include <QtStudio3D/private/q3dsviewersettings_p.h>
+#include <QtStudio3D/private/q3dspresentation_p.h>
+#include <QtGui/qguiapplication.h>
+#include <QtQuick/qquickwindow.h>
+
+#include "viewer.h"
+#include "q3dspresentationitem.h"
+
+Viewer::Viewer(bool generatorMode, QObject *parent)
+ : QObject(parent)
+ , m_generatorMode(generatorMode)
+{
+ if (m_generatorMode)
+ setContentView(SequenceView);
+}
+
+Viewer::~Viewer()
+{
+}
+
+void Viewer::connectRemote()
+{
+ if (m_remoteDeploymentReceiver) {
+ delete m_remoteDeploymentReceiver;
+ m_remoteDeploymentReceiver = 0;
+ Q_EMIT connectedChanged();
+ }
+
+ m_remoteDeploymentReceiver = new RemoteDeploymentReceiver(m_connectPort, this);
+ QString error = m_remoteDeploymentReceiver->startServer();
+ if (!error.isEmpty()) {
+ delete m_remoteDeploymentReceiver;
+ m_remoteDeploymentReceiver = nullptr;
+ setContentView(DefaultView);
+ m_qmlRootObject->setProperty("error", QVariant(error));
+ return;
+ }
+
+ m_connectText.clear();
+ QTextStream stream(&m_connectText);
+ stream << tr("Connection Info\nAddress: %1\nPort: %2")
+ .arg(m_remoteDeploymentReceiver->hostAddress().toString())
+ .arg(QString::number(m_connectPort));
+ Q_EMIT connectTextChanged();
+
+ connect(m_remoteDeploymentReceiver, &RemoteDeploymentReceiver::remoteConnected,
+ this, &Viewer::remoteConnected);
+
+ connect(m_remoteDeploymentReceiver, &RemoteDeploymentReceiver::remoteDisconnected,
+ this, &Viewer::remoteDisconnected);
+
+ connect(m_remoteDeploymentReceiver, &RemoteDeploymentReceiver::projectChanging,
+ this, &Viewer::remoteProjectChanging);
+
+ connect(m_remoteDeploymentReceiver, &RemoteDeploymentReceiver::projectChanged,
+ this, &Viewer::loadRemoteDeploymentReceiver);
+
+ Q_EMIT connectedChanged();
+}
+
+// Used to load files via command line
+void Viewer::loadFile(const QString &filename)
+{
+ QFileInfo fileInfo(filename);
+ if (!fileInfo.exists()) {
+ setContentView(DefaultView);
+ m_qmlRootObject->setProperty(
+ "error", QVariant(tr("Tried to load nonexistent file %1").arg(filename)));
+ return;
+ }
+
+ QUrl sourceUrl = QUrl::fromLocalFile(fileInfo.absoluteFilePath());
+
+ setContentView(StudioView);
+
+ if (qmlStudio())
+ qmlStudio()->presentation()->setSource(sourceUrl);
+}
+
+QString Viewer::convertUrlListToFilename(const QList<QUrl> &list)
+{
+ for (const QUrl &url : list) {
+ QString str = url.toLocalFile();
+ if (str.isEmpty() == false) {
+ if ((QFileInfo(str).suffix() == "uip")
+ || (QFileInfo(str).suffix() == "uia")
+ || (QFileInfo(str).suffix() == "uiab"))
+ {
+ return str;
+ }
+ }
+ }
+ return QString();
+}
+
+void Viewer::restoreWindowState(QWindow *window)
+{
+ QSettings settings;
+ QRect geo = settings.value(QStringLiteral("WindowGeometry"), QRect()).toRect();
+ int visibility = settings.value(QStringLiteral("WindowVisibility"),
+ QWindow::Windowed).toInt();
+
+ if (!geo.isNull()) {
+ // The first geometry set at startup may adjust the geometry according to pixel
+ // ratio if mouse cursor is on different screen than where window goes and the
+ // two screens have different pixel ratios. Setting geometry twice seems to
+ // work around this.
+ geo.adjust(0, 0, -1, 0);
+ window->setGeometry(geo);
+ geo.adjust(0, 0, 1, 0);
+ window->setGeometry(geo);
+ }
+
+ window->setVisibility(QWindow::Visibility(visibility));
+}
+
+void Viewer::storeWindowState(QWindow *window)
+{
+ QSettings settings;
+ settings.setValue(QStringLiteral("WindowGeometry"), window->geometry());
+ settings.setValue(QStringLiteral("WindowState"), window->visibility());
+}
+
+// Since we need mouse events for handling the swipe gesture in viewer, we need to generate
+// a fake event for the presentation.
+void Viewer::handleMousePress(int x, int y, int button, int buttons, int modifiers)
+{
+ if (qmlStudio()) {
+ QMouseEvent fakeEvent(QEvent::MouseButtonPress,
+ QPointF(x, y) * qmlStudio()->window()->devicePixelRatio(),
+ Qt::MouseButton(button),
+ Qt::MouseButtons(buttons),
+ Qt::KeyboardModifiers(modifiers));
+ qmlStudio()->presentation()->mousePressEvent(&fakeEvent);
+ }
+}
+
+void Viewer::handleMouseRelease(int x, int y, int button, int buttons, int modifiers)
+{
+ if (qmlStudio()) {
+ QMouseEvent fakeEvent(QEvent::MouseButtonRelease,
+ QPointF(x, y) * qmlStudio()->window()->devicePixelRatio(),
+ Qt::MouseButton(button),
+ Qt::MouseButtons(buttons),
+ Qt::KeyboardModifiers(modifiers));
+ qmlStudio()->presentation()->mouseReleaseEvent(&fakeEvent);
+ }
+}
+
+void Viewer::handleMouseMove(int x, int y, int button, int buttons, int modifiers)
+{
+ if (qmlStudio()) {
+ QMouseEvent fakeEvent(QEvent::MouseMove,
+ QPointF(x, y) * qmlStudio()->window()->devicePixelRatio(),
+ Qt::MouseButton(button),
+ Qt::MouseButtons(buttons),
+ Qt::KeyboardModifiers(modifiers));
+ qmlStudio()->presentation()->mouseMoveEvent(&fakeEvent);
+ }
+}
+
+void Viewer::setContentView(Viewer::ContentView view)
+{
+ if (view != m_contentView) {
+ m_qmlStudio = nullptr;
+ m_contentView = view;
+ Q_EMIT contentViewChanged();
+ }
+}
+
+Viewer::ContentView Viewer::contentView() const
+{
+ return m_contentView;
+}
+
+void Viewer::setOpenFolder(const QUrl &folder)
+{
+ QString localFolder = folder.toLocalFile();
+ QFileInfo fi(localFolder);
+ QString newDir;
+ if (fi.isDir())
+ newDir = fi.absoluteFilePath();
+ else
+ newDir = fi.absolutePath();
+ if (newDir != m_openFileDir) {
+ m_openFileDir = newDir;
+ QSettings settings;
+ settings.setValue(QStringLiteral("DirectoryOfLastOpen"), m_openFileDir);
+ Q_EMIT openFolderChanged();
+ }
+}
+
+QUrl Viewer::openFolder()
+{
+ if (m_openFileDir.size() == 0) {
+ QSettings settings;
+ m_openFileDir = settings.value(QStringLiteral("DirectoryOfLastOpen"),
+ QString("")).toString();
+#ifdef Q_OS_ANDROID
+ if (m_openFileDir.isEmpty())
+ m_openFileDir = QStringLiteral("/sdcard/qt3dviewer"); // Add default folder for Android
+#endif
+ }
+ return QUrl::fromLocalFile(m_openFileDir);
+}
+
+void Viewer::setConnectPort(int port)
+{
+ if (m_connectPort != port) {
+ QSettings settings;
+ m_connectPort = port;
+ settings.setValue(QStringLiteral("ConnectPort"), m_connectPort);
+ Q_EMIT connectPortChanged();
+ }
+}
+
+int Viewer::connectPort()
+{
+ if (m_connectPort < 0) {
+ QSettings settings;
+ m_connectPort = settings.value(QStringLiteral("ConnectPort"), 36000).toInt();
+ }
+ return m_connectPort;
+}
+
+QString Viewer::connectText() const
+{
+ return m_connectText;
+}
+
+bool Viewer::isConnected() const
+{
+ return m_remoteDeploymentReceiver ? m_remoteDeploymentReceiver->isConnected() : false;
+}
+
+void Viewer::setQmlRootObject(QObject *obj)
+{
+ m_qmlRootObject = obj;
+}
+
+void Viewer::loadRemoteDeploymentReceiver()
+{
+ Q_ASSERT(m_remoteDeploymentReceiver);
+ const QString remote = m_remoteDeploymentReceiver->fileName();
+ QMetaObject::invokeMethod(this, "loadFile", Qt::QueuedConnection, Q_ARG(QString, remote));
+}
+
+void Viewer::remoteProjectChanging()
+{
+ if (m_contentView != ConnectView)
+ setContentView(ConnectView);
+ m_connectText = tr("Loading remote project...");
+ Q_EMIT connectTextChanged();
+}
+
+void Viewer::remoteConnected()
+{
+ m_connectText = tr("Remote Connected");
+ Q_EMIT connectTextChanged();
+ Q_EMIT connectedChanged();
+}
+
+void Viewer::remoteDisconnected()
+{
+ m_connectText = tr("Remote Disconnected");
+ Q_EMIT connectTextChanged();
+ Q_EMIT connectedChanged();
+}
+
+Q3DSView *Viewer::qmlStudio()
+{
+ if (m_contentView == StudioView) {
+ if (!m_qmlStudio) {
+ QObject *loadedContent = m_qmlRootObject->property("loadedContent").value<QObject *>();
+ m_qmlStudio = static_cast<Q3DSView *>(loadedContent);
+ }
+ } else {
+ m_qmlStudio = nullptr;
+ }
+ return m_qmlStudio;
+}
+
+void Viewer::generatorProgress(int totalFrames, int frameCount)
+{
+ QString progressString;
+ if (frameCount >= totalFrames) {
+ progressString =
+ QCoreApplication::translate(
+ "main", "Image sequence generation done! (%2 frames generated)")
+ .arg(totalFrames);
+ } else {
+ progressString =
+ QCoreApplication::translate("main", "Image sequence generation progress: %1 / %2")
+ .arg(frameCount).arg(totalFrames);
+ }
+ QObject *loadedContent = m_qmlRootObject->property("loadedContent").value<QObject *>();
+ loadedContent->setProperty("mainText", progressString);
+}
+
+void Viewer::generatorFinished(bool success, const QString &details)
+{
+ QObject *loadedContent = m_qmlRootObject->property("loadedContent").value<QObject *>();
+ if (success) {
+ loadedContent->setProperty("detailsText", details);
+ } else {
+ QString mainString =
+ QCoreApplication::translate("main", "Image sequence generation failed:");
+ loadedContent->setProperty("mainText", mainString);
+ loadedContent->setProperty("detailsText", details);
+ }
+}
+
+void Viewer::updateProgress(int percent)
+{
+ // Don't wait for 100%, as it'll already start loading and text isn't updated anymore
+ if (percent >= 99)
+ m_connectText = tr("Loading remote project...");
+ else
+ m_connectText = QStringLiteral("Receiving (%1%)").arg(percent);
+ Q_EMIT connectTextChanged();
+}
+
+void Viewer::setGeneratorDetails(const QString &filename)
+{
+ QObject *loadedContent = m_qmlRootObject->property("loadedContent").value<QObject *>();
+ loadedContent->setProperty("detailsText", filename);
+}
diff --git a/src/Viewer/Qt3DViewer/viewer.h b/src/Viewer/Qt3DViewer/viewer.h
new file mode 100644
index 00000000..7114728f
--- /dev/null
+++ b/src/Viewer/Qt3DViewer/viewer.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VIEWER_H
+#define VIEWER_H
+
+#include "remotedeploymentreceiver.h"
+
+#include <QtCore/qobject.h>
+#include <QtCore/qurl.h>
+#include <QtGui/qwindow.h>
+#include "Qt3DSView.h"
+
+class Viewer : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(ContentView contentView READ contentView WRITE setContentView NOTIFY contentViewChanged)
+ Q_PROPERTY(QUrl openFolder READ openFolder WRITE setOpenFolder NOTIFY openFolderChanged)
+ Q_PROPERTY(int connectPort READ connectPort WRITE setConnectPort NOTIFY connectPortChanged)
+ Q_PROPERTY(QString connectText READ connectText NOTIFY connectTextChanged)
+ Q_PROPERTY(bool connected READ isConnected NOTIFY connectedChanged)
+
+public:
+ enum ContentView {
+ DefaultView,
+ StudioView,
+ ConnectView,
+ SequenceView
+ };
+
+ Q_ENUM(ContentView)
+
+ explicit Viewer(bool generatorMode, QObject *parent = nullptr);
+ ~Viewer();
+
+ Q_INVOKABLE void connectRemote();
+ Q_INVOKABLE void loadFile(const QString &filename);
+ Q_INVOKABLE QString convertUrlListToFilename(const QList<QUrl> &list);
+ Q_INVOKABLE void restoreWindowState(QWindow *window);
+ Q_INVOKABLE void storeWindowState(QWindow *window);
+
+ Q_INVOKABLE void handleMousePress(int x, int y, int button, int buttons, int modifiers);
+ Q_INVOKABLE void handleMouseRelease(int x, int y, int button, int buttons, int modifiers);
+ Q_INVOKABLE void handleMouseMove(int x, int y, int button, int buttons, int modifiers);
+
+ void setContentView(ContentView view);
+ ContentView contentView() const;
+ void setOpenFolder(const QUrl &folder);
+ QUrl openFolder(); // not const since it potentially updates from settings
+ void setConnectPort(int port);
+ int connectPort(); // not const since it potentially updates from settings
+ QString connectText() const;
+ bool isConnected() const;
+ QRect initialRect() const;
+ int initialState() const;
+
+ void setQmlRootObject(QObject *obj);
+
+ void loadProject(const QByteArray &data);
+ void updateProgress(int percent);
+ void setGeneratorDetails(const QString &filename);
+
+public Q_SLOTS:
+ void generatorProgress(int totalFrames, int frameCount);
+ void generatorFinished(bool success, const QString &details);
+
+private Q_SLOTS:
+ void loadRemoteDeploymentReceiver();
+ void remoteProjectChanging();
+ void remoteConnected();
+ void remoteDisconnected();
+
+Q_SIGNALS:
+ void contentViewChanged();
+ void openFolderChanged();
+ void connectPortChanged();
+ void connectTextChanged();
+ void connectedChanged();
+
+private:
+ Q3DSView *qmlStudio();
+
+ QString m_openFileDir;
+ RemoteDeploymentReceiver *m_remoteDeploymentReceiver = nullptr;
+ bool m_generatorMode = false;
+ ContentView m_contentView = DefaultView;
+ QObject *m_qmlRootObject = nullptr;
+ int m_connectPort = -1;
+ QString m_connectText;
+ Q3DSView *m_qmlStudio = nullptr;
+};
+
+#endif // VIEWER_H