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:
parent
ebfe616460
commit
a78a48bb2e
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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() });
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user