diff options
author | Martin Kampas <martin.kampas@jolla.com> | 2016-11-05 08:49:59 +0100 |
---|---|---|
committer | Juergen Bocklage-Ryannel <juergen.bocklage-ryannel@pelagicore.com> | 2016-11-23 05:24:41 +0000 |
commit | 6b6c17f19bda671d6f9553662f1475241837f533 (patch) | |
tree | 056e7dce77f805474732b287e7d7aff81ff7bbf0 | |
parent | d99e8c0513cba836972be008007ea97ad145f236 (diff) |
Consistently and reliably handle paths to workspace documents
Use relative paths. Consistently and reliably means Always.
Change-Id: I660ad89a9b9b8baee782aa701ea101ea542c70ce
Reviewed-by: Juergen Bocklage-Ryannel <juergen.bocklage-ryannel@pelagicore.com>
32 files changed, 485 insertions, 159 deletions
diff --git a/src/bench/allhostswidget.cpp b/src/bench/allhostswidget.cpp index add6e0e..899be34 100644 --- a/src/bench/allhostswidget.cpp +++ b/src/bench/allhostswidget.cpp @@ -31,6 +31,7 @@ #include "allhostswidget.h" +#include "livedocument.h" AllHostsWidget::AllHostsWidget(QWidget *parent) : QWidget(parent) @@ -95,6 +96,6 @@ void AllHostsWidget::dropEvent(QDropEvent *event) QUrl url(event->mimeData()->text()); if (url.isLocalFile()) - emit currentFileChanged(url.toLocalFile()); + emit currentFileChanged(LiveDocument::resolve(m_workspace, url.toLocalFile())); event->acceptProposedAction(); } diff --git a/src/bench/allhostswidget.h b/src/bench/allhostswidget.h index 47f4460..a53785f 100644 --- a/src/bench/allhostswidget.h +++ b/src/bench/allhostswidget.h @@ -33,6 +33,8 @@ #include <QtWidgets> +class LiveDocument; + class AllHostsWidget : public QWidget { Q_OBJECT @@ -44,7 +46,7 @@ public: signals: void refreshAll(); void publishAll(); - void currentFileChanged(const QString file); + void currentFileChanged(const LiveDocument &file); protected: void dropEvent(QDropEvent *event); diff --git a/src/bench/benchlivenodeengine.cpp b/src/bench/benchlivenodeengine.cpp index abe1910..30dd5b5 100644 --- a/src/bench/benchlivenodeengine.cpp +++ b/src/bench/benchlivenodeengine.cpp @@ -108,7 +108,11 @@ void BenchLiveNodeEngine::initPlugins() DirectoryPreviewAdapter *adapter = new DirectoryPreviewAdapter(this); if (m_workspaceView) { //This needs to be QueuedConnection because Qt5 doesn't like it to destruct it's object while it is in a signalHandler - connect(adapter, SIGNAL(loadDocument(QString)), m_workspaceView, SLOT(activateDocument(QString)), Qt::QueuedConnection); + connect(adapter, &DirectoryPreviewAdapter::loadDocument, + this, [this](const QString &document) { + m_workspaceView->activateDocument(LiveDocument(document)); + }, + Qt::QueuedConnection); } QmlPreviewAdapter *previewAdapter = new QmlPreviewAdapter(this); diff --git a/src/bench/host.cpp b/src/bench/host.cpp index fb1f366..fc54513 100644 --- a/src/bench/host.cpp +++ b/src/bench/host.cpp @@ -73,7 +73,7 @@ QString Host::address() const return m_address; } -QString Host::currentFile() const +LiveDocument Host::currentFile() const { return m_currentFile; } @@ -109,7 +109,7 @@ void Host::setAddress(QString arg) } } -void Host::setCurrentFile(QString arg) +void Host::setCurrentFile(LiveDocument arg) { m_currentFile = arg; emit currentFileChanged(arg); @@ -208,7 +208,7 @@ void Host::saveToSettings(QSettings *s) s->setValue("xOffset", xOffset()); s->setValue("yOffset", yOffset()); s->setValue("rotation", rotation()); - s->setValue("currentFile", currentFile()); + s->setValue("currentFile", currentFile().relativeFilePath()); s->setValue("autoDiscoveryId", autoDiscoveryId().toString()); s->setValue("systemName", systemName()); s->setValue("productVersion", productVersion()); @@ -226,7 +226,7 @@ void Host::restoreFromSettings(QSettings *s) setXOffset(s->value("xOffset").toInt()); setYOffset(s->value("yOffset").toInt()); setRotation(s->value("rotation").toInt()); - setCurrentFile(s->value("currentFile").toString()); + setCurrentFile(LiveDocument(s->value("currentFile").toString())); setAutoDiscoveryId(QUuid(s->value("autoDiscoveryId").toString())); setSystemName(s->value("systemName").toString()); setProductVersion(s->value("productVersion").toString()); diff --git a/src/bench/host.h b/src/bench/host.h index 658303c..e04b4a8 100644 --- a/src/bench/host.h +++ b/src/bench/host.h @@ -31,6 +31,8 @@ #pragma once +#include "livedocument.h" + #include <QObject> #include <QUuid> #include <QMetaType> @@ -51,7 +53,7 @@ public: Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(QString address READ address WRITE setAddress NOTIFY addressChanged) Q_PROPERTY(int port READ port WRITE setPort NOTIFY portChanged) - Q_PROPERTY(QString currentFile READ currentFile WRITE setCurrentFile NOTIFY currentFileChanged) + Q_PROPERTY(LiveDocument currentFile READ currentFile WRITE setCurrentFile NOTIFY currentFileChanged) Q_PROPERTY(int xOffset READ xOffset WRITE setXOffset NOTIFY xOffsetChanged) Q_PROPERTY(int yOffset READ yOffset WRITE setYOffset NOTIFY yOffsetChanged) Q_PROPERTY(int rotation READ rotation WRITE setRotation NOTIFY rotationChanged) @@ -67,7 +69,7 @@ public: QString name() const; QString address() const; int port() const; - QString currentFile() const; + LiveDocument currentFile() const; int xOffset() const; int yOffset() const; int rotation() const; @@ -88,7 +90,7 @@ signals: void nameChanged(QString arg); void addressChanged(QString arg); void portChanged(int arg); - void currentFileChanged(QString arg); + void currentFileChanged(LiveDocument arg); void xOffsetChanged(int arg); void yOffsetChanged(int arg); void rotationChanged(int arg); @@ -102,7 +104,7 @@ public slots: void setName(QString arg); void setAddress(QString arg); void setPort(int arg); - void setCurrentFile(QString arg); + void setCurrentFile(LiveDocument arg); void setXOffset(int arg); void setYOffset(int arg); void setRotation(int arg); @@ -117,7 +119,7 @@ private: QString m_name; QString m_address; int m_port; - QString m_currentFile; + LiveDocument m_currentFile; int m_xOffset; int m_yOffset; int m_rotation; diff --git a/src/bench/hostmanager.cpp b/src/bench/hostmanager.cpp index cfce965..1d80eb4 100644 --- a/src/bench/hostmanager.cpp +++ b/src/bench/hostmanager.cpp @@ -82,9 +82,9 @@ void HostManager::setLiveHubEngine(LiveHubEngine *engine) } } -void HostManager::followTreeSelection(const QString ¤tFile) +void HostManager::followTreeSelection(const LiveDocument ¤tFile) { - if (!QFileInfo(currentFile).isFile()) + if (!currentFile.isFileIn(m_engine->workspace())) return; for (int i=0; i < m_model->rowCount(); i++) { @@ -94,9 +94,9 @@ void HostManager::followTreeSelection(const QString ¤tFile) } } -void HostManager::setCurrentFile(const QString ¤tFile) +void HostManager::setCurrentFile(const LiveDocument ¤tFile) { - if (!QFileInfo(currentFile).isFile()) + if (!currentFile.isFileIn(m_engine->workspace())) return; for (int i=0; i < m_model->rowCount(); i++) { diff --git a/src/bench/hostmanager.h b/src/bench/hostmanager.h index f37b915..68f241e 100644 --- a/src/bench/hostmanager.h +++ b/src/bench/hostmanager.h @@ -34,6 +34,7 @@ #include <QListView> #include <QPointer> +class LiveDocument; class LiveHubEngine; class HostModel; class Host; @@ -54,8 +55,8 @@ signals: void openHostConfig(Host* host); public slots: - void followTreeSelection(const QString& currentFile); - void setCurrentFile(const QString& currentFile); + void followTreeSelection(const LiveDocument& currentFile); + void setCurrentFile(const LiveDocument& currentFile); void publishAll(); void refreshAll(); void probe(const QString &hostName); diff --git a/src/bench/hostmodel.cpp b/src/bench/hostmodel.cpp index a253614..a0a3b76 100644 --- a/src/bench/hostmodel.cpp +++ b/src/bench/hostmodel.cpp @@ -104,7 +104,7 @@ void HostModel::addHost(Host *host) connect(host, SIGNAL(addressChanged(QString)), this, SLOT(onHostChanged())); connect(host, SIGNAL(portChanged(int)), this, SLOT(onHostChanged())); connect(host, SIGNAL(followTreeSelectionChanged(bool)), this, SLOT(onHostChanged())); - connect(host, SIGNAL(currentFileChanged(QString)), this, SLOT(onHostChanged())); + connect(host, SIGNAL(currentFileChanged(LiveDocument)), this, SLOT(onHostChanged())); connect(host, SIGNAL(xOffsetChanged(int)), this, SLOT(onHostChanged())); connect(host, SIGNAL(yOffsetChanged(int)), this, SLOT(onHostChanged())); connect(host, SIGNAL(rotationChanged(int)), this, SLOT(onHostChanged())); diff --git a/src/bench/hostwidget.cpp b/src/bench/hostwidget.cpp index 60ec74f..5cc646d 100644 --- a/src/bench/hostwidget.cpp +++ b/src/bench/hostwidget.cpp @@ -34,6 +34,7 @@ #include "host.h" #include "livehubengine.h" +#include <QMessageBox> const int LABEL_STACK_INDEX=0; const int PROGRESS_STACK_INDEX=1; @@ -130,7 +131,7 @@ void HostWidget::setHost(Host *host) connect(host, SIGNAL(addressChanged(QString)), this, SLOT(updateIp(QString))); connect(host, SIGNAL(portChanged(int)), this, SLOT(updatePort(int))); connect(host, SIGNAL(onlineChanged(bool)), this, SLOT(updateOnlineState(bool))); - connect(host, SIGNAL(currentFileChanged(QString)), this, SLOT(updateFile(QString))); + connect(host, SIGNAL(currentFileChanged(LiveDocument)), this, SLOT(updateFile(LiveDocument))); connect(host, SIGNAL(nameChanged(QString)), this, SLOT(updateName(QString))); connect(host, SIGNAL(xOffsetChanged(int)), this, SLOT(sendXOffset(int))); connect(host, SIGNAL(yOffsetChanged(int)), this, SLOT(sendYOffset(int))); @@ -148,13 +149,14 @@ void HostWidget::setLiveHubEngine(LiveHubEngine *engine) m_publisher.setWorkspace(m_engine->workspace()); connect(m_engine.data(), SIGNAL(workspaceChanged(QString)), &m_publisher, SLOT(setWorkspace(QString))); - connect(m_engine.data(), SIGNAL(fileChanged(QString)), this, SLOT(sendDocument(QString))); + connect(m_engine.data(), SIGNAL(workspaceChanged(QString)), this, SLOT(refreshDocumentLabel())); + connect(m_engine.data(), SIGNAL(fileChanged(LiveDocument)), this, SLOT(sendDocument(LiveDocument))); connect(m_engine.data(), SIGNAL(beginPublishWorkspace()), &m_publisher, SLOT(beginBulkSend())); connect(m_engine.data(), SIGNAL(endPublishWorkspace()), &m_publisher, SLOT(endBulkSend())); connect(&m_publisher, SIGNAL(needsPublishWorkspace()), this, SLOT(publishWorkspace())); } -void HostWidget::setCurrentFile(const QString currentFile) +void HostWidget::setCurrentFile(const LiveDocument ¤tFile) { m_host->setCurrentFile(currentFile); } @@ -192,25 +194,49 @@ void HostWidget::updatePort(int port) QTimer::singleShot(0, this, SLOT(connectToServer())); } -void HostWidget::updateFile(const QString &file) +void HostWidget::updateFile(const LiveDocument &file) { setUpdateFile(file); connectAndSendFile(); } -void HostWidget::setUpdateFile(const QString &file) +void HostWidget::setUpdateFile(const LiveDocument &file) { - if (file.isEmpty()) { - m_documentLabel->setText(tr("<none>")); - m_documentLabel->setToolTip(tr("No active document. Drop one.")); - return; + QFont font(this->font()); + QPalette palette(this->palette()); + QString text; + QString toolTip; + + if (file.isNull()) { + text = tr("No active document"); + toolTip = tr("No active document. Drop one."); + font.setItalic(true); + } else { + text = file.relativeFilePath(); + + if (file.isFileIn(m_engine->workspace())) { + toolTip = file.absoluteFilePathIn(m_engine->workspace()); + } else { + // red color from http://clrs.cc + palette.setColor(QPalette::Text, QColor(0xff, 0x41, 0x36)); + toolTip = file.errorString(); + } } - QString relFile = QDir(m_engine->workspace()).relativeFilePath(file); - QFontMetrics metrics(font()); - m_documentLabel->setText(metrics.elidedText(relFile, Qt::ElideLeft, m_documentLabel->width())); - m_documentLabel->setToolTip(relFile); + QFontMetrics metrics(font); + m_documentLabel->setFont(font); + m_documentLabel->setPalette(palette); + m_documentLabel->setText(metrics.elidedText(text, Qt::ElideLeft, + m_documentLabel->width())); + m_documentLabel->setToolTip(toolTip); +} + +void HostWidget::refreshDocumentLabel() +{ + if (!m_host) + return; + setUpdateFile(m_host->currentFile()); } void HostWidget::updateOnlineState(bool online) @@ -254,7 +280,8 @@ void HostWidget::connectToServer() void HostWidget::connectAndSendFile() { connectToServer(); - m_activateId = m_publisher.activateDocument(QDir(m_engine->workspace()).relativeFilePath(m_host->currentFile())); + if (!m_host->currentFile().isNull()) + m_activateId = m_publisher.activateDocument(m_host->currentFile()); } void HostWidget::onConnected() @@ -307,12 +334,12 @@ void HostWidget::probe() void HostWidget::publishWorkspace() { connectToServer(); - connect(m_engine.data(), SIGNAL(publishFile(QString)), this, SLOT(sendDocument(QString))); + connect(m_engine.data(), SIGNAL(publishFile(LiveDocument)), this, SLOT(sendDocument(LiveDocument))); m_engine->publishWorkspace(); - disconnect(m_engine.data(), SIGNAL(publishFile(QString)), this, SLOT(sendDocument(QString))); + disconnect(m_engine.data(), SIGNAL(publishFile(LiveDocument)), this, SLOT(sendDocument(LiveDocument))); } -void HostWidget::sendDocument(const QString& document) +void HostWidget::sendDocument(const LiveDocument& document) { if (m_publisher.state() != QAbstractSocket::ConnectedState) return; @@ -421,8 +448,7 @@ void HostWidget::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); - if (m_host) - setUpdateFile(m_host->currentFile()); + refreshDocumentLabel(); } void HostWidget::showPinDialog() @@ -446,11 +472,19 @@ void HostWidget::dragEnterEvent(QDragEnterEvent *event) void HostWidget::dropEvent(QDropEvent *event) { - QUrl url(event->mimeData()->text()); - - if (url.isLocalFile()) - m_host->setCurrentFile(url.toLocalFile()); event->acceptProposedAction(); + + QUrl url(event->mimeData()->text()); + if (url.isLocalFile()) { + LiveDocument document = LiveDocument::resolve(m_engine->workspace(), url.toLocalFile()); + if (!document.isNull() && document.isFileIn(m_engine->workspace())) { + m_host->setCurrentFile(document); + } else { + QMessageBox::warning(this, tr("Not a workspace document"), + tr("The dropped document is not a file in the current workspace:<br/>%1") + .arg(url.toString())); + } + } } bool HostWidget::eventFilter(QObject *object, QEvent *event) diff --git a/src/bench/hostwidget.h b/src/bench/hostwidget.h index b5470e7..fa08f26 100644 --- a/src/bench/hostwidget.h +++ b/src/bench/hostwidget.h @@ -35,6 +35,7 @@ #include <remotepublisher.h> class Host; +class LiveDocument; class HostWidget : public QWidget { @@ -45,7 +46,7 @@ public: void setHost(Host* host); void setLiveHubEngine(LiveHubEngine* engine); - void setCurrentFile(const QString currentFile); + void setCurrentFile(const LiveDocument ¤tFile); bool followTreeSelection() const; signals: @@ -68,8 +69,9 @@ private slots: void updateName(const QString& name); void updateIp(const QString& ip); void updatePort(int port); - void updateFile(const QString& file); - void setUpdateFile(const QString& file); + void updateFile(const LiveDocument& file); + void setUpdateFile(const LiveDocument& file); + void refreshDocumentLabel(); void updateOnlineState(bool online); void updateFollowTreeSelection(bool follow); @@ -80,7 +82,7 @@ private slots: void onDisconnected(); void onConnectionError(QAbstractSocket::SocketError error); - void sendDocument(const QString &document); + void sendDocument(const LiveDocument &document); void sendXOffset(int offset); void sendYOffset(int offset); diff --git a/src/bench/main.cpp b/src/bench/main.cpp index 395d48b..ac91d64 100644 --- a/src/bench/main.cpp +++ b/src/bench/main.cpp @@ -273,7 +273,7 @@ void Application::parseArguments(const QStringList &arguments, Options *options) parser.showHelp(-1); } options->setWorkspace(fi.absolutePath()); - options->setActiveDocument(fi.absoluteFilePath()); + options->setActiveDocument(LiveDocument(fi.absoluteFilePath())); } else { qDebug() << "First argument does not ending with \".qml\". Assuming it is a workspace."; if (!fi.exists() || !fi.isDir()) { @@ -288,11 +288,12 @@ void Application::parseArguments(const QStringList &arguments, Options *options) QFileInfo fi(argument); if (argument.endsWith(".qml")) { qDebug() << "Second argument ends with \".qml\". Assuming it is a file."; - if (!fi.exists() || !fi.isFile()) { - qWarning() << "Document does not exist or is not a file: " << fi.absoluteFilePath(); + LiveDocument document = LiveDocument::resolve(options->workspace(), argument); + if (document.isNull() || !document.isFileIn(options->workspace())) { + qWarning() << document.errorString(); parser.showHelp(-1); } - options->setActiveDocument(fi.absoluteFilePath()); + options->setActiveDocument(document); } else { qWarning() << "If second argument is present it needs to be a QML document: " << fi.absoluteFilePath(); parser.showHelp(-1); @@ -399,7 +400,7 @@ void MasterApplication::applyOptions(const Options &options) qDebug() << "Ignoring attempt to set import paths after initialization."; } - if (!options.activeDocument().isEmpty()) { + if (!options.activeDocument().isNull()) { m_window->activateDocument(options.activeDocument()); } diff --git a/src/bench/mainwindow.cpp b/src/bench/mainwindow.cpp index 6e3c17b..44b0436 100644 --- a/src/bench/mainwindow.cpp +++ b/src/bench/mainwindow.cpp @@ -77,14 +77,14 @@ MainWindow::MainWindow(QWidget *parent) m_hub->setFilePublishingActive(true); m_node->setWorkspaceView(m_workspace); - connect(m_workspace, SIGNAL(pathActivated(QString)), m_hub, SLOT(setActivePath(QString))); - connect(m_workspace, SIGNAL(pathActivated(QString)), m_hostManager, SLOT(followTreeSelection(QString))); - connect(m_hub, SIGNAL(activateDocument(QString)), this, SLOT(updateWindowTitle())); - connect(m_hub, SIGNAL(activateDocument(QString)), m_node, SLOT(setActiveDocument(QString))); + connect(m_workspace, SIGNAL(pathActivated(LiveDocument)), m_hub, SLOT(setActivePath(LiveDocument))); + connect(m_workspace, SIGNAL(pathActivated(LiveDocument)), m_hostManager, SLOT(followTreeSelection(LiveDocument))); + connect(m_hub, SIGNAL(activateDocument(LiveDocument)), this, SLOT(updateWindowTitle())); + connect(m_hub, SIGNAL(activateDocument(LiveDocument)), m_node, SLOT(setActiveDocument(LiveDocument))); connect(m_node, SIGNAL(activeWindowChanged(QQuickWindow*)), this, SLOT(onActiveWindowChanged(QQuickWindow*))); connect(m_node->qmlEngine(), SIGNAL(quit()), this, SLOT(logQuitEvent())); connect(m_allHosts, SIGNAL(publishAll()), m_hostManager, SLOT(publishAll())); - connect(m_allHosts, SIGNAL(currentFileChanged(QString)), m_hostManager, SLOT(setCurrentFile(QString))); + connect(m_allHosts, SIGNAL(currentFileChanged(LiveDocument)), m_hostManager, SLOT(setCurrentFile(LiveDocument))); connect(m_allHosts, SIGNAL(refreshAll()), m_hostManager, SLOT(refreshAll())); connect(m_hostManager, SIGNAL(logWidgetAdded(QDockWidget*)), this, SLOT(onLogWidgetAdded(QDockWidget*))); connect(m_hostManager, SIGNAL(openHostConfig(Host*)), this, SLOT(openPreferences(Host*))); @@ -240,13 +240,15 @@ void MainWindow::init() updateRecentFolder(); - //Only set the workspace if we didn't already set it by command line - if (m_node->activeDocument().isEmpty()) { - if (s.contains("activeDocument")) { - activateDocument(s.value("activeDocument").toString()); - } else { + //Only set the document if we didn't already set it by command line + if (m_node->activeDocument().isNull()) { + LiveDocument last; + if (s.contains("activeDocument")) + last = LiveDocument::resolve(m_workspacePath, s.value("activeDocument").toString()); + if (!last.isNull()) + activateDocument(last); + else m_workspace->activateRootPath(); - } } resetImportPaths(); @@ -263,7 +265,8 @@ void MainWindow::writeSettings() s.setValue("geometry", saveGeometry()); s.setValue("windowState", saveState()); s.setValue("workspace", m_workspacePath); - s.setValue("activeDocument", m_node->activeDocument().toLocalFile()); + if (!m_node->activeDocument().isNull()) + s.setValue("activeDocument", m_node->activeDocument().relativeFilePath()); s.beginWriteArray("recentFolder"); for (int i = 0; i < m_recentFolder.count(); i++) { @@ -300,7 +303,7 @@ void MainWindow::setupToolBar() m_toolBar->addAction(m_resizeFit); } -void MainWindow::activateDocument(const QString path) +void MainWindow::activateDocument(const LiveDocument &path) { m_workspace->activateDocument(path); } @@ -395,11 +398,11 @@ void MainWindow::logQuitEvent() void MainWindow::updateWindowTitle() { setWindowFilePath(QString()); - if (m_hub->activePath().isEmpty()) { + if (m_hub->activePath().isNull()) { setWindowTitle(QApplication::applicationName()); } else { setWindowTitle(QString()); - setWindowFilePath(m_hub->activePath()); + setWindowFilePath(m_hub->activePath().absoluteFilePathIn(m_workspacePath)); } } diff --git a/src/bench/mainwindow.h b/src/bench/mainwindow.h index 87e65a8..4a7e8f1 100644 --- a/src/bench/mainwindow.h +++ b/src/bench/mainwindow.h @@ -39,6 +39,7 @@ class BenchQuickView; class WorkspaceView; class LogView; +class LiveDocument; class LiveRuntime; class LiveHubEngine; class BenchLiveNodeEngine; @@ -57,7 +58,7 @@ class MainWindow : public QMainWindow public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); - void activateDocument(const QString path); + void activateDocument(const LiveDocument &path); void setWorkspace(const QString& path, bool activateRootPath = true); void setPluginPath(const QString& path); void setImportPaths(const QStringList& pathList); diff --git a/src/bench/options.cpp b/src/bench/options.cpp index 7fa8386..5baedc2 100644 --- a/src/bench/options.cpp +++ b/src/bench/options.cpp @@ -85,12 +85,12 @@ void Options::setPing(bool ping) m_ping = ping; } -QString Options::activeDocument() const +LiveDocument Options::activeDocument() const { return m_activeDocument; } -void Options::setActiveDocument(const QString &activeDocument) +void Options::setActiveDocument(const LiveDocument &activeDocument) { m_activeDocument = activeDocument; } diff --git a/src/bench/options.h b/src/bench/options.h index 2760059..e7c84bd 100644 --- a/src/bench/options.h +++ b/src/bench/options.h @@ -31,6 +31,8 @@ #pragma once +#include "livedocument.h" + #include <QtCore> class Options : public QObject @@ -58,8 +60,8 @@ public: bool ping() const; void setPing(bool ping); - QString activeDocument() const; - void setActiveDocument(const QString &activeDocument); + LiveDocument activeDocument() const; + void setActiveDocument(const LiveDocument &activeDocument); QString workspace() const; void setWorkspace(const QString &workspace); @@ -88,7 +90,7 @@ private: bool m_noRemote; bool m_remoteOnly; bool m_ping; - QString m_activeDocument; + LiveDocument m_activeDocument; QString m_workspace; QString m_pluginPath; QStringList m_importPaths; diff --git a/src/livedocument.cpp b/src/livedocument.cpp new file mode 100644 index 0000000..d4347cf --- /dev/null +++ b/src/livedocument.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QmlLive tool. +** +** $QT_BEGIN_LICENSE:GPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite 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$ +** +** SPDX-License-Identifier: GPL-3.0 +** +****************************************************************************/ + +#include "livedocument.h" + +#include <QDebug> + +/*! + * \class LiveDocument + * \brief Encapsulates a relative path to a workspace document + * \inmodule qmllive + */ + +/*! + * Constructs a null instance. + * + * \sa isNull(), errorString() + */ +LiveDocument::LiveDocument() +{ + m_errorString = tr("Internal error: A null LiveDocument passed"); +} + +/*! + * Constructs instance for the given \a relativeFilePath. + * + * The \a relativeFilePath MUST NOT be an empty string, it MUST be a relative + * path, and when resolved relatively to a directory it MUST NOT resolve to a + * path outside of the directory. + */ +LiveDocument::LiveDocument(const QString &relativeFilePath) +{ + LIVE_ASSERT(!relativeFilePath.isEmpty(), return); + LIVE_ASSERT(QDir::isRelativePath(relativeFilePath), return); + LIVE_ASSERT(!QDir::cleanPath(relativeFilePath).startsWith(QLatin1String("../")), return); + + m_relativeFilePath = relativeFilePath; +} + +/*! + * \fn bool LiveDocument::isNull() const + * + * Returns true if this is a null instance. + * + * A null instance has been either contructed with the default constructor or + * the resolve() call failed. + * + * \sa errorString() + */ + +/*! + * \fn QString LiveDocument::errorString() const + * + * When called just after resolve(), existsIn() or isFileIn() failed, returns a + * descriptive message suitable for displaying in user interface. When called in + * other context, the result is undefined. + */ + +/*! + * Returns \c true if this document exists in the given \a workspace directory. + * + * \sa errorString() + */ +bool LiveDocument::existsIn(const QDir &workspace) const +{ + LIVE_ASSERT(!isNull(), return false); + + bool exists = QFileInfo(workspace, m_relativeFilePath).exists(); + if (!exists) { + m_errorString = tr("Document '%1' does not exist in workspace '%2'") + .arg(m_relativeFilePath) + .arg(workspace.path()); + } + return exists; +} + +/*! + * Returns \c true if this document exists as a regular file (or a symbolic link + * to a regular file) in the given \a workspace directory. + * + * Symbolic links resolution applies. + * + * \sa errorString() + */ +bool LiveDocument::isFileIn(const QDir &workspace) const +{ + LIVE_ASSERT(!isNull(), return false); + + if (!existsIn(workspace)) + return false; + + bool isFile = QFileInfo(workspace, m_relativeFilePath).isFile(); + if (!isFile) { + m_errorString = tr("Document '%1' is a non-regular file in workspace '%2'") + .arg(m_relativeFilePath) + .arg(workspace.path()); + } + return isFile; +} + +/*! + * Returns the relative file path including the file name. + */ +QString LiveDocument::relativeFilePath() const +{ + LIVE_ASSERT(!isNull(), return QString()); + + return m_relativeFilePath; +} + +/*! + * Returns the absolute file path within a \a workspace, including the file name. + */ +QString LiveDocument::absoluteFilePathIn(const QDir &workspace) const +{ + LIVE_ASSERT(!isNull(), return QString()); + + return QDir::cleanPath(workspace.absoluteFilePath(m_relativeFilePath)); +} + +/*! + * Constructs a non-null instance unless the \a filePath resolves outside of the + * \a workspace directory. + * + * \a filePath may be an absolute or relative file path to a file which is NOT + * required to exist. + * + * \sa isNull(), errorString() + */ +LiveDocument LiveDocument::resolve(const QDir &workspace, const QString &filePath) +{ + LiveDocument retv; + + if (filePath.isEmpty()) { + qWarning() << "filePath is an empty string"; + retv.m_errorString = tr("Not a valid file path: ''"); + return retv; + } + + QString relativeFilePath = workspace.relativeFilePath(filePath); + QString cleanPath = QDir::cleanPath(relativeFilePath); + if (cleanPath.isEmpty()) { + retv.m_relativeFilePath = QStringLiteral("."); + } else if (!cleanPath.startsWith(QLatin1String("../"))) { + retv.m_relativeFilePath = relativeFilePath; + } else { + retv.m_errorString = tr("Document path '%1' is outside the workspace directory '%2'") + .arg(filePath).arg(workspace.path()); + } + + return retv; +} + +/*! + * Allows to print LiveDocument \a document via debug stream \a dbg. + */ +QDebug operator<<(QDebug dbg, const LiveDocument &document) +{ + if (document.isNull()) + dbg << QStringLiteral("<null>"); + else + dbg << document.relativeFilePath(); + + return dbg; +} diff --git a/src/livedocument.h b/src/livedocument.h new file mode 100644 index 0000000..6aa9b0c --- /dev/null +++ b/src/livedocument.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QmlLive tool. +** +** $QT_BEGIN_LICENSE:GPL-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite 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$ +** +** SPDX-License-Identifier: GPL-3.0 +** +****************************************************************************/ + +#pragma once + +#include <QtCore> + +#include "qmllive_global.h" + +class QMLLIVESHARED_EXPORT LiveDocument +{ + Q_DECLARE_TR_FUNCTIONS(LiveDocument) + +public: + LiveDocument(); + explicit LiveDocument(const QString &relativeFilePath); + + bool isNull() const { return m_relativeFilePath.isEmpty(); } + QString errorString() const { return m_errorString; } + + bool existsIn(const QDir &workspace) const; + bool isFileIn(const QDir &workspace) const; + + QString relativeFilePath() const; + QString absoluteFilePathIn(const QDir &workspace) const; + + static LiveDocument resolve(const QDir &workspace, const QString &filePath); + + friend inline bool operator==(const LiveDocument &d1, const LiveDocument &d2) + { return d1.m_relativeFilePath == d2.m_relativeFilePath; } + friend inline bool operator!=(const LiveDocument &d1, const LiveDocument &d2) + { return !(d1 == d2); } + +private: + QString m_relativeFilePath; + mutable QString m_errorString; +}; + +QDebug QMLLIVESHARED_EXPORT operator<<(QDebug dbg, const LiveDocument &document); diff --git a/src/livehubengine.cpp b/src/livehubengine.cpp index 6db5520..b922a58 100644 --- a/src/livehubengine.cpp +++ b/src/livehubengine.cpp @@ -78,18 +78,18 @@ QString LiveHubEngine::workspace() const /*! * Sets the active document path to \a path. - * Emits activateDocument() with the workspace relative path. + * Emits activateDocument() with this path. */ -void LiveHubEngine::setActivePath(const QString &path) +void LiveHubEngine::setActivePath(const LiveDocument &path) { m_activePath = path; - emit activateDocument(m_watcher->relativeFilePath(path)); + emit activateDocument(m_activePath); } /*! * Returns the active Document */ -QString LiveHubEngine::activePath() const +LiveDocument LiveHubEngine::activePath() const { return m_activePath; } @@ -106,7 +106,7 @@ void LiveHubEngine::directoriesChanged(const QStringList &changes) } } - emit activateDocument(m_watcher->relativeFilePath(m_activePath)); + emit activateDocument(m_activePath); } /*! @@ -132,10 +132,11 @@ void LiveHubEngine::publishDirectory(const QString& dirPath, bool fileChange) if (!m_filePublishingActive) { return; } QDirIterator iter(dirPath, QDir::Files); while (iter.hasNext()) { + LiveDocument document = LiveDocument::resolve(m_watcher->directory(), iter.next()); if (fileChange) - emit fileChanged(iter.next()); + emit fileChanged(document); else - emit publishFile(iter.next()); + emit publishFile(document); } } @@ -162,21 +163,21 @@ void LiveHubEngine::setFilePublishingActive(bool on) */ /*! - * \fn void LiveHubEngine::publishFile(const QString& document) + * \fn void LiveHubEngine::publishFile(const LiveDocument& document) * * This signal is emitted during publishing the directory to inform a connected * node to publish the \a document to the remote device form the hub */ /*! - * \fn void LiveHubEngine::fileChanged(const QString& document) + * \fn void LiveHubEngine::fileChanged(const LiveDocument& document) * * This signal is emitted during publishing a directory to inform a connected * node that \a document has changed on the hub. */ /*! - * \fn void LiveHubEngine::activateDocument(const QString& document) + * \fn void LiveHubEngine::activateDocument(const LiveDocument& document) * The signal is emitted when the document identified by \a document has been activated */ diff --git a/src/livehubengine.h b/src/livehubengine.h index 362c7db..266e07e 100644 --- a/src/livehubengine.h +++ b/src/livehubengine.h @@ -33,6 +33,7 @@ #include <QtCore> +#include "livedocument.h" #include "qmllive_global.h" class Watcher; @@ -46,17 +47,17 @@ public: void setWorkspace(const QString& path); QString workspace() const; - QString activePath() const; + LiveDocument activePath() const; public Q_SLOTS: - void setActivePath(const QString& path); + void setActivePath(const LiveDocument& path); void setFilePublishingActive(bool on); void publishWorkspace(); Q_SIGNALS: void beginPublishWorkspace(); void endPublishWorkspace(); - void publishFile(const QString& document); - void fileChanged(const QString& document); - void activateDocument(const QString& document); + void publishFile(const LiveDocument& document); + void fileChanged(const LiveDocument& document); + void activateDocument(const LiveDocument& document); void workspaceChanged(const QString& workspace); private Q_SLOTS: void directoriesChanged(const QStringList& changes); @@ -65,6 +66,6 @@ private: private: Watcher *m_watcher; bool m_filePublishingActive; - QString m_activePath; + LiveDocument m_activePath; }; diff --git a/src/livenodeengine.cpp b/src/livenodeengine.cpp index 1fa9e4c..594a9c8 100644 --- a/src/livenodeengine.cpp +++ b/src/livenodeengine.cpp @@ -119,12 +119,12 @@ public: QDir overlay() const { return m_overlay; } - QString reserve(const QString &document) + QString reserve(const LiveDocument &document) { QWriteLocker locker(&m_lock); - QString overlayingPath = m_overlay.absoluteFilePath(document); - m_mappings.insert(QUrl::fromLocalFile(m_base.absoluteFilePath(document)), + QString overlayingPath = document.absoluteFilePathIn(m_overlay); + m_mappings.insert(QUrl::fromLocalFile(document.absoluteFilePathIn(m_base)), QUrl::fromLocalFile(overlayingPath)); return overlayingPath; } @@ -285,14 +285,14 @@ int LiveNodeEngine::rotation() const } /*! - * Loads the given \a url onto the QML view. Clears any caches. + * Loads the given \a document onto the QML view. Clears any caches. */ -void LiveNodeEngine::loadDocument(const QUrl& url) +void LiveNodeEngine::loadDocument(const LiveDocument& document) { - DEBUG << "LiveNodeEngine::loadDocument: " << url; - m_activeFile = url; + DEBUG << "LiveNodeEngine::loadDocument: " << document; + m_activeFile = document; - if (!m_activeFile.isEmpty()) + if (!m_activeFile.isNull()) reloadDocument(); } @@ -362,7 +362,8 @@ void LiveNodeEngine::reloadDocument() emit clearLog(); - const QUrl url = queryDocumentViewer(m_activeFile); + const QUrl originalUrl = QUrl::fromLocalFile(m_activeFile.absoluteFilePathIn(m_workspace)); + const QUrl url = queryDocumentViewer(originalUrl); QScopedPointer<QQmlComponent> component(new QQmlComponent(m_qmlEngine, url)); m_object = component->create(); @@ -371,7 +372,7 @@ void LiveNodeEngine::reloadDocument() if (component->isLoading()) { qCritical() << "Component did not load synchronously." << "URL:" << url.toString() - << "(original URL:" << m_activeFile.toString() << ")"; + << "(original URL:" << originalUrl.toString() << ")"; } else { emit logErrors(component->errors()); delete m_object; @@ -444,7 +445,7 @@ void LiveNodeEngine::reloadDocument() * * The behavior of this function is controlled by WorkspaceOptions passed to setWorkspace(). */ -void LiveNodeEngine::updateDocument(const QString &document, const QByteArray &content) +void LiveNodeEngine::updateDocument(const LiveDocument &document, const QByteArray &content) { if (!(m_workspaceOptions & AllowUpdates)) { return; @@ -452,7 +453,7 @@ void LiveNodeEngine::updateDocument(const QString &document, const QByteArray &c QString filePath = (m_workspaceOptions & UpdatesAsOverlay) ? m_overlayUrlInterceptor->reserve(document) - : m_workspace.absoluteFilePath(document); + : document.absoluteFilePathIn(m_workspace); QString dirPath = QFileInfo(filePath).absoluteDir().absolutePath(); QDir().mkpath(dirPath); @@ -464,7 +465,7 @@ void LiveNodeEngine::updateDocument(const QString &document, const QByteArray &c file.write(content); file.close(); - if (!m_activeFile.isEmpty()) + if (!m_activeFile.isNull()) delayReload(); } @@ -495,14 +496,9 @@ QUrl LiveNodeEngine::queryDocumentViewer(const QUrl& url) /*! * Sets the document \a document to be shown */ -void LiveNodeEngine::setActiveDocument(const QString &document) +void LiveNodeEngine::setActiveDocument(const LiveDocument &document) { - QUrl url; - if (!document.isEmpty()) { - url = QUrl::fromLocalFile(m_workspace.absoluteFilePath(document)); - } - - loadDocument(url); + loadDocument(document); emit activateDocument(document); } @@ -597,9 +593,9 @@ QString LiveNodeEngine::pluginPath() const } /*! - * Returns the current active document url. + * Returns the current active document. */ -QUrl LiveNodeEngine::activeDocument() const +LiveDocument LiveNodeEngine::activeDocument() const { return m_activeFile; } @@ -650,7 +646,7 @@ void LiveNodeEngine::onSizeChanged() } /*! - * \fn void LiveNodeEngine::activateDocument(const QString& document) + * \fn void LiveNodeEngine::activateDocument(const LiveDocument& document) * * The document \a document was activated */ diff --git a/src/livenodeengine.h b/src/livenodeengine.h index df030e1..2b16489 100644 --- a/src/livenodeengine.h +++ b/src/livenodeengine.h @@ -35,6 +35,7 @@ #include <QtQuick> #include "contentadapterinterface.h" +#include "livedocument.h" #include "qmllive_global.h" class LiveRuntime; @@ -79,7 +80,7 @@ public: void setPluginPath(const QString& path); QString pluginPath() const; - QUrl activeDocument() const; + LiveDocument activeDocument() const; ContentAdapterInterface *activePlugin() const; QQuickWindow *activeWindow() const; @@ -87,14 +88,14 @@ public Q_SLOTS: void setXOffset(int offset); void setYOffset(int offset); void setRotation(int rotation); - void setActiveDocument(const QString& document); - void loadDocument(const QUrl& url); + void setActiveDocument(const LiveDocument& document); + void loadDocument(const LiveDocument& document); void delayReload(); virtual void reloadDocument(); - void updateDocument(const QString &document, const QByteArray &content); + void updateDocument(const LiveDocument &document, const QByteArray &content); Q_SIGNALS: - void activateDocument(const QString& document); + void activateDocument(const LiveDocument& document); void clearLog(); void logIgnoreMessages(bool on); void documentLoaded(); @@ -105,7 +106,7 @@ Q_SIGNALS: protected: virtual void initPlugins(); QList<ContentAdapterInterface*> m_plugins; - QUrl m_activeFile; + LiveDocument m_activeFile; LiveRuntime *m_runtime; private Q_SLOTS: diff --git a/src/qmllive_global.h b/src/qmllive_global.h index ce64734..f78924a 100644 --- a/src/qmllive_global.h +++ b/src/qmllive_global.h @@ -40,4 +40,20 @@ # define QMLLIVESHARED_EXPORT Q_DECL_IMPORT #endif +#if defined(QMLLIVE_VERSION) +# define QMLLIVE_SOURCE +#endif + +#if defined(QMLLIVE_SOURCE) +# if !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS) +# define LIVE_ASSERT(cond, action) Q_ASSERT(cond) +# else +# define LIVE_ASSERT(cond, action) if (cond) {} else { \ + QMessageLogger(__FILE__, __LINE__, Q_FUNC_INFO).critical() \ + << "Assertion \"" #cond "\" failed"; \ + action; \ + } do {} while (0) +# endif +#endif + #endif // QMLLIVELIB_GLOBAL_H diff --git a/src/remotepublisher.cpp b/src/remotepublisher.cpp index c1e1982..08908a8 100644 --- a/src/remotepublisher.cpp +++ b/src/remotepublisher.cpp @@ -31,6 +31,7 @@ #include "remotepublisher.h" #include "ipc/ipcclient.h" +#include "livedocument.h" #include "livehubengine.h" #ifdef QMLLIVE_DEBUG @@ -91,9 +92,9 @@ void RemotePublisher::registerHub(LiveHubEngine *hub) disconnect(m_hub); } m_hub = hub; - connect(hub, SIGNAL(activateDocument(QString)), this, SLOT(activateDocument(QString))); - connect(hub, SIGNAL(fileChanged(QString)), this, SLOT(sendDocument(QString))); - connect(hub, SIGNAL(publishFile(QString)), this, SLOT(sendDocument(QString))); + connect(hub, SIGNAL(activateDocument(LiveDocument)), this, SLOT(activateDocument(LiveDocument))); + connect(hub, SIGNAL(fileChanged(LiveDocument)), this, SLOT(sendDocument(LiveDocument))); + connect(hub, SIGNAL(publishFile(LiveDocument)), this, SLOT(sendDocument(LiveDocument))); connect(this, SIGNAL(needsPublishWorkspace()), hub, SLOT(publishWorkspace())); connect(hub, SIGNAL(beginPublishWorkspace()), this, SLOT(beginBulkSend())); connect(hub, SIGNAL(endPublishWorkspace()), this, SLOT(endBulkSend())); @@ -137,12 +138,12 @@ void RemotePublisher::disconnectFromServer() * Send "activateDocument(QString)" to IPC-server on activate document. * \a document defines the Document which should be activated */ -QUuid RemotePublisher::activateDocument(const QString &document) +QUuid RemotePublisher::activateDocument(const LiveDocument &document) { DEBUG << "RemotePublisher::activateDocument" << document; QByteArray bytes; QDataStream out(&bytes, QIODevice::WriteOnly); - out << document; + out << document.relativeFilePath(); return m_ipc->send("activateDocument(QString)", bytes); } @@ -165,10 +166,10 @@ QUuid RemotePublisher::endBulkSend() } /*! - * Sends "sendDocument(QString)" using \a document as path to the document to be + * Sends "sendDocument(QString)" using \a document to identify the document to be *send to via IPC. */ -QUuid RemotePublisher::sendDocument(const QString& document) +QUuid RemotePublisher::sendDocument(const LiveDocument& document) { DEBUG << "RemotePublisher::sendDocument" << document; return sendWholeDocument(document); @@ -224,10 +225,10 @@ QUuid RemotePublisher::setRotation(int rotation) /*! Sends the \e sendWholeDocument with \a document as argument via IPC */ -QUuid RemotePublisher::sendWholeDocument(const QString& document) +QUuid RemotePublisher::sendWholeDocument(const LiveDocument& document) { DEBUG << "RemotePublisher::sendWholeDocument" << document; - QFile file(document); + QFile file(document.absoluteFilePathIn(m_workspace)); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "ERROR: can't open file: " << document; return QUuid(); @@ -236,7 +237,7 @@ QUuid RemotePublisher::sendWholeDocument(const QString& document) QByteArray bytes; QDataStream out(&bytes, QIODevice::WriteOnly); - out << m_workspace.relativeFilePath(document); + out << document.relativeFilePath(); out << data; return m_ipc->send("sendDocument(QString,QByteArray)", bytes); } diff --git a/src/remotepublisher.h b/src/remotepublisher.h index 8d69f9b..9df2601 100644 --- a/src/remotepublisher.h +++ b/src/remotepublisher.h @@ -36,6 +36,7 @@ #include "qmllive_global.h" +class LiveDocument; class LiveHubEngine; class IpcClient; @@ -64,10 +65,10 @@ Q_SIGNALS: public Q_SLOTS: void setWorkspace(const QString &path); void disconnectFromServer(); - QUuid activateDocument(const QString& document); + QUuid activateDocument(const LiveDocument& document); QUuid beginBulkSend(); QUuid endBulkSend(); - QUuid sendDocument(const QString& document); + QUuid sendDocument(const LiveDocument& document); QUuid checkPin(const QString& pin); QUuid setXOffset(int offset); QUuid setYOffset(int offset); @@ -75,7 +76,7 @@ public Q_SLOTS: private Q_SLOTS: void handleCall(const QString &method, const QByteArray &content); - QUuid sendWholeDocument(const QString &document); + QUuid sendWholeDocument(const LiveDocument &document); void onSentSuccessfully(const QUuid& uuid); void onSendingError(const QUuid& uuid, QAbstractSocket::SocketError socketError); diff --git a/src/remotereceiver.cpp b/src/remotereceiver.cpp index ebfa989..d434a5b 100644 --- a/src/remotereceiver.cpp +++ b/src/remotereceiver.cpp @@ -227,13 +227,13 @@ void RemoteReceiver::handleCall(const QString &method, const QByteArray &content QDataStream in(content); in >> document; in >> data; - emit updateDocument(document, data); + emit updateDocument(LiveDocument(document), data); } else if (method == "activateDocument(QString)") { QString document; QDataStream in(content); in >> document; qDebug() << "\tactivate document: " << document; - emit activateDocument(document); + emit activateDocument(LiveDocument(document)); } else if (method == "ping()") { if (m_client) m_client->send("pong()", QByteArray()); @@ -249,8 +249,8 @@ void RemoteReceiver::registerNode(LiveNodeEngine *node) m_node = node; connect(m_node, SIGNAL(logErrors(QList<QQmlError>)), this, SLOT(appendToLog(QList<QQmlError>))); connect(m_node, SIGNAL(clearLog()), this, SLOT(clearLog())); - connect(this, SIGNAL(activateDocument(QString)), m_node, SLOT(setActiveDocument(QString))); - connect(this, SIGNAL(updateDocument(QString,QByteArray)), m_node, SLOT(updateDocument(QString,QByteArray))); + connect(this, SIGNAL(activateDocument(LiveDocument)), m_node, SLOT(setActiveDocument(LiveDocument))); + connect(this, SIGNAL(updateDocument(LiveDocument,QByteArray)), m_node, SLOT(updateDocument(LiveDocument,QByteArray))); connect(this, SIGNAL(xOffsetChanged(int)), m_node, SLOT(setXOffset(int))); connect(this, SIGNAL(yOffsetChanged(int)), m_node, SLOT(setYOffset(int))); connect(this, SIGNAL(rotationChanged(int)), m_node, SLOT(setRotation(int))); @@ -341,7 +341,7 @@ void RemoteReceiver::clearLog() } /*! - * \fn void RemoteReceiver::activateDocument(const QString& document) + * \fn void RemoteReceiver::activateDocument(const LiveDocument& document) * * This signal is emitted when the remote active document \a document has changed */ @@ -410,7 +410,7 @@ void RemoteReceiver::clearLog() */ /*! - * \fn void RemoteReceiver::updateDocument(const QString &document, const QByteArray &content) + * \fn void RemoteReceiver::updateDocument(const LiveDocument &document, const QByteArray &content) * * This signal is emitted to notify that a \a document has changed its \a content */ diff --git a/src/remotereceiver.h b/src/remotereceiver.h index aba3eed..6877f50 100644 --- a/src/remotereceiver.h +++ b/src/remotereceiver.h @@ -38,6 +38,7 @@ #include "qmllive_global.h" +class LiveDocument; class LiveNodeEngine; class IpcServer; class IpcClient; @@ -80,7 +81,7 @@ public: void setMaxConnections(int max); Q_SIGNALS: - void activateDocument(const QString& document); + void activateDocument(const LiveDocument& document); void reload(); void clientConnected(const QHostAddress& address); void clientDisconnected(const QHostAddress& address); @@ -91,7 +92,7 @@ Q_SIGNALS: void beginBulkUpdate(); void endBulkUpdate(); void updateDocumentsOnConnectFinished(bool ok); - void updateDocument(const QString &document, const QByteArray &content); + void updateDocument(const LiveDocument &document, const QByteArray &content); private Q_SLOTS: void handleCall(const QString& method, const QByteArray& content); diff --git a/src/runtime/main.cpp b/src/runtime/main.cpp index e741768..3058e24 100644 --- a/src/runtime/main.cpp +++ b/src/runtime/main.cpp @@ -189,12 +189,13 @@ int main(int argc, char** argv) engine.setFallbackView(&fallbackView); engine.setWorkspace(options.workspace, workspaceOptions); engine.setPluginPath(options.pluginPath); - engine.loadDocument(QUrl("qrc:/qml/qmlsplash/splash-qt5.qml")); RemoteReceiver receiver; receiver.registerNode(&engine); if (!receiver.listen(options.ipcPort, connectionOptions)) return EXIT_FAILURE; + fallbackView.setSource(QUrl("qrc:/qml/qmlsplash/splash-qt5.qml")); + int ret = app.exec(); return ret; diff --git a/src/src.pri b/src/src.pri index 8a629e6..1af18e4 100644 --- a/src/src.pri +++ b/src/src.pri @@ -8,6 +8,7 @@ DEFINES += NO_LIBRSYNC SOURCES += \ $$PWD/watcher.cpp \ + $$PWD/livedocument.cpp \ $$PWD/livehubengine.cpp \ $$PWD/livenodeengine.cpp \ $$PWD/qmlhelper.cpp \ @@ -22,6 +23,7 @@ SOURCES += \ $$PWD/fontadapter.cpp public_headers += \ + $$PWD/livedocument.h \ $$PWD/livehubengine.h \ $$PWD/livenodeengine.h \ $$PWD/qmlhelper.h \ diff --git a/src/watcher.cpp b/src/watcher.cpp index c97fa8f..37f625f 100644 --- a/src/watcher.cpp +++ b/src/watcher.cpp @@ -105,15 +105,6 @@ void Watcher::addDirectoriesRecursively(const QString &path) } -/*! - Returns the given path relative to the watcher's Directory - /sa setDirectory, directory() - */ -QString Watcher::relativeFilePath(const QString &path) -{ - return m_rootDir.relativeFilePath(path); -} - void Watcher::recordChange(const QString &path) { // qDebug() << "Watcher::recordChange: " << path; diff --git a/src/watcher.h b/src/watcher.h index 67f39ae..a17e28a 100644 --- a/src/watcher.h +++ b/src/watcher.h @@ -40,7 +40,6 @@ public: explicit Watcher(QObject *parent = 0); void setDirectory(const QString& path); QString directory() const; - QString relativeFilePath(const QString& path); private Q_SLOTS: void recordChange(const QString &path); void notifyChanges(); diff --git a/src/widgets/workspaceview.cpp b/src/widgets/workspaceview.cpp index d6523ab..10b9f2b 100644 --- a/src/widgets/workspaceview.cpp +++ b/src/widgets/workspaceview.cpp @@ -85,17 +85,17 @@ void WorkspaceView::setRootPath(const QString &dirPath) /*! * Activates the document by the given \a path */ -void WorkspaceView::activateDocument(const QString &path) +void WorkspaceView::activateDocument(const LiveDocument &path) { //qDebug() << "WorkspaceView::activateDocument" << path; - QModelIndex index = m_model->index(path); + QModelIndex index = m_model->index(path.absoluteFilePathIn(rootPath())); selectIndex(index); } void WorkspaceView::activateRootPath() { selectIndex(m_rootIndex); - emit pathActivated(m_model->rootPath()); + emit pathActivated(LiveDocument(QStringLiteral("."))); } void WorkspaceView::goUp() @@ -110,7 +110,7 @@ void WorkspaceView::goUp() /*! * Returns the active, selected document. */ -QString WorkspaceView::activeDocument() const +LiveDocument WorkspaceView::activeDocument() const { return m_currentDocument; } @@ -140,8 +140,8 @@ void WorkspaceView::indexActivated(const QModelIndex &index) QString path = m_model->filePath(index); - m_currentDocument = path; - emit pathActivated(path); + m_currentDocument = LiveDocument::resolve(m_model->rootDirectory(), path); + emit pathActivated(m_currentDocument); } void WorkspaceView::selectIndex(const QModelIndex &index) diff --git a/src/widgets/workspaceview.h b/src/widgets/workspaceview.h index 4e1c9c3..6058b04 100644 --- a/src/widgets/workspaceview.h +++ b/src/widgets/workspaceview.h @@ -31,6 +31,8 @@ #pragma once +#include "livedocument.h" + #include <QtGui> #include <QtWidgets> @@ -41,19 +43,19 @@ class WorkspaceView : public QWidget Q_OBJECT public: explicit WorkspaceView(QWidget *parent = 0); - QString activeDocument() const; + LiveDocument activeDocument() const; QString rootPath() const; void setDirectoriesSelectable(bool enabled); bool directoriesSelectable() const; public Q_SLOTS: void setRootPath(const QString& dirPath); - void activateDocument(const QString& path); + void activateDocument(const LiveDocument& path); void activateRootPath(); void goUp(); Q_SIGNALS: - void pathActivated(const QString& path); + void pathActivated(const LiveDocument& path); private Q_SLOTS: void indexActivated(const QModelIndex& index); @@ -63,5 +65,5 @@ private: QTreeView *m_view; FileSystemModel *m_model; QModelIndex m_rootIndex; - QString m_currentDocument; + LiveDocument m_currentDocument; }; |