diff options
Diffstat (limited to 'src/Viewer/Qt3DViewer/viewer.cpp')
-rw-r--r-- | src/Viewer/Qt3DViewer/viewer.cpp | 359 |
1 files changed, 359 insertions, 0 deletions
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); +} |