1
0
mirror of https://gitlab.com/kelteseth/ScreenPlay.git synced 2024-11-22 10:42:29 +01:00

Add live reloading to Widgets

This commit is contained in:
Elias Steurer 2021-05-14 13:11:12 +02:00
parent ebfe616460
commit a78a48bb2e
4 changed files with 91 additions and 44 deletions

View File

@ -22,20 +22,17 @@ Item {
var newObject = Qt.createQmlObject(obj2.toString(), root, "err")
newObject.destroy(10000)
}
}
// Replace wallpaper with QML Scene
function onReloadQML(oldType) {
Action {
shortcut: "F5"
onTriggered: {
loader.sourceComponent = undefined
loader.source = ""
Widget.clearComponentCache()
if (Widget.type === "qmlWidget") {
loader.source = Qt.resolvedUrl(Widget.sourcePath)
} else if (Widget.type === "htmlWidget") {
loader.sourceComponent = webViewComponent
}
loader.source = Qt.resolvedUrl(Widget.projectSourceFileAbsolute)
}
}
OpacityAnimator {

View File

@ -16,8 +16,8 @@ int main(int argc, char* argv[])
// If we start with only one argument (path, appID, type),
// it means we want to test a single widget
if (argumentList.length() == 1) {
//WidgetWindow spwmw("test", "appid", "qmlWidget", { 0, 0 });
WidgetWindow spwmw("C:/Program Files (x86)/Steam/steamapps/workshop/content/672870/2136442401", "appid", "qmlWidget", { 0, 0 });
//WidgetWindow spwmw("test", "appid", "qmlWidget", { 0, 0 }, true);
WidgetWindow spwmw("C:/Program Files (x86)/Steam/steamapps/workshop/content/672870/2136442401", "appid", "qmlWidget", { 0, 0 }, true);
return app.exec();
}

View File

@ -21,11 +21,13 @@ WidgetWindow::WidgetWindow(
const QString& projectPath,
const QString& appID,
const QString& type,
const QPoint& position)
const QPoint& position,
const bool debugMode)
: QObject(nullptr)
, m_appID { appID }
, m_position { position }
, m_sdk { std::make_unique<ScreenPlaySDK>(appID, type) }
, m_debugMode { debugMode }
{
qRegisterMetaType<ScreenPlay::InstalledType::InstalledType>();
@ -56,14 +58,15 @@ WidgetWindow::WidgetWindow(
setProjectSourceFileAbsolute({ "qrc:/test.qml" });
setType(ScreenPlay::InstalledType::InstalledType::QMLWidget);
} else {
auto projectOpt = ScreenPlayUtil::openJsonFileToObject(projectPath + "/project.json");
setProjectPath(projectPath);
auto projectOpt = ScreenPlayUtil::openJsonFileToObject(m_projectPath + "/project.json");
if (!projectOpt.has_value()) {
qWarning() << "Unable to parse project file!";
}
m_project = projectOpt.value();
setProjectSourceFile(m_project.value("file").toString());
setProjectSourceFileAbsolute(QUrl::fromLocalFile(projectPath + "/" + projectSourceFile()));
setProjectSourceFileAbsolute(QUrl::fromLocalFile(m_projectPath + "/" + projectSourceFile()));
if (auto typeOpt = ScreenPlayUtil::getInstalledTypeFromString(m_project.value("type").toString())) {
setType(typeOpt.value());
@ -79,26 +82,30 @@ WidgetWindow::WidgetWindow(
m_window.show();
// Do not trigger position changed save reuqest on startup
sdk()->start();
QTimer::singleShot(1000, this, [=, this]() {
// We limit ourself to only update the position every 500ms!
auto sendPositionUpdate = [this]() {
m_positionMessageLimiter.stop();
if (!m_sdk->isConnected())
return;
if (!m_debugMode) {
sdk()->start();
QTimer::singleShot(1000, this, [=, this]() {
// We limit ourself to only update the position every 500ms!
auto sendPositionUpdate = [this]() {
m_positionMessageLimiter.stop();
if (!m_sdk->isConnected())
return;
QJsonObject obj;
obj.insert("messageType", "positionUpdate");
obj.insert("positionX", m_window.x());
obj.insert("positionY", m_window.y());
m_sdk->sendMessage(obj);
};
m_positionMessageLimiter.setInterval(500);
QJsonObject obj;
obj.insert("messageType", "positionUpdate");
obj.insert("positionX", m_window.x());
obj.insert("positionY", m_window.y());
m_sdk->sendMessage(obj);
};
m_positionMessageLimiter.setInterval(500);
QObject::connect(&m_positionMessageLimiter, &QTimer::timeout, this, sendPositionUpdate);
QObject::connect(&m_window, &QWindow::xChanged, this, [this]() { m_positionMessageLimiter.start(); });
QObject::connect(&m_window, &QWindow::yChanged, this, [this]() { m_positionMessageLimiter.start(); });
});
QObject::connect(&m_positionMessageLimiter, &QTimer::timeout, this, sendPositionUpdate);
QObject::connect(&m_window, &QWindow::xChanged, this, [this]() { m_positionMessageLimiter.start(); });
QObject::connect(&m_window, &QWindow::yChanged, this, [this]() { m_positionMessageLimiter.start(); });
});
}
setupLiveReloading();
}
void WidgetWindow::setSize(QSize size)
@ -133,11 +140,6 @@ void WidgetWindow::setWidgetSize(const int with, const int height)
m_window.setHeight(height);
}
void WidgetWindow::clearComponentCache()
{
m_window.engine()->clearComponentCache();
}
#ifdef Q_OS_WIN
void WidgetWindow::setWindowBlur(unsigned int style)
{
@ -174,3 +176,34 @@ void WidgetWindow::setWindowBlur(unsigned int style)
}
}
#endif
/*!
\brief Call the qml engine clearComponentCache. This function is used for
refreshing wallpaper when the content has changed. For example this
is needed for live editing when the content is chached.
*/
void WidgetWindow::clearComponentCache()
{
m_window.engine()->clearComponentCache();
}
/*!
\brief This public slot is for QML usage. We limit the change event updates
to every 50ms, because the filesystem can be very trigger happy
with multiple change events per second.
*/
void WidgetWindow::setupLiveReloading()
{
auto reloadQMLLambda = [this]() {
m_liveReloadLimiter.stop();
emit reloadQML(type());
};
auto timeoutLambda = [this]() {
m_liveReloadLimiter.start(50);
};
QObject::connect(&m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged, this, timeoutLambda);
QObject::connect(&m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, this, timeoutLambda);
QObject::connect(&m_liveReloadLimiter, &QTimer::timeout, this, reloadQMLLambda);
m_fileSystemWatcher.addPaths({ projectPath() });
}

View File

@ -52,6 +52,7 @@
#include <QtQuick/QQuickWindow>
#ifdef Q_OS_WIN
#include <QFileSystemWatcher>
#include <qt_windows.h>
#endif
@ -67,7 +68,8 @@ public:
const QString& projectPath,
const QString& appid,
const QString& type,
const QPoint& position);
const QPoint& position,
const bool debugMode = false);
Q_PROPERTY(QString appID READ appID WRITE setAppID NOTIFY appIDChanged)
Q_PROPERTY(QString projectPath READ projectPath WRITE setProjectPath NOTIFY projectPathChanged)
@ -76,6 +78,7 @@ public:
Q_PROPERTY(QPoint position READ position WRITE setPosition NOTIFY positionChanged)
Q_PROPERTY(ScreenPlay::InstalledType::InstalledType type READ type WRITE setType NOTIFY typeChanged)
Q_PROPERTY(ScreenPlaySDK* sdk READ sdk WRITE setSdk NOTIFY sdkChanged)
Q_PROPERTY(bool debugMode READ debugMode WRITE setDebugMode NOTIFY debugModeChanged)
QString appID() const { return m_appID; }
QPoint position() const { return m_position; }
@ -84,10 +87,11 @@ public:
const QString& projectSourceFile() const { return m_projectSourceFile; }
const QUrl& projectSourceFileAbsolute() const { return m_projectSourceFileAbsolute; }
ScreenPlaySDK* sdk() const { return m_sdk.get(); }
bool debugMode() const { return m_debugMode; }
signals:
void qmlExit();
void reloadQML(const ScreenPlay::InstalledType::InstalledType oldType);
void appIDChanged(QString appID);
void qmlSceneValueReceived(QString key, QString value);
void positionChanged(QPoint position);
@ -95,8 +99,8 @@ signals:
void typeChanged(ScreenPlay::InstalledType::InstalledType);
void projectSourceFileChanged(const QString& projectSourceFile);
void projectSourceFileAbsoluteChanged(const QUrl& projectSourceFileAbsolute);
void sdkChanged(ScreenPlaySDK*);
void sdkChanged(ScreenPlaySDK* sdk);
void debugModeChanged(bool debugMode);
public slots:
void setSize(QSize size);
@ -171,9 +175,21 @@ public slots:
emit sdkChanged(sdk);
}
void setDebugMode(bool debugMode)
{
if (m_debugMode == debugMode)
return;
m_debugMode = debugMode;
emit debugModeChanged(m_debugMode);
}
private:
void setupLiveReloading();
private:
QString m_appID;
QString m_projectPath;
QString m_projectSourceFile;
QJsonObject m_project;
QPoint m_clickPos = { 0, 0 };
QPoint m_lastPos = { 0, 0 };
@ -182,10 +198,11 @@ private:
std::unique_ptr<ScreenPlaySDK> m_sdk;
QTimer m_positionMessageLimiter;
ScreenPlay::InstalledType::InstalledType m_type;
QFileSystemWatcher m_fileSystemWatcher;
QTimer m_liveReloadLimiter;
QUrl m_projectSourceFileAbsolute;
#ifdef Q_OS_WIN
HWND m_hwnd;
#endif
QString m_projectSourceFile;
QUrl m_projectSourceFileAbsolute;
bool m_debugMode = false;
};