mirror of
https://gitlab.com/kelteseth/ScreenPlay.git
synced 2024-11-06 19:12:30 +01:00
WIP: Move timeline related stuff into ScreenPlayTimeline
This commit is contained in:
parent
7831290365
commit
142b58f308
@ -12,7 +12,7 @@ set(SOURCES
|
||||
# cmake-format: sort
|
||||
src/wallpaperdata.cpp
|
||||
src/wallpapertimelinesection.cpp
|
||||
src/screenplaytimeline.cpp
|
||||
src/screenplaytimelinemanager.cpp
|
||||
src/app.cpp
|
||||
src/applicationengine.cpp
|
||||
src/create.cpp
|
||||
@ -34,7 +34,7 @@ set(HEADER
|
||||
# cmake-format: sort
|
||||
inc/public/ScreenPlay/wallpaperdata.h
|
||||
inc/public/ScreenPlay/wallpapertimelinesection.h
|
||||
inc/public/ScreenPlay/screenplaytimeline.h
|
||||
inc/public/ScreenPlay/screenplaytimelinemanager.h
|
||||
inc/public/ScreenPlay/app.h
|
||||
inc/public/ScreenPlay/applicationengine.h
|
||||
inc/public/ScreenPlay/create.h
|
||||
|
@ -2,31 +2,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonParseError>
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QQmlEngine>
|
||||
#include <QScopedPointer>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <QtMath>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ScreenPlay/createimportstates.h"
|
||||
#include "ScreenPlay/createimportvideo.h"
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
#include "ScreenPlayUtil/contenttypes.h"
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
@ -40,9 +25,9 @@ class Create : public QObject {
|
||||
Q_PROPERTY(QString ffmpegOutput READ ffmpegOutput WRITE appendFfmpegOutput NOTIFY ffmpegOutputChanged)
|
||||
|
||||
public:
|
||||
explicit Create(const std::shared_ptr<GlobalVariables>& globalVariables);
|
||||
explicit Create(const std::shared_ptr<GlobalVariables>& globalVariables, QObject* parent = nullptr);
|
||||
|
||||
Create();
|
||||
Create(QObject* parent = nullptr);
|
||||
|
||||
Q_INVOKABLE void cancel();
|
||||
|
||||
|
@ -2,14 +2,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QMetaType>
|
||||
#include <QObject>
|
||||
#include <QQmlEngine>
|
||||
#include <QStandardPaths>
|
||||
#include <QUrl>
|
||||
#include <QVersionNumber>
|
||||
|
||||
#include <QQmlEngine>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QRegularExpression>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <memory>
|
||||
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
#include "ScreenPlay/installedlistmodel.h"
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
@ -4,30 +4,18 @@
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QByteArray>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QFile>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
#include <QHash>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QStandardPaths>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QVector>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <memory>
|
||||
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
#include "ScreenPlay/settings.h"
|
||||
#include "ScreenPlayUtil/projectfile.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
class InstalledListModel : public QAbstractListModel {
|
||||
@ -67,9 +55,9 @@ public:
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
Q_INVOKABLE QVariantMap get(const QString& folderName) const;
|
||||
|
||||
public slots:
|
||||
QVariantMap get(const QString& folderName) const;
|
||||
|
||||
void loadInstalledContent();
|
||||
void append(const QString& projectJsonFilePath);
|
||||
|
@ -4,22 +4,16 @@
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QRect>
|
||||
#include <QScreen>
|
||||
#include <QSize>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
#include "ScreenPlay/screenplaywallpaper.h"
|
||||
#include "ScreenPlay/wallpapertimelinesection.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <qt_windows.h>
|
||||
#endif
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "ScreenPlay/wallpapertimelinesection.h"
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
struct Monitor {
|
||||
|
@ -3,19 +3,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QStandardPaths>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QVector>
|
||||
#include <memory>
|
||||
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
#include "ScreenPlay/profile.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
struct Profile;
|
||||
|
@ -1,18 +1,11 @@
|
||||
// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ScreenPlayUtil/contenttypes.h"
|
||||
#include <QAbstractListModel>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QVector>
|
||||
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
struct SettingsItem {
|
||||
|
@ -2,21 +2,20 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QLocalServer>
|
||||
#include <QObject>
|
||||
#include <QPoint>
|
||||
#include <QProcess>
|
||||
#include <QVariantMap>
|
||||
|
||||
#include "ScreenPlay/screenplaytimeline.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
#include "globalvariables.h"
|
||||
#include "monitorlistmodel.h"
|
||||
#include "projectsettingslistmodel.h"
|
||||
#include "screenplaywallpaper.h"
|
||||
#include "screenplaywidget.h"
|
||||
#include "settings.h"
|
||||
#include <memory>
|
||||
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
#include "ScreenPlay/monitorlistmodel.h"
|
||||
#include "ScreenPlay/projectsettingslistmodel.h"
|
||||
#include "ScreenPlay/screenplaytimelinemanager.h"
|
||||
#include "ScreenPlay/screenplaywallpaper.h"
|
||||
#include "ScreenPlay/screenplaywidget.h"
|
||||
#include "ScreenPlay/settings.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
|
||||
@ -37,9 +36,6 @@ public:
|
||||
const std::shared_ptr<MonitorListModel>& mlm,
|
||||
const std::shared_ptr<Settings>& settings);
|
||||
|
||||
int activeWallpaperCounter() const { return m_activeWallpaperCounter; }
|
||||
int activeWidgetsCounter() const { return m_activeWidgetsCounter; }
|
||||
|
||||
std::shared_ptr<ScreenPlayWallpaper> startWallpaper(
|
||||
WallpaperData wallpaperData,
|
||||
const bool saveToProfilesConfigFile);
|
||||
@ -55,14 +51,11 @@ public:
|
||||
const QString identifier,
|
||||
const float relativePosition,
|
||||
QString positionTimeString);
|
||||
|
||||
Q_INVOKABLE QString getTimeString(double relativeLinePosition);
|
||||
|
||||
Q_INVOKABLE bool addTimelineAt(
|
||||
const int index,
|
||||
const float reltiaveLinePosition,
|
||||
QString identifier);
|
||||
Q_INVOKABLE void removeAllTimlineSections();
|
||||
Q_INVOKABLE QCoro::QmlTask removeAllTimlineSections();
|
||||
Q_INVOKABLE bool removeTimelineAt(const int index);
|
||||
Q_INVOKABLE QJsonArray initialSectionsList();
|
||||
Q_INVOKABLE bool setWallpaperAtTimelineIndex(
|
||||
@ -89,7 +82,11 @@ public:
|
||||
Q_INVOKABLE bool setWallpaperFillModeAtMonitorIndex(const int index, const int fillmode);
|
||||
Q_INVOKABLE bool setAllWallpaperValue(const QString& key, const QString& value);
|
||||
Q_INVOKABLE bool setWallpaperValue(const QString& appID, const QString& key, const QString& value);
|
||||
signals:
|
||||
|
||||
int activeWallpaperCounter() const { return m_activeWallpaperCounter; }
|
||||
int activeWidgetsCounter() const { return m_activeWidgetsCounter; }
|
||||
|
||||
signals:
|
||||
void activeWallpaperCounterChanged(int activeWallpaperCounter);
|
||||
void activeWidgetsCounterChanged(int activeWidgetsCounter);
|
||||
void monitorConfigurationChanged();
|
||||
@ -103,21 +100,16 @@ public:
|
||||
|
||||
private slots:
|
||||
bool saveProfiles();
|
||||
void checkActiveWallpaperTimeline();
|
||||
void newConnection();
|
||||
void setActiveWallpaperCounter(int activeWallpaperCounter);
|
||||
void setActiveWidgetsCounter(int activeWidgetsCounter);
|
||||
|
||||
private:
|
||||
void printTimelines();
|
||||
bool loadProfiles();
|
||||
void updateQmlTimelines();
|
||||
|
||||
void updateIndices();
|
||||
bool checkIsAnotherScreenPlayInstanceRunning();
|
||||
bool removeWallpaper(const QString& appID);
|
||||
bool removeWidget(const QString& appID);
|
||||
void activateNewTimeline();
|
||||
|
||||
bool loadWidgetConfig(const QJsonObject& widget);
|
||||
std::shared_ptr<GlobalVariables> m_globalVariables;
|
||||
@ -126,13 +118,12 @@ private:
|
||||
std::unique_ptr<QLocalServer> m_server;
|
||||
QVector<std::shared_ptr<ScreenPlayWidget>> m_screenPlayWidgets;
|
||||
std::vector<std::unique_ptr<SDKConnection>> m_unconnectedClients;
|
||||
ScreenPlayTimeline m_screenPlayTimeline;
|
||||
ScreenPlayTimelineManager m_screenPlayTimelineManager;
|
||||
|
||||
int m_activeWallpaperCounter { 0 };
|
||||
int m_activeWidgetsCounter { 0 };
|
||||
|
||||
QTimer m_saveLimiter;
|
||||
QTimer m_contentTimer;
|
||||
|
||||
Util m_util;
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFileInfoList>
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <memory>
|
||||
|
||||
#include "ScreenPlay/wallpapertimelinesection.h"
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
|
||||
struct ScreenPlayTimeline{
|
||||
|
||||
|
||||
float calculateRelativePosition(const QTime& endTime);
|
||||
|
||||
std::optional<std::shared_ptr<WallpaperTimelineSection>> loadTimelineWallpaperConfig(const QJsonObject& timelineObj);
|
||||
std::shared_ptr<WallpaperTimelineSection> findActiveWallpaperTimelineSection();
|
||||
std::optional<std::shared_ptr<WallpaperTimelineSection>> activeWallpaperSectionByAppID(const QString& appID);
|
||||
std::shared_ptr<WallpaperTimelineSection> getCurrentTimeline();
|
||||
|
||||
|
||||
QVector<std::shared_ptr<WallpaperTimelineSection>> m_wallpaperTimelineSectionsList;
|
||||
|
||||
// We use a24 hour system
|
||||
const QString m_timelineTimeFormat = "hh:mm:ss";
|
||||
};
|
||||
|
||||
}
|
53
ScreenPlay/inc/public/ScreenPlay/screenplaytimelinemanager.h
Normal file
53
ScreenPlay/inc/public/ScreenPlay/screenplaytimelinemanager.h
Normal file
@ -0,0 +1,53 @@
|
||||
// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <memory>
|
||||
|
||||
#include "ScreenPlay/wallpapertimelinesection.h"
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
class ScreenPlayTimelineManager : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ScreenPlayTimelineManager(QObject* parent = nullptr);
|
||||
|
||||
std::optional<std::shared_ptr<WallpaperTimelineSection>> activeWallpaperSectionByAppID(const QString& appID);
|
||||
std::shared_ptr<WallpaperTimelineSection> findActiveWallpaperTimelineSection();
|
||||
std::shared_ptr<WallpaperTimelineSection> findTimelineForCurrentTime();
|
||||
bool addTimelineFromSettings(const QJsonObject& timelineObj);
|
||||
bool deactivateCurrentTimeline();
|
||||
bool moveTimelineAt(const int index, const QString identifier, const float relativePosition, QString positionTimeString);
|
||||
bool startTimeline();
|
||||
bool addTimelineAt(const int index, const float reltiaveLinePosition, QString identifier);
|
||||
bool removeTimelineAt(const int index);
|
||||
QCoro::Task<bool> removeAllTimlineSections();
|
||||
void updateIndices();
|
||||
void printTimelines();
|
||||
bool setWallpaperAtTimelineIndex(WallpaperData wallpaperData,
|
||||
const int timelineIndex,
|
||||
const QString& identifier);
|
||||
QJsonArray initialSectionsList();
|
||||
QJsonArray timelineWallpaperList();
|
||||
void setGlobalVariables(const std::shared_ptr<GlobalVariables>& globalVariables);
|
||||
void setSettings(const std::shared_ptr<Settings>& settings);
|
||||
void startupFirstTimeline();
|
||||
private slots:
|
||||
void checkActiveWallpaperTimeline();
|
||||
|
||||
signals:
|
||||
void requestSaveProfiles();
|
||||
|
||||
private:
|
||||
QVector<std::shared_ptr<WallpaperTimelineSection>> m_wallpaperTimelineSectionsList;
|
||||
// We use a 24 hour system
|
||||
const QString m_timelineTimeFormat = "hh:mm:ss";
|
||||
QTimer m_contentTimer;
|
||||
std::shared_ptr<GlobalVariables> m_globalVariables;
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
};
|
||||
}
|
@ -2,14 +2,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFileInfoList>
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
#include <memory>
|
||||
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
|
@ -2,21 +2,19 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QJsonObject>
|
||||
#include <QLocalSocket>
|
||||
#include <QObject>
|
||||
#include <QPoint>
|
||||
#include <QProcess>
|
||||
#include <QTimer>
|
||||
#include <memory>
|
||||
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
#include "ScreenPlay/projectsettingslistmodel.h"
|
||||
#include "ScreenPlay/sdkconnection.h"
|
||||
#include "ScreenPlayUtil/processmanager.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
class ScreenPlayWidget : public QObject {
|
||||
|
@ -2,21 +2,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
#include <QVector>
|
||||
#include <QWebSocketServer>
|
||||
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
|
@ -2,41 +2,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QDomDocument>
|
||||
#include <QDomElement>
|
||||
#include <QDomNodeList>
|
||||
#include <QFile>
|
||||
#include <QFontDatabase>
|
||||
#include <QGuiApplication>
|
||||
#include <QIODevice>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
#include <QPair>
|
||||
#include <QProcess>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QQmlPropertyMap>
|
||||
#include <QSettings>
|
||||
#include <QStandardPaths>
|
||||
#include <QString>
|
||||
#include <QSysInfo>
|
||||
#include <QTextStream>
|
||||
#include <QThread>
|
||||
#include <QUrl>
|
||||
#include <QTranslator>
|
||||
#include <QVariant>
|
||||
#include <QVector>
|
||||
#include <QVersionNumber>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
|
||||
#include "ScreenPlayUtil/contenttypes.h"
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace ScreenPlay {
|
||||
class ActiveProfile;
|
||||
|
@ -1,16 +1,15 @@
|
||||
// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFileInfoList>
|
||||
#include <QCoro/QCoroTask>
|
||||
#include <QCoro/QCoroTimer>
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTimer>
|
||||
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
#include "ScreenPlay/settings.h"
|
||||
#include "ScreenPlay/wallpaperdata.h"
|
||||
|
||||
namespace ScreenPlay {
|
||||
@ -18,13 +17,20 @@ class ScreenPlayWallpaper;
|
||||
// Represents one line in the UI. ScreenPlayManager has a list of
|
||||
// WallpaperTimeline. Only the active timeline section has
|
||||
// a filled vector of ScreenPlayWallpaper
|
||||
struct WallpaperTimelineSection {
|
||||
// Is active is needed as an additional flag during switching.
|
||||
// When timeline A is no longer in the time range, then we can
|
||||
// use this flag to know that it was the last active timeline and
|
||||
// remove all active wallpaper.
|
||||
bool isActive = false;
|
||||
|
||||
class WallpaperTimelineSection : public QObject {
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
QML_UNCREATABLE("")
|
||||
Q_CLASSINFO("RegisterEnumClassesUnscoped", "false")
|
||||
public:
|
||||
enum class Status {
|
||||
Inactive,
|
||||
Starting,
|
||||
Closing,
|
||||
Active,
|
||||
};
|
||||
Q_ENUM(Status)
|
||||
Status status = Status::Inactive;
|
||||
QString identifier;
|
||||
int index = 0; // Needed to check
|
||||
float relativePosition = 0.0f;
|
||||
@ -33,49 +39,21 @@ struct WallpaperTimelineSection {
|
||||
// Data from the profiles.json that we need when we
|
||||
// enable this section of the pipeline. We keep a copy
|
||||
// here when this timeline needs to become active
|
||||
std::vector<WallpaperData> wallpaperData;
|
||||
std::vector<WallpaperData> wallpaperDataList;
|
||||
// All active wallpaper.
|
||||
std::vector<std::shared_ptr<ScreenPlayWallpaper>> activeWallpaperList;
|
||||
|
||||
bool close();
|
||||
|
||||
std::shared_ptr<GlobalVariables> globalVariables;
|
||||
std::shared_ptr<Settings> settings;
|
||||
// Check if currentTime falls within the timeline section
|
||||
bool containsTime(const QTime& time) const
|
||||
{
|
||||
if (endTime < startTime) { // Timeline spans midnight
|
||||
return (time >= startTime || time < endTime);
|
||||
} else {
|
||||
return (time >= startTime && time < endTime);
|
||||
}
|
||||
}
|
||||
bool containsTime(const QTime& time) const;
|
||||
|
||||
QJsonObject serialize() const
|
||||
{
|
||||
QJsonObject data;
|
||||
data.insert("isActive", isActive);
|
||||
data.insert("identifier", identifier);
|
||||
data.insert("index", index);
|
||||
data.insert("relativePosition", relativePosition);
|
||||
data.insert("startTime", startTime.toString());
|
||||
data.insert("endTime", endTime.toString());
|
||||
QJsonObject serialize() const;
|
||||
|
||||
// Serialize vector<WallpaperData>
|
||||
QJsonArray wallpaperDataArray;
|
||||
for (const auto& wallpaper : wallpaperData) {
|
||||
QJsonObject wallpaperObject = wallpaper.serialize(); // Assuming WallpaperData has a serialize method
|
||||
wallpaperDataArray.append(wallpaperObject);
|
||||
}
|
||||
data.insert("wallpaperData", wallpaperDataArray);
|
||||
bool activateTimeline();
|
||||
QCoro::Task<bool> deactivateTimeline();
|
||||
|
||||
// Serialize vector<std::shared_ptr<ScreenPlayWallpaper>>
|
||||
// QJsonArray activeWallpaperArray;
|
||||
// for (const auto& wallpaper : activeWallpaperList) {
|
||||
// QJsonObject wallpaperObject = wallpaper->serialize(); // Assuming ScreenPlayWallpaper has a serialize method
|
||||
// activeWallpaperArray.append(wallpaperObject);
|
||||
// }
|
||||
// data.insert("activeWallpaperList", activeWallpaperArray);
|
||||
|
||||
return data;
|
||||
}
|
||||
signals:
|
||||
void requestSaveProfiles();
|
||||
};
|
||||
}
|
||||
|
@ -2,41 +2,24 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QColor>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QFont>
|
||||
#include <QFuture>
|
||||
#include <QFutureWatcher>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonParseError>
|
||||
#include <QLinearGradient>
|
||||
#include <QObject>
|
||||
#include <QPainter>
|
||||
#include <QProcess>
|
||||
#include <QQmlEngine>
|
||||
#include <QScopedPointer>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QTextOption>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <QtMath>
|
||||
|
||||
#include "ScreenPlay/CMakeVariables.h"
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
|
||||
#include <QColor>
|
||||
#include <QFuture>
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QQmlEngine>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "qcorotask.h"
|
||||
#include "qml/qcoroqml.h"
|
||||
#include "qml/qcoroqmltask.h"
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
class Wizards : public QObject {
|
||||
|
@ -18,17 +18,19 @@ Control {
|
||||
property int length: timeLine.sectionsList.length
|
||||
|
||||
function getActiveTimeline() {
|
||||
return timeLine.sectionsList[root.activeTimelineIndex];
|
||||
return timeLine.sectionsList[root.activeTimelineIndex]
|
||||
}
|
||||
|
||||
function removeAll() {
|
||||
timeLine.removeAll();
|
||||
timeLine.removeAll()
|
||||
}
|
||||
|
||||
function printTimelines() {
|
||||
print("################# qml:");
|
||||
print("################# qml:")
|
||||
for (var i = 0; i < timeLine.sectionsList.length; i++) {
|
||||
print(timeLine.sectionsList[i].index, timeLine.sectionsList[i].identifier, timeLine.sectionsList[i].relativeLinePosition);
|
||||
print(timeLine.sectionsList[i].index,
|
||||
timeLine.sectionsList[i].identifier,
|
||||
timeLine.sectionsList[i].relativeLinePosition)
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +40,8 @@ Control {
|
||||
property string identifier
|
||||
property int index: 0
|
||||
property real relativeLinePosition: lineHandle.linePosition
|
||||
onRelativeLinePositionChanged: print("relativelinepos: ", relativeLinePosition)
|
||||
onRelativeLinePositionChanged: print("relativelinepos: ",
|
||||
relativeLinePosition)
|
||||
property LineHandle lineHandle
|
||||
property LineIndicator lineIndicator
|
||||
}
|
||||
@ -52,35 +55,45 @@ Control {
|
||||
onWidthChanged: timeLine.updatePositions()
|
||||
property var initialSectionsList: []
|
||||
Component.onCompleted: {
|
||||
let sectionObects = App.screenPlayManager.initialSectionsList();
|
||||
let sectionObects = App.screenPlayManager.initialSectionsList()
|
||||
for (let sectionObject in sectionObects) {
|
||||
initialSectionsList.push(sectionObects[sectionObject]);
|
||||
initialSectionsList.push(sectionObects[sectionObject])
|
||||
}
|
||||
initialSectionsList.sort(function (a, b) {
|
||||
return b.index - a.index;
|
||||
});
|
||||
return b.index - a.index
|
||||
})
|
||||
for (let index in initialSectionsList) {
|
||||
let section = initialSectionsList[index];
|
||||
addSection(section.identifier, section.relativePosition);
|
||||
let section = initialSectionsList[index]
|
||||
addSection(section.identifier, section.relativePosition)
|
||||
}
|
||||
}
|
||||
|
||||
function removeAll() {
|
||||
print("removeAll", timeLine.sectionsList.length);
|
||||
print("removeAll", timeLine.sectionsList.length)
|
||||
for (var i = 0; i < timeLine.sectionsList.length; i++) {
|
||||
// ORDER is important here! Destory the children first
|
||||
print("remove index ", i);
|
||||
let section = timeLine.sectionsList[i];
|
||||
section.lineHandle.destroy();
|
||||
section.lineIndicator.destroy();
|
||||
section.destroy();
|
||||
print("remove index ", i)
|
||||
let section = timeLine.sectionsList[i]
|
||||
section.lineHandle.destroy()
|
||||
section.lineIndicator.destroy()
|
||||
section.destroy()
|
||||
}
|
||||
timeLine.sectionsList = [];
|
||||
App.screenPlayManager.removeAllTimlineSections();
|
||||
const position = 1.0;
|
||||
const identifier = App.util.generateRandomString(4);
|
||||
const sectionObject = timeLine.addSection(identifier, position);
|
||||
App.screenPlayManager.addTimelineAt(sectionObject.index, sectionObject.relativeLinePosition, sectionObject.identifier);
|
||||
timeLine.sectionsList = []
|
||||
App.screenPlayManager.removeAllTimlineSections().then(result => {
|
||||
|
||||
if (!result.success) {
|
||||
console.error("removeAllTimlineSections failed")
|
||||
return
|
||||
}
|
||||
|
||||
const position = 1.0
|
||||
const identifier = App.util.generateRandomString(
|
||||
4)
|
||||
const sectionObject = timeLine.addSection(
|
||||
identifier,
|
||||
position)
|
||||
App.screenPlayManager.addTimelineAt(sectionObject.index, sectionObject.relativeLinePosition, sectionObject.identifier)
|
||||
})
|
||||
}
|
||||
|
||||
// IMPORTANT: The new element is always on the left. The first
|
||||
@ -88,206 +101,215 @@ Control {
|
||||
// user can never delete it. It only gets "pushed" further
|
||||
// to the right, by decreasing its size.
|
||||
function addSection(identifier, stopPosition) {
|
||||
print("stopPosition", stopPosition);
|
||||
print("stopPosition", stopPosition)
|
||||
|
||||
// Make sure to limit float precision
|
||||
const fixedStopPosition = stopPosition;
|
||||
print("addSection at: ", fixedStopPosition);
|
||||
const fixedStopPosition = stopPosition
|
||||
print("addSection at: ", fixedStopPosition)
|
||||
if (stopPosition < 0 || fixedStopPosition > 1) {
|
||||
console.error("Invalid position:", fixedStopPosition);
|
||||
return;
|
||||
console.error("Invalid position:", fixedStopPosition)
|
||||
return
|
||||
}
|
||||
let sectionObject = sectionComp.createObject(timeLine, {
|
||||
"identifier": identifier,
|
||||
"relativeLinePosition": fixedStopPosition
|
||||
});
|
||||
timeLine.sectionsList.push(sectionObject);
|
||||
})
|
||||
timeLine.sectionsList.push(sectionObject)
|
||||
timeLine.sectionsList.sort(function (a, b) {
|
||||
return a.relativeLinePosition - b.relativeLinePosition;
|
||||
});
|
||||
const index = timeLine.sectionsList.indexOf(sectionObject);
|
||||
console.log("Addsection:", index);
|
||||
createSection(index, fixedStopPosition, sectionObject, identifier);
|
||||
updatePositions();
|
||||
return sectionObject;
|
||||
return a.relativeLinePosition - b.relativeLinePosition
|
||||
})
|
||||
const index = timeLine.sectionsList.indexOf(sectionObject)
|
||||
console.log("Addsection:", index)
|
||||
createSection(index, fixedStopPosition, sectionObject, identifier)
|
||||
updatePositions()
|
||||
return sectionObject
|
||||
}
|
||||
|
||||
function createSection(index, stopPosition, section, identifier) {
|
||||
console.log("Adding at:", index, stopPosition, identifier);
|
||||
console.log("Adding at:", index, stopPosition, identifier)
|
||||
|
||||
//console.assert(isFloat(stopPosition))
|
||||
let haComponent = Qt.createComponent("LineHandle.qml");
|
||||
let haComponent = Qt.createComponent("LineHandle.qml")
|
||||
if (haComponent.status === Component.Error) {
|
||||
console.assert(haComponent.errorString());
|
||||
return;
|
||||
console.assert(haComponent.errorString())
|
||||
return
|
||||
}
|
||||
section.lineHandle = haComponent.createObject(handleWrapper);
|
||||
section.lineHandle.lineWidth = timeLine.width;
|
||||
section.lineHandle.x = Math.round(handleWrapper.width * timeLine.sectionsList[index].relativeLinePosition);
|
||||
section.lineHandle.y = -section.lineHandle.height / 2;
|
||||
section.lineHandle = haComponent.createObject(handleWrapper)
|
||||
section.lineHandle.lineWidth = timeLine.width
|
||||
section.lineHandle.x = Math.round(
|
||||
handleWrapper.width * timeLine.sectionsList[index].relativeLinePosition)
|
||||
section.lineHandle.y = -section.lineHandle.height / 2
|
||||
// Will be set later
|
||||
section.lineHandle.lineMinimum = timeLine.x;
|
||||
section.lineHandle.lineMaximum = timeLine.x;
|
||||
section.lineHandle.handleMoved.connect(timeLine.onHandleMoved);
|
||||
let liComponent = Qt.createComponent("LineIndicator.qml");
|
||||
section.lineHandle.lineMinimum = timeLine.x
|
||||
section.lineHandle.lineMaximum = timeLine.x
|
||||
section.lineHandle.handleMoved.connect(timeLine.onHandleMoved)
|
||||
let liComponent = Qt.createComponent("LineIndicator.qml")
|
||||
if (liComponent.status === Component.Error) {
|
||||
console.assert(liComponent.errorString());
|
||||
return;
|
||||
console.assert(liComponent.errorString())
|
||||
return
|
||||
}
|
||||
|
||||
// Set color initially so we do not have a weird color animation at start
|
||||
const lineIndicatorProperties = {
|
||||
"color": getColorAtIndex(index)
|
||||
};
|
||||
section.lineIndicator = liComponent.createObject(lineIndicatorWrapper, lineIndicatorProperties);
|
||||
section.lineIndicator.height = lineIndicatorWrapper.height;
|
||||
section.lineIndicator.index = index;
|
||||
section.lineIndicator.identifier = identifier;
|
||||
section.lineIndicator.color = getColorAtIndex(index);
|
||||
section.lineIndicator.remove.connect(timeLine.removeSection);
|
||||
section.lineIndicator.lineSelected.connect(timeLine.lineIndicatorSelected);
|
||||
}
|
||||
section.lineIndicator = liComponent.createObject(
|
||||
lineIndicatorWrapper, lineIndicatorProperties)
|
||||
section.lineIndicator.height = lineIndicatorWrapper.height
|
||||
section.lineIndicator.index = index
|
||||
section.lineIndicator.identifier = identifier
|
||||
section.lineIndicator.color = getColorAtIndex(index)
|
||||
section.lineIndicator.remove.connect(timeLine.removeSection)
|
||||
section.lineIndicator.lineSelected.connect(
|
||||
timeLine.lineIndicatorSelected)
|
||||
}
|
||||
|
||||
function sectionFromHandle(lineHandle) {
|
||||
for (var i = 0; i < timeLine.sectionsList.length; i++) {
|
||||
if (timeLine.sectionsList[i].lineHandle === lineHandle)
|
||||
return timeLine.sectionsList[i];
|
||||
return timeLine.sectionsList[i]
|
||||
}
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
function onHandleMoved(lineHandle) {
|
||||
updatePositions();
|
||||
const section = sectionFromHandle(lineHandle);
|
||||
updatePositions()
|
||||
const section = sectionFromHandle(lineHandle)
|
||||
if (section === null) {
|
||||
print(lineHandle.linePosition);
|
||||
console.error("Unable to match handle to section list");
|
||||
return;
|
||||
print(lineHandle.linePosition)
|
||||
console.error("Unable to match handle to section list")
|
||||
return
|
||||
}
|
||||
App.screenPlayManager.moveTimelineAt(section.index, section.identifier, lineHandle.linePosition, lineHandle.timeString);
|
||||
App.screenPlayManager.moveTimelineAt(section.index,
|
||||
section.identifier,
|
||||
lineHandle.linePosition,
|
||||
lineHandle.timeString)
|
||||
}
|
||||
|
||||
function lineIndicatorSelected(activeTimelineIndex) {
|
||||
for (var i = 0; i < timeLine.sectionsList.length; i++) {
|
||||
if (i === activeTimelineIndex) {
|
||||
timeLine.sectionsList[i].lineIndicator.selected = true;
|
||||
continue;
|
||||
timeLine.sectionsList[i].lineIndicator.selected = true
|
||||
continue
|
||||
}
|
||||
timeLine.sectionsList[i].lineIndicator.selected = false;
|
||||
timeLine.sectionsList[i].lineIndicator.selected = false
|
||||
}
|
||||
root.activeTimelineIndex = activeTimelineIndex;
|
||||
root.activeTimelineIndex = activeTimelineIndex
|
||||
}
|
||||
|
||||
// We must update all indexes when removing/adding an element
|
||||
function updateIndicatorIndexes() {
|
||||
if (timeLine.sectionsList === null || timeLine.sectionsList === undefined)
|
||||
return;
|
||||
if (timeLine.sectionsList === null
|
||||
|| timeLine.sectionsList === undefined)
|
||||
return
|
||||
timeLine.sectionsList.sort(function (a, b) {
|
||||
return a.relativeLinePosition - b.relativeLinePosition;
|
||||
});
|
||||
return a.relativeLinePosition - b.relativeLinePosition
|
||||
})
|
||||
for (var i = 0; i < timeLine.sectionsList.length; i++) {
|
||||
timeLine.sectionsList[i].index = i;
|
||||
timeLine.sectionsList[i].lineIndicator.index = i;
|
||||
timeLine.sectionsList[i].index = i
|
||||
timeLine.sectionsList[i].lineIndicator.index = i
|
||||
//print("updateIndicatorIndexes:", timeLine.sectionsList[i].index, timeLine.sectionsList[i].relativeLinePosition)
|
||||
}
|
||||
}
|
||||
|
||||
function removeSection(index) {
|
||||
print(timeLine.stopPositionList);
|
||||
print(timeLine.sectionList);
|
||||
const isLast = index === timeLine.sectionsList.length - 1;
|
||||
print(timeLine.stopPositionList)
|
||||
print(timeLine.sectionList)
|
||||
const isLast = index === timeLine.sectionsList.length - 1
|
||||
if (isLast)
|
||||
return;
|
||||
return
|
||||
// ORDER is important here! First destory the object
|
||||
// and then remove i f
|
||||
let section = timeLine.sectionsList[index];
|
||||
section.lineHandle.destroy();
|
||||
section.lineIndicator.destroy();
|
||||
section.destroy();
|
||||
timeLine.sectionsList.splice(index, 1);
|
||||
updatePositions();
|
||||
App.screenPlayManager.removeTimelineAt(index);
|
||||
let section = timeLine.sectionsList[index]
|
||||
section.lineHandle.destroy()
|
||||
section.lineIndicator.destroy()
|
||||
section.destroy()
|
||||
timeLine.sectionsList.splice(index, 1)
|
||||
updatePositions()
|
||||
App.screenPlayManager.removeTimelineAt(index)
|
||||
}
|
||||
|
||||
function updatePositions() {
|
||||
// Iterate through each handle in the 'sectionList' array
|
||||
for (var i = 0; i < timeLine.sectionsList.length; i++) {
|
||||
let handle = timeLine.sectionsList[i].lineHandle;
|
||||
let handle = timeLine.sectionsList[i].lineHandle
|
||||
|
||||
// Determine the minimum position for the current handle
|
||||
let prevPos;
|
||||
let prevPos
|
||||
if (i === 0) {
|
||||
// If it's the first handle, its minimum is 0
|
||||
prevPos = 0;
|
||||
prevPos = 0
|
||||
} else {
|
||||
// Otherwise, it's directly the position of the previous handle
|
||||
prevPos = timeLine.sectionsList[i - 1].lineHandle.x;
|
||||
prevPos = timeLine.sectionsList[i - 1].lineHandle.x
|
||||
}
|
||||
|
||||
// Determine the maximum position for the current handle
|
||||
let nextPos;
|
||||
let nextPos
|
||||
if (i === timeLine.sectionsList.length - 1) {
|
||||
// If it's the last handle, its maximum is the width of the line
|
||||
nextPos = timeLine.width;
|
||||
nextPos = timeLine.width
|
||||
} else {
|
||||
// Otherwise, it's directly the position of the next handle
|
||||
nextPos = timeLine.sectionsList[i + 1].lineHandle.x;
|
||||
nextPos = timeLine.sectionsList[i + 1].lineHandle.x
|
||||
}
|
||||
|
||||
// Set the determined minimum and maximum positions for the current handle
|
||||
handle.lineMinimum = prevPos;
|
||||
handle.lineMaximum = nextPos;
|
||||
handle.lineMinimum = prevPos
|
||||
handle.lineMaximum = nextPos
|
||||
|
||||
//timeLine.sectionsList[i].relativeLinePosition =prevPos / timeLine.width
|
||||
// print("sections: ", i, "prev minimum ",prevPos,"next maximum", nextPos, timeLine.sectionsList[i].relativeLinePosition)
|
||||
}
|
||||
for (var i = 0; i < timeLine.sectionsList.length; i++) {
|
||||
let section = timeLine.sectionsList[i];
|
||||
section.relativeLinePosition = section.lineHandle.linePosition;
|
||||
let section = timeLine.sectionsList[i]
|
||||
section.relativeLinePosition = section.lineHandle.linePosition
|
||||
// print(section.relativeLinePosition, section.lineHandle.lineMinimum, section.lineHandle.lineMaximum)
|
||||
}
|
||||
updateIndicatorPositions();
|
||||
updateLastHandle();
|
||||
updateIndicatorColor();
|
||||
updateIndicatorIndexes();
|
||||
updateIndicatorPositions()
|
||||
updateLastHandle()
|
||||
updateIndicatorColor()
|
||||
updateIndicatorIndexes()
|
||||
}
|
||||
|
||||
function getColorAtIndex(index) {
|
||||
let i = index;
|
||||
let i = index
|
||||
// Start from the beginnging again
|
||||
if (index >= timeLine.lineColors.length) {
|
||||
i = index % timeLine.lineColors.length;
|
||||
i = index % timeLine.lineColors.length
|
||||
}
|
||||
return timeLine.lineColors[i];
|
||||
return timeLine.lineColors[i]
|
||||
}
|
||||
|
||||
function updateIndicatorColor() {
|
||||
for (var i = 0; i < timeLine.sectionsList.length; i++) {
|
||||
let lineIndicator = timeLine.sectionsList[i].lineIndicator;
|
||||
lineIndicator.color = getColorAtIndex(i);
|
||||
let lineIndicator = timeLine.sectionsList[i].lineIndicator
|
||||
lineIndicator.color = getColorAtIndex(i)
|
||||
}
|
||||
}
|
||||
|
||||
function updateLastHandle() {
|
||||
for (var i = 0; i < timeLine.sectionsList.length; i++) {
|
||||
timeLine.sectionsList[i].lineHandle.isLast = i === timeLine.sectionsList.length - 1;
|
||||
timeLine.sectionsList[i].lineIndicator.isLast = i === timeLine.sectionsList.length - 1;
|
||||
timeLine.sectionsList[i].lineHandle.isLast = i === timeLine.sectionsList.length - 1
|
||||
timeLine.sectionsList[i].lineIndicator.isLast = i
|
||||
=== timeLine.sectionsList.length - 1
|
||||
}
|
||||
}
|
||||
|
||||
function updateIndicatorPositions() {
|
||||
for (var i = 0; i < timeLine.sectionsList.length; i++) {
|
||||
const lineIndicator = timeLine.sectionsList[i].lineIndicator;
|
||||
const lineIndicator = timeLine.sectionsList[i].lineIndicator
|
||||
//print(i, lineIndicator.x, lineIndicator.width, timeLine.sectionsList[i].relativeLinePosition)
|
||||
const handle = timeLine.sectionsList[i].lineHandle;
|
||||
lineIndicator.x = handle.dragHandler.xAxis.minimum;
|
||||
lineIndicator.width = (handle.linePosition * handle.lineWidth).toFixed(2) - lineIndicator.x;
|
||||
const handle = timeLine.sectionsList[i].lineHandle
|
||||
lineIndicator.x = handle.dragHandler.xAxis.minimum
|
||||
lineIndicator.width = (handle.linePosition * handle.lineWidth).toFixed(
|
||||
2) - lineIndicator.x
|
||||
}
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/3885844
|
||||
function isFloat(n) {
|
||||
return n === +n && n !== (n | 0);
|
||||
return n === +n && n !== (n | 0)
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@ -310,10 +332,13 @@ Control {
|
||||
color: Material.color(Material.BlueGrey)
|
||||
width: 2
|
||||
height: 30
|
||||
y: (addHandleWrapper.height - height) / 2 // Vertically center within addHandleWrapper
|
||||
y: (addHandleWrapper.height - height)
|
||||
/ 2 // Vertically center within addHandleWrapper
|
||||
|
||||
property int totalSeconds: 86400 // Total seconds in a day
|
||||
property int currentSeconds: (new Date().getHours() * 3600) + (new Date().getMinutes() * 60) + new Date().getSeconds()
|
||||
property int currentSeconds: (new Date().getHours(
|
||||
) * 3600) + (new Date().getMinutes(
|
||||
) * 60) + new Date().getSeconds()
|
||||
|
||||
x: addHandleWrapper.width * (currentSeconds / totalSeconds)
|
||||
|
||||
@ -322,9 +347,15 @@ Control {
|
||||
repeat: true
|
||||
running: true
|
||||
onTriggered: {
|
||||
currentTimeIndicator.currentSeconds = (new Date().getHours() * 3600) + (new Date().getMinutes() * 60) + new Date().getSeconds();
|
||||
currentTimeIndicator.x = addHandleWrapper.width * (currentTimeIndicator.currentSeconds / currentTimeIndicator.totalSeconds);
|
||||
currentTimeText.text = Qt.formatTime(new Date(), "hh:mm:ss");
|
||||
currentTimeIndicator.currentSeconds
|
||||
= (new Date().getHours(
|
||||
) * 3600) + (new Date().getMinutes(
|
||||
) * 60) + new Date().getSeconds(
|
||||
)
|
||||
currentTimeIndicator.x = addHandleWrapper.width
|
||||
* (currentTimeIndicator.currentSeconds / currentTimeIndicator.totalSeconds)
|
||||
currentTimeText.text = Qt.formatTime(new Date(),
|
||||
"hh:mm:ss")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -372,11 +403,15 @@ Control {
|
||||
ToolButton {
|
||||
text: "➕"
|
||||
onClicked: {
|
||||
const p = this.x / timeLine.width;
|
||||
const position = p.toFixed(4);
|
||||
const identifier = App.util.generateRandomString(4);
|
||||
const sectionObject = timeLine.addSection(identifier, position);
|
||||
App.screenPlayManager.addTimelineAt(sectionObject.index, sectionObject.relativeLinePosition, sectionObject.identifier);
|
||||
const p = this.x / timeLine.width
|
||||
const position = p.toFixed(4)
|
||||
const identifier = App.util.generateRandomString(4)
|
||||
const sectionObject = timeLine.addSection(identifier,
|
||||
position)
|
||||
App.screenPlayManager.addTimelineAt(
|
||||
sectionObject.index,
|
||||
sectionObject.relativeLinePosition,
|
||||
sectionObject.identifier)
|
||||
}
|
||||
|
||||
x: hoverHandler.point.position.x - width * .5
|
||||
|
@ -120,12 +120,13 @@ void App::init()
|
||||
// Must be called last to display a error message on startup by the qml engine
|
||||
m_screenPlayManager->init(m_globalVariables, m_monitorListModel, m_settings);
|
||||
|
||||
QObject::connect(
|
||||
m_monitorListModel.get(),
|
||||
&MonitorListModel::monitorConfigurationChanged,
|
||||
m_screenPlayManager.get(), [this]() {
|
||||
m_screenPlayManager->removeAllWallpapers(true);
|
||||
});
|
||||
// TODO
|
||||
// QObject::connect(
|
||||
// m_monitorListModel.get(),
|
||||
// &MonitorListModel::monitorConfigurationChanged,
|
||||
// m_screenPlayManager.get(), [this]() {
|
||||
// m_screenPlayManager->removeAllWallpapers(true);
|
||||
// });
|
||||
}
|
||||
|
||||
QString App::version() const
|
||||
|
@ -1,8 +1,22 @@
|
||||
// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only
|
||||
|
||||
#include "ScreenPlay/create.h"
|
||||
#include "ScreenPlay/createimportvideo.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
#include "qguiapplication.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QGuiApplication>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonParseError>
|
||||
#include <QStringList>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <QtMath>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
@ -19,8 +33,8 @@ namespace ScreenPlay {
|
||||
/*!
|
||||
Constructor.
|
||||
*/
|
||||
Create::Create(const std::shared_ptr<GlobalVariables>& globalVariables)
|
||||
: QObject(nullptr)
|
||||
Create::Create(const std::shared_ptr<GlobalVariables>& globalVariables, QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_globalVariables(globalVariables)
|
||||
{
|
||||
}
|
||||
@ -28,8 +42,8 @@ Create::Create(const std::shared_ptr<GlobalVariables>& globalVariables)
|
||||
/*!
|
||||
Constructor for the QMLEngine.
|
||||
*/
|
||||
Create::Create()
|
||||
: QObject(nullptr)
|
||||
Create::Create(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
#include "ScreenPlay/CMakeVariables.h"
|
||||
#include <QMetaType>
|
||||
#include <QStandardPaths>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only
|
||||
|
||||
#include "ScreenPlay/installedlistfilter.h"
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
#include <QRegularExpression>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
|
@ -2,8 +2,17 @@
|
||||
|
||||
#include "ScreenPlay/installedlistmodel.h"
|
||||
#include "ScreenPlay/CMakeVariables.h"
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QGuiApplication>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QStandardPaths>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
|
||||
#include <QUrl>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
|
@ -1,10 +1,15 @@
|
||||
// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only
|
||||
|
||||
#include "ScreenPlay/monitorlistmodel.h"
|
||||
#include "ScreenPlay/screenplaywallpaper.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include "windowsintegration.h"
|
||||
#endif
|
||||
#include <QGuiApplication>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
/*!
|
||||
|
@ -2,11 +2,16 @@
|
||||
|
||||
#include "ScreenPlay/profilelistmodel.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QFile>
|
||||
#include <QFileInfoList>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QPair>
|
||||
#include <QStandardPaths>
|
||||
#include <QUrl>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
|
@ -2,6 +2,13 @@
|
||||
|
||||
#include "ScreenPlay/projectsettingslistmodel.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
/*!
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include "ScreenPlay/screenplaymanager.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QScopeGuard>
|
||||
namespace ScreenPlay {
|
||||
|
||||
@ -26,8 +24,8 @@ ScreenPlayManager::ScreenPlayManager(
|
||||
: QObject { parent }
|
||||
{
|
||||
m_server = std::make_unique<QLocalServer>();
|
||||
|
||||
QObject::connect(m_server.get(), &QLocalServer::newConnection, this, &ScreenPlayManager::newConnection);
|
||||
QObject::connect(&m_screenPlayTimelineManager, &ScreenPlayTimelineManager::requestSaveProfiles, this, &ScreenPlayManager::requestSaveProfiles);
|
||||
m_server->setSocketOptions(QLocalServer::WorldAccessOption);
|
||||
if (!m_server->listen("ScreenPlay")) {
|
||||
qCritical("Could not open Local Socket with the name ScreenPlay!");
|
||||
@ -41,91 +39,30 @@ ScreenPlayManager::ScreenPlayManager(
|
||||
QObject::connect(this, &ScreenPlayManager::requestSaveProfiles, this, [this]() {
|
||||
m_saveLimiter.start();
|
||||
});
|
||||
|
||||
m_contentTimer.setInterval(1000);
|
||||
// Do not start the timer here. This will be done after
|
||||
// we have loaded all timeline wallpaper from the config.json
|
||||
QObject::connect(&m_contentTimer, &QTimer::timeout, this, &ScreenPlayManager::checkActiveWallpaperTimeline);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\brief Checks if we need to display a different wallpaper at the current time.
|
||||
|
||||
CurrentTimeline => Timeline that should currently run, based on start and endtime.
|
||||
ActiveTimeline => Timeline with isActive flag set to true
|
||||
*/
|
||||
void ScreenPlayManager::checkActiveWallpaperTimeline()
|
||||
{
|
||||
std::shared_ptr<WallpaperTimelineSection> currentTimeline = m_screenPlayTimeline.getCurrentTimeline();
|
||||
if (!currentTimeline) {
|
||||
qCritical() << "No active timeline found. There must always be an active timeline.";
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for currently active timeline.
|
||||
std::shared_ptr<WallpaperTimelineSection> activeTimelineSection = nullptr;
|
||||
for (const auto& section : m_screenPlayTimeline.m_wallpaperTimelineSectionsList) {
|
||||
if (section->isActive) {
|
||||
activeTimelineSection = section;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We start the first timeline section,if there is currently no active timeline section.
|
||||
// This happens at every startup.
|
||||
if (!activeTimelineSection) {
|
||||
activateNewTimeline();
|
||||
}
|
||||
|
||||
// If timeline does not match current time, switch to new timeline.
|
||||
if (activeTimelineSection) {
|
||||
if (!activeTimelineSection->containsTime(QTime::currentTime()) || !activeTimelineSection->isActive) {
|
||||
activateNewTimeline();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Change active timeline. We need an extra flags to know if our
|
||||
timeline is active and out of time range.
|
||||
\brief Inits this class instead of init in the constructor. This is because we need to check
|
||||
first if another ScreenPlay instance is running. If it is not the case we call this function.
|
||||
*/
|
||||
void ScreenPlayManager::activateNewTimeline()
|
||||
void ScreenPlayManager::init(
|
||||
const std::shared_ptr<GlobalVariables>& globalVariables,
|
||||
const std::shared_ptr<MonitorListModel>& mlm,
|
||||
const std::shared_ptr<Settings>& settings)
|
||||
{
|
||||
// Remove old timeline content
|
||||
auto oldTimeline = m_screenPlayTimeline.findActiveWallpaperTimelineSection();
|
||||
// Will be null on startup, where there is no old timeline
|
||||
if (oldTimeline) {
|
||||
m_globalVariables = globalVariables;
|
||||
m_monitorListModel = mlm;
|
||||
m_settings = settings;
|
||||
|
||||
oldTimeline->isActive = false;
|
||||
for (auto& activeWallpaper : oldTimeline->activeWallpaperList) {
|
||||
activeWallpaper->close();
|
||||
}
|
||||
// Clear all active wallpaper connections, but do not
|
||||
// clear WallpaperData in case we need it again later
|
||||
oldTimeline->activeWallpaperList.clear();
|
||||
}
|
||||
m_screenPlayTimelineManager.setGlobalVariables(m_globalVariables);
|
||||
m_screenPlayTimelineManager.setSettings(m_settings);
|
||||
|
||||
// Activate new timeline content
|
||||
std::shared_ptr<WallpaperTimelineSection> newTimelineSection = m_screenPlayTimeline.getCurrentTimeline();
|
||||
if (!newTimelineSection) {
|
||||
qCritical() << "No active timeline found. There must always be an active timeline.";
|
||||
return;
|
||||
// Reset to default settings if we are unable to load
|
||||
// the existing one
|
||||
if (!loadProfiles()) {
|
||||
qInfo() << "Reset default profiles.json at:" << m_globalVariables->localSettingsPath();
|
||||
m_settings->writeDefaultProfiles();
|
||||
}
|
||||
newTimelineSection->isActive = true;
|
||||
|
||||
// Activate new wallpaper
|
||||
for (const auto& wallpaper : newTimelineSection->wallpaperData) {
|
||||
auto activeWallpaper = startWallpaper(wallpaper, false);
|
||||
if (!activeWallpaper) {
|
||||
qCritical() << "Unable to start the new wallpaper at timeline:" << newTimelineSection->identifier
|
||||
<< newTimelineSection->startTime << "-" << newTimelineSection->endTime;
|
||||
return;
|
||||
}
|
||||
newTimelineSection->activeWallpaperList.push_back(activeWallpaper);
|
||||
}
|
||||
qInfo() << "Timeline switched successfully.";
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -148,118 +85,22 @@ bool ScreenPlayManager::setWallpaperAtTimelineIndex(
|
||||
wallpaperData.file = file;
|
||||
wallpaperData.monitors = monitorIndex;
|
||||
wallpaperData.fillMode = m_settings->videoFillMode();
|
||||
bool ok = false;
|
||||
for (auto& timelineSection : m_screenPlayTimeline.m_wallpaperTimelineSectionsList) {
|
||||
const bool sameIndex = timelineSection->index == timelineIndex;
|
||||
const bool sameIdentifier = timelineSection->identifier == identifier;
|
||||
if (sameIndex && sameIdentifier) {
|
||||
// TODO support more than one wallpaper per timeline
|
||||
timelineSection->wallpaperData = { wallpaperData };
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ok) {
|
||||
qCritical() << "Invalid sameIdentifier: " << timelineIndex << identifier;
|
||||
const bool success = m_screenPlayTimelineManager.setWallpaperAtTimelineIndex(wallpaperData, timelineIndex, identifier);
|
||||
|
||||
printTimelines();
|
||||
if (!success) {
|
||||
qCritical() << "Invalid timeline index or identifier: " << timelineIndex << identifier;
|
||||
m_screenPlayTimelineManager.printTimelines();
|
||||
emit printQmlTimeline();
|
||||
return false;
|
||||
}
|
||||
|
||||
// We do not start the wallpaper here, but let
|
||||
// ScreenPlayManager::checkActiveWallpaperTimeline decide
|
||||
// ScreenPlayTimelineManager::checkActiveWallpaperTimeline decide
|
||||
// if the wallpaper
|
||||
emit requestSaveProfiles();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Inits this class instead of init in the constructor. This is because we need to check
|
||||
first if another ScreenPlay instance is running. If it is not the case we call this function.
|
||||
*/
|
||||
void ScreenPlayManager::init(
|
||||
const std::shared_ptr<GlobalVariables>& globalVariables,
|
||||
const std::shared_ptr<MonitorListModel>& mlm,
|
||||
const std::shared_ptr<Settings>& settings)
|
||||
{
|
||||
m_globalVariables = globalVariables;
|
||||
m_monitorListModel = mlm;
|
||||
m_settings = settings;
|
||||
|
||||
// Reset to default settings if we are unable to load
|
||||
// the existing one
|
||||
if (!loadProfiles()) {
|
||||
qInfo() << "Reset default profiles.json at:" << m_globalVariables->localSettingsPath();
|
||||
m_settings->writeDefaultProfiles();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Creates a wallpaper with a given \a monitorIndex list, \a a absoluteStoragePath folder,
|
||||
a \a previewImage (relative path to the absoluteStoragePath), a default \a volume,
|
||||
a \a fillMode, a \a type (htmlWallpaper, qmlWallpaper etc.), a \a saveToProfilesConfigFile bool only set to flase
|
||||
if we call the method when using via the settings on startup to skip a unnecessary save.
|
||||
*/
|
||||
std::shared_ptr<ScreenPlayWallpaper> ScreenPlayManager::startWallpaper(
|
||||
WallpaperData wallpaperData,
|
||||
const bool saveToProfilesConfigFile)
|
||||
{
|
||||
|
||||
const int screenCount = QGuiApplication::screens().count();
|
||||
|
||||
QJsonArray monitors;
|
||||
for (const int index : wallpaperData.monitors) {
|
||||
monitors.append(index);
|
||||
if (index > screenCount - 1) {
|
||||
qWarning() << "Configuration contains invalid monitor with index: " << index << " screen count: " << screenCount;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
auto saveToProfile = qScopeGuard([=, this] {
|
||||
// Do not save on app start
|
||||
if (saveToProfilesConfigFile) {
|
||||
emit requestSaveProfiles();
|
||||
}
|
||||
});
|
||||
|
||||
// Remove file:///
|
||||
wallpaperData.absolutePath = QUrl::fromUserInput(wallpaperData.absolutePath).toLocalFile();
|
||||
const QString appID = Util().generateRandomString();
|
||||
qInfo() << "Start wallpaper" << wallpaperData.absolutePath << appID;
|
||||
|
||||
// Only support remove wallpaper that spans over 1 monitor
|
||||
// if (wallpaperData.monitors.length() == 1) {
|
||||
// int i = 0;
|
||||
// for (auto& wallpaper : m_screenPlayWallpapers) {
|
||||
// if (wallpaper->monitors().length() == 1) {
|
||||
// if (monitors.at(0) == wallpaper->monitors().at(0)) {
|
||||
// return wallpaper->replace(
|
||||
// wallpaperData,
|
||||
// m_settings->checkWallpaperVisible());
|
||||
// m_monitorListModel->setWallpaperMonitor(wallpaper, wallpaperData.monitors);
|
||||
// }
|
||||
// }
|
||||
// i++;
|
||||
// }
|
||||
// }
|
||||
|
||||
auto wallpaper = std::make_shared<ScreenPlayWallpaper>(
|
||||
m_globalVariables,
|
||||
appID,
|
||||
wallpaperData,
|
||||
m_settings);
|
||||
|
||||
QObject::connect(wallpaper.get(), &ScreenPlayWallpaper::requestSave, this, &ScreenPlayManager::requestSaveProfiles);
|
||||
QObject::connect(wallpaper.get(), &ScreenPlayWallpaper::requestClose, this, &ScreenPlayManager::removeWallpaper);
|
||||
QObject::connect(wallpaper.get(), &ScreenPlayWallpaper::error, this, &ScreenPlayManager::displayErrorPopup);
|
||||
if (!wallpaper->start()) {
|
||||
return nullptr;
|
||||
}
|
||||
// m_monitorListModel->setWallpaperMonitor(wallpaper, wallpaperData.monitors);
|
||||
return wallpaper;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Creates a ScreenPlayWidget object via a \a absoluteStoragePath and a \a preview image (relative path).
|
||||
*/
|
||||
@ -311,30 +152,30 @@ bool ScreenPlayManager::startWidget(
|
||||
*/
|
||||
bool ScreenPlayManager::removeAllWallpapers(bool saveToProfile)
|
||||
{
|
||||
// TODO
|
||||
// if (m_screenPlayTimelineManager.m_wallpaperTimelineSectionsList.empty()) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
if (m_screenPlayTimeline.m_wallpaperTimelineSectionsList.empty()) {
|
||||
return false;
|
||||
}
|
||||
// QStringList appIDs;
|
||||
// auto activeTimelineSection = m_screenPlayTimelineManager.findActiveWallpaperTimelineSection();
|
||||
// if (!activeTimelineSection) {
|
||||
// qWarning() << "Trying to remove all Wallpapers while findActiveSection is empty.";
|
||||
// return false;
|
||||
// }
|
||||
// // Do not remove items from the vector you iterate on.
|
||||
// for (auto& client : activeTimelineSection->activeWallpaperList) {
|
||||
// appIDs.append(client->appID());
|
||||
// }
|
||||
|
||||
QStringList appIDs;
|
||||
auto activeTimelineSection = m_screenPlayTimeline.findActiveWallpaperTimelineSection();
|
||||
if (!activeTimelineSection) {
|
||||
qWarning() << "Trying to remove all Wallpapers while findActiveSection is empty.";
|
||||
return false;
|
||||
}
|
||||
// Do not remove items from the vector you iterate on.
|
||||
for (auto& client : activeTimelineSection->activeWallpaperList) {
|
||||
appIDs.append(client->appID());
|
||||
}
|
||||
// for (const auto& appID : appIDs) {
|
||||
// if (!removeWallpaper(appID)) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
for (const auto& appID : appIDs) {
|
||||
if (!removeWallpaper(appID)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (saveToProfile)
|
||||
emit requestSaveProfiles();
|
||||
// if (saveToProfile)
|
||||
// emit requestSaveProfiles();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -390,7 +231,7 @@ bool ScreenPlayManager::removeWallpaperAt(int index)
|
||||
*/
|
||||
bool ScreenPlayManager::requestProjectSettingsAtMonitorIndex(const int index)
|
||||
{
|
||||
auto activeTimelineSection = m_screenPlayTimeline.findActiveWallpaperTimelineSection();
|
||||
auto activeTimelineSection = m_screenPlayTimelineManager.findActiveWallpaperTimelineSection();
|
||||
if (!activeTimelineSection) {
|
||||
return false;
|
||||
}
|
||||
@ -440,7 +281,7 @@ bool ScreenPlayManager::setWallpaperFillModeAtMonitorIndex(const int index, cons
|
||||
*/
|
||||
bool ScreenPlayManager::setAllWallpaperValue(const QString& key, const QString& value)
|
||||
{
|
||||
auto activeTimelineSection = m_screenPlayTimeline.findActiveWallpaperTimelineSection();
|
||||
auto activeTimelineSection = m_screenPlayTimelineManager.findActiveWallpaperTimelineSection();
|
||||
if (!activeTimelineSection) {
|
||||
return false;
|
||||
}
|
||||
@ -458,7 +299,7 @@ bool ScreenPlayManager::setAllWallpaperValue(const QString& key, const QString&
|
||||
ScreenPlayWallpaper* ScreenPlayManager::getWallpaperByAppID(const QString& appID)
|
||||
{
|
||||
|
||||
auto activeTimelineSection = m_screenPlayTimeline.findActiveWallpaperTimelineSection();
|
||||
auto activeTimelineSection = m_screenPlayTimelineManager.findActiveWallpaperTimelineSection();
|
||||
if (!activeTimelineSection) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -476,273 +317,40 @@ ScreenPlayWallpaper* ScreenPlayManager::getWallpaperByAppID(const QString& appID
|
||||
*/
|
||||
bool ScreenPlayManager::moveTimelineAt(const int index, const QString identifier, const float relativePosition, QString positionTimeString)
|
||||
{
|
||||
m_contentTimer.stop();
|
||||
auto updateTimer = qScopeGuard([this] { m_contentTimer.start(); });
|
||||
|
||||
auto& wallpapterTimelineSection = m_screenPlayTimeline.m_wallpaperTimelineSectionsList.at(index);
|
||||
QTime newPositionTime = QTime::fromString(positionTimeString, "hh:mm");
|
||||
if (!newPositionTime.isValid()) {
|
||||
qWarning() << "Unable to move with invalid time:" << positionTimeString;
|
||||
return false;
|
||||
}
|
||||
wallpapterTimelineSection->endTime = newPositionTime;
|
||||
wallpapterTimelineSection->relativePosition = relativePosition;
|
||||
// We set the identifier here, because we generate it in qml
|
||||
// The identiefier is only used for debugging
|
||||
wallpapterTimelineSection->identifier = identifier;
|
||||
|
||||
const auto timelineCount = m_screenPlayTimeline.m_wallpaperTimelineSectionsList.size();
|
||||
// Only update the next timeline startTime
|
||||
// if we are not end last wallpaper, that always
|
||||
// must end at 24:00
|
||||
if (index <= timelineCount) {
|
||||
auto& wallpapterTimelineSectionNext = m_screenPlayTimeline.m_wallpaperTimelineSectionsList.at(index + 1);
|
||||
wallpapterTimelineSectionNext->startTime = newPositionTime;
|
||||
}
|
||||
|
||||
printTimelines();
|
||||
emit requestSaveProfiles();
|
||||
return true;
|
||||
return m_screenPlayTimelineManager.moveTimelineAt(index, identifier, relativePosition, positionTimeString);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Converts a range from 0.0f - 1.0f to 00:00:00 0 23:59:59
|
||||
*/
|
||||
QString ScreenPlayManager::getTimeString(double relativeLinePosition)
|
||||
{
|
||||
if (relativeLinePosition == 1.0) {
|
||||
// We overwrite the endTime here
|
||||
return "23:59:59";
|
||||
}
|
||||
const double totalHours = relativeLinePosition * 24;
|
||||
int hours = static_cast<int>(std::floor(totalHours)); // Gets the whole hour part
|
||||
double fractionalHours = totalHours - hours;
|
||||
int minutes = static_cast<int>(std::floor(fractionalHours * 60)); // Calculates the minutes
|
||||
double fractionalMinutes = fractionalHours * 60 - minutes;
|
||||
int seconds = static_cast<int>(std::round(fractionalMinutes * 60)); // Calculates the seconds
|
||||
|
||||
// Adjust minutes and seconds if seconds rolled over to 60
|
||||
if (seconds == 60) {
|
||||
seconds = 0;
|
||||
minutes += 1;
|
||||
}
|
||||
|
||||
// Adjust hours and minutes if minutes rolled over to 60
|
||||
if (minutes == 60) {
|
||||
minutes = 0;
|
||||
hours += 1;
|
||||
}
|
||||
|
||||
// Ensure hours wrap correctly at 24
|
||||
if (hours == 24) {
|
||||
hours = 0;
|
||||
}
|
||||
|
||||
// Format the output to "HH:MM:SS"
|
||||
return QString("%1:%2:%3").arg(hours, 2, 10, QChar('0')).arg(minutes, 2, 10, QChar('0')).arg(seconds, 2, 10, QChar('0'));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Update m_screenPlayTimeline.m_wallpaperTimelineSectionsList index based on the startTime;
|
||||
*/
|
||||
void ScreenPlayManager::updateIndices()
|
||||
{
|
||||
// Sort the vector based on startTime
|
||||
std::sort(m_screenPlayTimeline.m_wallpaperTimelineSectionsList.begin(), m_screenPlayTimeline.m_wallpaperTimelineSectionsList.end(),
|
||||
[](const auto& a, const auto& b) {
|
||||
return a->startTime < b->startTime;
|
||||
});
|
||||
|
||||
// Update the indices based on new order
|
||||
for (int i = 0; i < m_screenPlayTimeline.m_wallpaperTimelineSectionsList.size(); ++i) {
|
||||
m_screenPlayTimeline.m_wallpaperTimelineSectionsList[i]->index = i;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Adds a new timeline at relative position. We always shrink the timeline at the input
|
||||
position and append the new one to the left. There must always (lightning) an active
|
||||
timeline section.
|
||||
|
||||
*/
|
||||
bool ScreenPlayManager::addTimelineAt(const int index, const float reltiaveLinePosition, QString identifier)
|
||||
{
|
||||
|
||||
m_contentTimer.stop();
|
||||
auto updateTimer = qScopeGuard([this] { m_contentTimer.start(); });
|
||||
|
||||
// We always get the new endTime
|
||||
const QString newStopPosition = getTimeString(reltiaveLinePosition);
|
||||
QTime newStopPositionTime = QTime::fromString(newStopPosition, m_screenPlayTimeline.m_timelineTimeFormat);
|
||||
if (!newStopPositionTime.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// IMPORTANT: The new element is always on the left. The first
|
||||
// handle always persists because the
|
||||
// user can never delete it. It only gets "pushed" further
|
||||
// to the right, by increasing the size.
|
||||
|
||||
// | Insert here
|
||||
// ˇ
|
||||
// |-----------------------------------------------|
|
||||
// 0 ID: AAA
|
||||
//
|
||||
//
|
||||
// |-----------------------|-----------------------|
|
||||
// 0 ID: BBB 1 - ID: AAA
|
||||
// We directly get the new index of 0 in this example from qml
|
||||
|
||||
auto newTimelineSection = std::make_shared<WallpaperTimelineSection>();
|
||||
newTimelineSection->index = index;
|
||||
newTimelineSection->identifier = identifier;
|
||||
newTimelineSection->endTime = newStopPositionTime;
|
||||
// In case we do a full reset, we must set the start time manually
|
||||
if (m_screenPlayTimeline.m_wallpaperTimelineSectionsList.empty()) {
|
||||
newTimelineSection->startTime = QTime::fromString("00:00:00", m_screenPlayTimeline.m_timelineTimeFormat);
|
||||
} else {
|
||||
|
||||
// We can use the given index here, because it points
|
||||
// the the current item at that index, and we have not yet
|
||||
// added our new timelineSection to our list.
|
||||
newTimelineSection->startTime = m_screenPlayTimeline.m_wallpaperTimelineSectionsList.at(index)->startTime;
|
||||
}
|
||||
|
||||
const bool isLast = (m_screenPlayTimeline.m_wallpaperTimelineSectionsList.length() - 1) == index;
|
||||
if (isLast) {
|
||||
m_screenPlayTimeline.m_wallpaperTimelineSectionsList.last()->startTime = newTimelineSection->endTime;
|
||||
}
|
||||
|
||||
m_screenPlayTimeline.m_wallpaperTimelineSectionsList.append(newTimelineSection);
|
||||
|
||||
updateIndices();
|
||||
printTimelines();
|
||||
emit requestSaveProfiles();
|
||||
return true;
|
||||
const bool success = m_screenPlayTimelineManager.addTimelineAt(index, reltiaveLinePosition, identifier);
|
||||
return success;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Qml function that removes all Timeline sections. Qml then creates
|
||||
a new default section.
|
||||
*/
|
||||
void ScreenPlayManager::removeAllTimlineSections()
|
||||
QCoro::QmlTask ScreenPlayManager::removeAllTimlineSections()
|
||||
{
|
||||
m_contentTimer.stop();
|
||||
auto updateTimer = qScopeGuard([this] { m_contentTimer.start(); });
|
||||
|
||||
// First check if there is any active wallpaper that we save in
|
||||
// this shared ptr. We can have many timlines, but the current timeline
|
||||
// can have no active wallpaper
|
||||
|
||||
auto activeTimelineSection = m_screenPlayTimeline.findActiveWallpaperTimelineSection();
|
||||
if (!activeTimelineSection) {
|
||||
qCritical() << "There must always be (lightning) an active timline";
|
||||
return;
|
||||
}
|
||||
|
||||
if (activeTimelineSection) {
|
||||
// Close the localsocket
|
||||
activeTimelineSection->close();
|
||||
// Reset all active wallpaper
|
||||
activeTimelineSection.reset();
|
||||
}
|
||||
|
||||
m_screenPlayTimeline.m_wallpaperTimelineSectionsList.clear();
|
||||
removeAllWallpapers();
|
||||
removeAllWidgets();
|
||||
// Do not call requestSaveProfiles, because qml will add
|
||||
// the default timeline after this function
|
||||
return QCoro::QmlTask([this]() -> QCoro::Task<Result> {
|
||||
// call with coro
|
||||
const bool success = co_await m_screenPlayTimelineManager.removeAllTimlineSections();
|
||||
qDebug() << "Task: removeAllTimlineSections" << success;
|
||||
// emit requestSaveProfiles();
|
||||
// removeAllWallpapers();
|
||||
co_return Result { success };
|
||||
}());
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Removes a timeline at a given index. Expands the timeline next to it
|
||||
to fill the space.
|
||||
*/
|
||||
bool ScreenPlayManager::removeTimelineAt(const int index)
|
||||
{
|
||||
printTimelines();
|
||||
const auto timelineCount = m_screenPlayTimeline.m_wallpaperTimelineSectionsList.size();
|
||||
if (timelineCount == 0) {
|
||||
qCritical() << "Timeline empty";
|
||||
return false;
|
||||
}
|
||||
if (timelineCount == 1) {
|
||||
qCritical() << "Timeline must always have at least one element, that span across the whole timeline from 00:00:00 to 23:59:59.";
|
||||
return false;
|
||||
}
|
||||
m_contentTimer.stop();
|
||||
auto updateTimer = qScopeGuard([this] { m_contentTimer.start(); });
|
||||
|
||||
auto& wallpapterTimelineSection = m_screenPlayTimeline.m_wallpaperTimelineSectionsList.at(index);
|
||||
|
||||
// When we have two timelines, we know that only the first
|
||||
// timeline can be removed and the second one will then span
|
||||
// across the whole timeline
|
||||
// remove <- expand
|
||||
// |-----------|-----------|
|
||||
// 0 1
|
||||
if (timelineCount == 2) {
|
||||
if (index != 0) {
|
||||
qCritical() << "Removing the last timeline is not allowed. This must always span the whole timeline";
|
||||
return false;
|
||||
}
|
||||
m_screenPlayTimeline.m_wallpaperTimelineSectionsList.removeAt(index);
|
||||
m_screenPlayTimeline.m_wallpaperTimelineSectionsList.first()->startTime = QTime::fromString("00:00:00", m_screenPlayTimeline.m_timelineTimeFormat);
|
||||
updateIndices();
|
||||
printTimelines();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Now handle all states where we have more than two wallpaper
|
||||
// There is no timeline before if we want to remove
|
||||
// the timeline at index 0. We do not need to make the same
|
||||
// check for the timelineAfter, because the last timeline
|
||||
// cannot be deleted
|
||||
QTime endTime;
|
||||
if (index == 0) {
|
||||
endTime = QTime::fromString("00:00:00", m_screenPlayTimeline.m_timelineTimeFormat);
|
||||
} else {
|
||||
endTime = m_screenPlayTimeline.m_wallpaperTimelineSectionsList.at(index - 1)->endTime;
|
||||
}
|
||||
auto timelineAfter = m_screenPlayTimeline.m_wallpaperTimelineSectionsList.at(index + 1);
|
||||
// before remove <- expand
|
||||
// |-----------|-----------|-----------|
|
||||
// 0 1 2
|
||||
// Now when removing timeline at index 1, the next (after)
|
||||
// wallpaper gets the remaining space
|
||||
timelineAfter->startTime = endTime;
|
||||
m_screenPlayTimeline.m_wallpaperTimelineSectionsList.removeAt(index);
|
||||
updateIndices();
|
||||
printTimelines();
|
||||
|
||||
const bool success = m_screenPlayTimelineManager.removeTimelineAt(index);
|
||||
emit requestSaveProfiles();
|
||||
return true;
|
||||
return success;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Print to check if our qml data matches our c++.
|
||||
*/
|
||||
void ScreenPlayManager::printTimelines()
|
||||
{
|
||||
std::cout << "#############################\n";
|
||||
for (auto& timeline : m_screenPlayTimeline.m_wallpaperTimelineSectionsList) {
|
||||
std::cout << timeline->index << ": " << timeline->identifier.toStdString() << "\t"
|
||||
<< timeline->relativePosition
|
||||
<< " start: " << timeline->startTime.toString().toStdString()
|
||||
<< " end: " << timeline->endTime.toString().toStdString() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Qml function to build our timeline on creation in qml.
|
||||
*/
|
||||
QJsonArray ScreenPlayManager::initialSectionsList()
|
||||
{
|
||||
QJsonArray sectionPositions;
|
||||
for (const auto& timelineSection : m_screenPlayTimeline.m_wallpaperTimelineSectionsList) {
|
||||
sectionPositions.push_back(timelineSection->serialize());
|
||||
}
|
||||
return sectionPositions;
|
||||
return m_screenPlayTimelineManager.initialSectionsList();
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -775,7 +383,7 @@ void ScreenPlayManager::newConnection()
|
||||
return;
|
||||
}
|
||||
|
||||
auto activeTimelineSection = m_screenPlayTimeline.findActiveWallpaperTimelineSection();
|
||||
auto activeTimelineSection = m_screenPlayTimelineManager.findActiveWallpaperTimelineSection();
|
||||
if (!activeTimelineSection) {
|
||||
return;
|
||||
}
|
||||
@ -829,7 +437,7 @@ void ScreenPlayManager::setActiveWidgetsCounter(int activeWidgetsCounter)
|
||||
bool ScreenPlayManager::removeWallpaper(const QString& appID)
|
||||
{
|
||||
|
||||
auto wallpaperSectionOpt = m_screenPlayTimeline.activeWallpaperSectionByAppID(appID);
|
||||
auto wallpaperSectionOpt = m_screenPlayTimelineManager.activeWallpaperSectionByAppID(appID);
|
||||
if (!wallpaperSectionOpt.has_value()) {
|
||||
qCritical() << "No wallpaper found.";
|
||||
return false;
|
||||
@ -908,7 +516,7 @@ bool ScreenPlayManager::removeWidget(const QString& appID)
|
||||
*/
|
||||
bool ScreenPlayManager::setWallpaperValue(const QString& appID, const QString& key, const QString& value)
|
||||
{
|
||||
std::shared_ptr<WallpaperTimelineSection> activeTimelineSection = m_screenPlayTimeline.findActiveWallpaperTimelineSection();
|
||||
std::shared_ptr<WallpaperTimelineSection> activeTimelineSection = m_screenPlayTimelineManager.findActiveWallpaperTimelineSection();
|
||||
if (!activeTimelineSection) {
|
||||
qCritical() << "setWallpaperValue failed, because no active timeline section was found";
|
||||
return false;
|
||||
@ -931,20 +539,7 @@ bool ScreenPlayManager::saveProfiles()
|
||||
{
|
||||
m_saveLimiter.stop();
|
||||
|
||||
QJsonArray timelineWallpaperList {};
|
||||
for (const auto& activeTimelineWallpaper : std::as_const(m_screenPlayTimeline.m_wallpaperTimelineSectionsList)) {
|
||||
QJsonObject timelineWallpaper;
|
||||
timelineWallpaper.insert("startTime", activeTimelineWallpaper->startTime.toString());
|
||||
timelineWallpaper.insert("endTime", activeTimelineWallpaper->endTime.toString());
|
||||
QJsonArray wallpaper;
|
||||
// Every timeline section can have multiple wallpaper
|
||||
for (const auto& wallpaperData : activeTimelineWallpaper->wallpaperData) {
|
||||
wallpaper.append(wallpaperData.serialize());
|
||||
}
|
||||
timelineWallpaper.insert("wallpaper", wallpaper);
|
||||
|
||||
timelineWallpaperList.append(timelineWallpaper);
|
||||
}
|
||||
QJsonArray timelineWallpaperList = m_screenPlayTimelineManager.timelineWallpaperList();
|
||||
|
||||
QJsonArray widgetList {};
|
||||
for (const auto& activeWidget : std::as_const(m_screenPlayWidgets)) {
|
||||
@ -1007,21 +602,10 @@ bool ScreenPlayManager::loadProfiles()
|
||||
|
||||
for (QJsonValueRef timelineWallpaper : wallpaper.toObject().value("timelineWallpaper").toArray()) {
|
||||
QJsonObject wallpaperObj = timelineWallpaper.toObject();
|
||||
std::optional<std::shared_ptr<WallpaperTimelineSection>> wallpaperDataOpt = m_screenPlayTimeline.loadTimelineWallpaperConfig(wallpaperObj);
|
||||
if (!wallpaperDataOpt.has_value()) {
|
||||
containsInvalidData = true;
|
||||
break;
|
||||
if (!m_screenPlayTimelineManager.addTimelineFromSettings(wallpaperObj)) {
|
||||
qCritical() << "Unable to add wallpaper timeline";
|
||||
continue;
|
||||
}
|
||||
|
||||
std::shared_ptr<WallpaperTimelineSection> wallpaperData = wallpaperDataOpt.value();
|
||||
wallpaperData->index = m_screenPlayTimeline.m_wallpaperTimelineSectionsList.length();
|
||||
wallpaperData->identifier = m_util.generateRandomString(4);
|
||||
|
||||
qInfo() << wallpaperData->index
|
||||
<< wallpaperData->startTime
|
||||
<< wallpaperData->endTime;
|
||||
|
||||
m_screenPlayTimeline.m_wallpaperTimelineSectionsList.append(wallpaperDataOpt.value());
|
||||
}
|
||||
|
||||
for (const QJsonValueRef widget : wallpaper.toObject().value("widgets").toArray()) {
|
||||
@ -1037,30 +621,11 @@ bool ScreenPlayManager::loadProfiles()
|
||||
if (containsInvalidData)
|
||||
saveProfiles();
|
||||
|
||||
activateNewTimeline();
|
||||
m_contentTimer.start();
|
||||
m_screenPlayTimelineManager.startupFirstTimeline();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScreenPlayManager::updateQmlTimelines()
|
||||
{
|
||||
QVariantList data;
|
||||
for (const auto& timelineSection : m_screenPlayTimeline.m_wallpaperTimelineSectionsList) {
|
||||
if (timelineSection->wallpaperData.empty())
|
||||
continue;
|
||||
|
||||
// We just use the frist one
|
||||
const auto& wp = timelineSection->wallpaperData.front();
|
||||
data.append(QVariant::fromValue(wp.previewImage));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\brief Loads a widget from C:\Users\XXX\AppData\Local\ScreenPlay\ScreenPlay\profiles.json
|
||||
*/
|
||||
|
@ -1,106 +0,0 @@
|
||||
#include "screenplaytimeline.h"
|
||||
#include "ScreenPlay/screenplaywallpaper.h"
|
||||
#include "ScreenPlay/wallpaperdata.h"
|
||||
|
||||
namespace ScreenPlay {
|
||||
/*!
|
||||
* \brief Calculates the relative position of a given time within a day.
|
||||
* * This function takes a QTime object representing the end time and calculates its
|
||||
* position relative to a fixed start and end time on the same day. The relative position
|
||||
* is a normalized value between 0 and 1, rounded to four decimal places.
|
||||
* * \param endTime The time for which to calculate the relative position.
|
||||
* \return A float representing the normalized relative position of endTime, rounded to four decimal places.
|
||||
*/
|
||||
float ScreenPlayTimeline::calculateRelativePosition(const QTime &endTime)
|
||||
{
|
||||
QTime startTime(0, 0, 0); // Start of the day
|
||||
QTime maxTime(23, 59, 59); // End of the day range
|
||||
|
||||
// Total number of seconds from startTime to maxTime
|
||||
int totalSeconds = startTime.secsTo(maxTime);
|
||||
|
||||
// Seconds from startTime to the given endTime
|
||||
int endTimeSeconds = startTime.secsTo(endTime);
|
||||
|
||||
// Calculate the relative position
|
||||
float relativePosition = static_cast<float>(endTimeSeconds) / totalSeconds;
|
||||
|
||||
// Round to four decimal places
|
||||
return qRound(relativePosition * 10000.0) / 10000.0;
|
||||
}
|
||||
|
||||
std::optional<std::shared_ptr<ScreenPlay::WallpaperTimelineSection> > ScreenPlay::ScreenPlayTimeline::loadTimelineWallpaperConfig(const QJsonObject &timelineObj)
|
||||
{
|
||||
const QTime startTime = QTime::fromString(timelineObj.value("startTime").toString(), m_timelineTimeFormat);
|
||||
const QTime endTime = QTime::fromString(timelineObj.value("endTime").toString(), m_timelineTimeFormat);
|
||||
if (startTime > endTime) {
|
||||
qCritical() << "Invalid time, start time is later than end time: " << startTime.toString() << endTime.toString();
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// TODO check license
|
||||
auto timelineSection = std::make_shared<WallpaperTimelineSection>();
|
||||
timelineSection->startTime = startTime;
|
||||
timelineSection->endTime = endTime;
|
||||
timelineSection->relativePosition = calculateRelativePosition(endTime);
|
||||
const auto wallpaperList = timelineObj.value("wallpaper").toArray();
|
||||
for (auto& wallpaper : wallpaperList) {
|
||||
std::optional<WallpaperData> wallpaperDataOpt = WallpaperData::loadWallpaperConfig(wallpaper.toObject());
|
||||
if (!wallpaperDataOpt.has_value())
|
||||
return std::nullopt;
|
||||
timelineSection->wallpaperData.push_back(wallpaperDataOpt.value());
|
||||
}
|
||||
return timelineSection;
|
||||
}
|
||||
/*!
|
||||
\brief Parses one timeline wallpaper:
|
||||
|
||||
"timelineWallpaper": [
|
||||
{
|
||||
"endTime": "08:32:00",
|
||||
"startTime": "00:00:00",
|
||||
"wallpaper": [
|
||||
[...]
|
||||
]
|
||||
},
|
||||
*/
|
||||
std::shared_ptr<WallpaperTimelineSection> ScreenPlayTimeline::findActiveWallpaperTimelineSection()
|
||||
{
|
||||
for (const auto& section : m_wallpaperTimelineSectionsList) {
|
||||
if (section->isActive) {
|
||||
return section;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
/*!
|
||||
\brief Returns the wallpaper timeline that has the isActive
|
||||
flag enabled.
|
||||
*/
|
||||
std::optional<std::shared_ptr<WallpaperTimelineSection> > ScreenPlayTimeline::activeWallpaperSectionByAppID(const QString &appID)
|
||||
{
|
||||
for (const auto& section : m_wallpaperTimelineSectionsList) {
|
||||
for (const auto& wallpaper : section->activeWallpaperList) {
|
||||
if(wallpaper->appID() == appID)
|
||||
return section;
|
||||
}
|
||||
}
|
||||
qCritical() << "No matching appID for:"<< appID;
|
||||
return nullptr;
|
||||
}
|
||||
/*!
|
||||
\brief Returns the current active timline. There must always be an active timeline!
|
||||
*/
|
||||
std::shared_ptr<WallpaperTimelineSection> ScreenPlayTimeline::getCurrentTimeline()
|
||||
{
|
||||
const QTime currentTime = QTime::currentTime();
|
||||
for (const auto& section : m_wallpaperTimelineSectionsList) {
|
||||
if (section->containsTime(currentTime)) {
|
||||
return section;
|
||||
}
|
||||
}
|
||||
qCritical() << "No active timeline";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
469
ScreenPlay/src/screenplaytimelinemanager.cpp
Normal file
469
ScreenPlay/src/screenplaytimelinemanager.cpp
Normal file
@ -0,0 +1,469 @@
|
||||
#include "ScreenPlay/screenplaytimelinemanager.h"
|
||||
#include "ScreenPlay/screenplaywallpaper.h"
|
||||
#include "ScreenPlay/wallpaperdata.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <iostream>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
/*!
|
||||
* \brief Calculates the relative position of a given time within a day.
|
||||
* * This function takes a QTime object representing the end time and calculates its
|
||||
* position relative to a fixed start and end time on the same day. The relative position
|
||||
* is a normalized value between 0 and 1, rounded to four decimal places.
|
||||
* * \param endTime The time for which to calculate the relative position.
|
||||
* \return A float representing the normalized relative position of endTime, rounded to four decimal places.
|
||||
*/
|
||||
ScreenPlayTimelineManager::ScreenPlayTimelineManager(
|
||||
QObject* parent)
|
||||
: QObject { parent }
|
||||
{
|
||||
// Do not start the timer here. This will be done after
|
||||
// we have loaded all timeline wallpaper from the config.json
|
||||
QObject::connect(&m_contentTimer, &QTimer::timeout, this, &ScreenPlayTimelineManager::checkActiveWallpaperTimeline);
|
||||
m_contentTimer.start(1000);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Parses one timeline wallpaper:
|
||||
|
||||
"timelineWallpaper": [
|
||||
{
|
||||
"endTime": "08:32:00",
|
||||
"startTime": "00:00:00",
|
||||
"wallpaper": [
|
||||
[...]
|
||||
]
|
||||
},
|
||||
*/
|
||||
std::shared_ptr<WallpaperTimelineSection> ScreenPlayTimelineManager::findActiveWallpaperTimelineSection()
|
||||
{
|
||||
for (const auto& section : m_wallpaperTimelineSectionsList) {
|
||||
if (section->status == WallpaperTimelineSection::Status::Active) {
|
||||
return section;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
/*!
|
||||
\brief Returns the wallpaper timeline that has the isActive
|
||||
flag enabled.
|
||||
*/
|
||||
std::optional<std::shared_ptr<WallpaperTimelineSection>> ScreenPlayTimelineManager::activeWallpaperSectionByAppID(const QString& appID)
|
||||
{
|
||||
for (const auto& section : m_wallpaperTimelineSectionsList) {
|
||||
for (const auto& wallpaper : section->activeWallpaperList) {
|
||||
if(wallpaper->appID() == appID)
|
||||
return section;
|
||||
}
|
||||
}
|
||||
qCritical() << "No matching appID for:"<< appID;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Returns the current active timline. There must always be an active timeline!
|
||||
*/
|
||||
std::shared_ptr<WallpaperTimelineSection> ScreenPlayTimelineManager::findTimelineForCurrentTime()
|
||||
{
|
||||
const QTime currentTime = QTime::currentTime();
|
||||
for (const auto& section : m_wallpaperTimelineSectionsList) {
|
||||
if (section->containsTime(currentTime)) {
|
||||
return section;
|
||||
}
|
||||
}
|
||||
qCritical() << "No active timeline";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Loads all timelines.
|
||||
*/
|
||||
bool ScreenPlayTimelineManager::addTimelineFromSettings(const QJsonObject& timelineObj)
|
||||
{
|
||||
const QTime startTime = QTime::fromString(timelineObj.value("startTime").toString(), m_timelineTimeFormat);
|
||||
const QTime endTime = QTime::fromString(timelineObj.value("endTime").toString(), m_timelineTimeFormat);
|
||||
if (startTime > endTime) {
|
||||
qCritical() << "Invalid time, start time is later than end time: " << startTime.toString() << endTime.toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO check license
|
||||
auto timelineSection = std::make_shared<WallpaperTimelineSection>();
|
||||
QObject::connect(timelineSection.get(), &WallpaperTimelineSection::requestSaveProfiles, this, &ScreenPlayTimelineManager::requestSaveProfiles);
|
||||
timelineSection->startTime = startTime;
|
||||
timelineSection->endTime = endTime;
|
||||
timelineSection->settings = m_settings;
|
||||
timelineSection->globalVariables = m_globalVariables;
|
||||
timelineSection->relativePosition = Util().calculateRelativePosition(endTime);
|
||||
const auto wallpaperList = timelineObj.value("wallpaper").toArray();
|
||||
for (auto& wallpaper : wallpaperList) {
|
||||
std::optional<WallpaperData> wallpaperDataOpt = WallpaperData::loadWallpaperConfig(wallpaper.toObject());
|
||||
if (!wallpaperDataOpt.has_value())
|
||||
return false;
|
||||
timelineSection->wallpaperDataList.push_back(wallpaperDataOpt.value());
|
||||
}
|
||||
|
||||
// Todo: Should we use addTimelineAt?
|
||||
timelineSection->index = m_wallpaperTimelineSectionsList.length();
|
||||
timelineSection->identifier = Util().generateRandomString(4);
|
||||
|
||||
qInfo() << timelineSection->index
|
||||
<< timelineSection->startTime
|
||||
<< timelineSection->endTime;
|
||||
|
||||
// Todo: Should we use addTimelineAt?
|
||||
m_wallpaperTimelineSectionsList.append(timelineSection);
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief We always handle the endTimeString, because it is the handle for the
|
||||
timeline. The last, default, timeline does not have a handle.
|
||||
*/
|
||||
bool ScreenPlayTimelineManager::moveTimelineAt(const int index, const QString identifier, const float relativePosition, QString positionTimeString)
|
||||
{
|
||||
m_contentTimer.stop();
|
||||
auto updateTimer = qScopeGuard([this] { m_contentTimer.start(); });
|
||||
|
||||
auto& wallpapterTimelineSection = m_wallpaperTimelineSectionsList.at(index);
|
||||
QTime newPositionTime = QTime::fromString(positionTimeString, "hh:mm");
|
||||
if (!newPositionTime.isValid()) {
|
||||
qWarning() << "Unable to move with invalid time:" << positionTimeString;
|
||||
return false;
|
||||
}
|
||||
wallpapterTimelineSection->endTime = newPositionTime;
|
||||
wallpapterTimelineSection->relativePosition = relativePosition;
|
||||
// We set the identifier here, because we generate it in qml
|
||||
// The identiefier is only used for debugging
|
||||
wallpapterTimelineSection->identifier = identifier;
|
||||
|
||||
const auto timelineCount = m_wallpaperTimelineSectionsList.size();
|
||||
// Only update the next timeline startTime
|
||||
// if we are not end last wallpaper, that always
|
||||
// must end at 24:00
|
||||
if (index <= timelineCount) {
|
||||
auto& wallpapterTimelineSectionNext = m_wallpaperTimelineSectionsList.at(index + 1);
|
||||
wallpapterTimelineSectionNext->startTime = newPositionTime;
|
||||
}
|
||||
|
||||
// printTimelines();
|
||||
emit requestSaveProfiles();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Checks if we need to display a different wallpaper at the current time.
|
||||
*/
|
||||
void ScreenPlayTimelineManager::checkActiveWallpaperTimeline()
|
||||
{
|
||||
// Current timeline with the state active
|
||||
std::shared_ptr<WallpaperTimelineSection> activeTimeline = findActiveWallpaperTimelineSection();
|
||||
|
||||
if (!activeTimeline) {
|
||||
std::shared_ptr<WallpaperTimelineSection> currentTimeline = findTimelineForCurrentTime();
|
||||
currentTimeline->activateTimeline();
|
||||
return;
|
||||
}
|
||||
// Current timline that should be active, based on the current time
|
||||
std::shared_ptr<WallpaperTimelineSection> currentTimeline = findTimelineForCurrentTime();
|
||||
if (!currentTimeline) {
|
||||
qCritical() << "No current timeline found. There must always be an active timeline.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentTimeline != activeTimeline) {
|
||||
activeTimeline->deactivateTimeline();
|
||||
currentTimeline->activateTimeline();
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenPlayTimelineManager::setSettings(const std::shared_ptr<Settings>& settings)
|
||||
{
|
||||
m_settings = settings;
|
||||
}
|
||||
|
||||
void ScreenPlayTimelineManager::startupFirstTimeline()
|
||||
{
|
||||
std::shared_ptr<WallpaperTimelineSection> currentTimeline = findTimelineForCurrentTime();
|
||||
if (!currentTimeline) {
|
||||
qCritical() << "No current timeline found. There must always be an active timeline.";
|
||||
return;
|
||||
}
|
||||
currentTimeline->activateTimeline();
|
||||
}
|
||||
|
||||
void ScreenPlayTimelineManager::setGlobalVariables(const std::shared_ptr<GlobalVariables>& globalVariables)
|
||||
{
|
||||
m_globalVariables = globalVariables;
|
||||
}
|
||||
|
||||
bool ScreenPlayTimelineManager::deactivateCurrentTimeline()
|
||||
{
|
||||
auto oldTimeline = findActiveWallpaperTimelineSection();
|
||||
if (!oldTimeline) {
|
||||
qCritical() << "No active timeline found. There must always be an active timeline.";
|
||||
return false;
|
||||
}
|
||||
oldTimeline->deactivateTimeline();
|
||||
return true;
|
||||
}
|
||||
/*!
|
||||
\brief Change active timeline. We need an extra flags to know if our
|
||||
timeline is active and out of time range.
|
||||
*/
|
||||
bool ScreenPlayTimelineManager::startTimeline()
|
||||
{
|
||||
|
||||
std::shared_ptr<WallpaperTimelineSection> newTimelineSection = findTimelineForCurrentTime();
|
||||
if (!newTimelineSection) {
|
||||
qCritical() << "No new timeline found. There must always be an active timeline.";
|
||||
return false;
|
||||
}
|
||||
if (!newTimelineSection->activateTimeline()) {
|
||||
qCritical() << "Unable activate timeline.";
|
||||
return false;
|
||||
}
|
||||
|
||||
qInfo() << "Timeline switched successfully.";
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Update m_wallpaperTimelineSectionsList index based on the startTime;
|
||||
*/
|
||||
void ScreenPlayTimelineManager::updateIndices()
|
||||
{
|
||||
// Sort the vector based on startTime
|
||||
std::sort(m_wallpaperTimelineSectionsList.begin(), m_wallpaperTimelineSectionsList.end(),
|
||||
[](const auto& a, const auto& b) {
|
||||
return a->startTime < b->startTime;
|
||||
});
|
||||
|
||||
// Update the indices based on new order
|
||||
for (int i = 0; i < m_wallpaperTimelineSectionsList.size(); ++i) {
|
||||
m_wallpaperTimelineSectionsList[i]->index = i;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Adds a new timeline at relative position. We always shrink the timeline at the input
|
||||
position and append the new one to the left. There must always (lightning) an active
|
||||
timeline section.
|
||||
|
||||
*/
|
||||
bool ScreenPlayTimelineManager::addTimelineAt(const int index, const float reltiaveLinePosition, QString identifier)
|
||||
{
|
||||
// We always get the new endTime
|
||||
const QString newStopPosition = Util().getTimeString(reltiaveLinePosition);
|
||||
QTime newStopPositionTime = QTime::fromString(newStopPosition, m_timelineTimeFormat);
|
||||
if (!newStopPositionTime.isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// IMPORTANT: The new element is always on the left. The first
|
||||
// handle always persists because the
|
||||
// user can never delete it. It only gets "pushed" further
|
||||
// to the right, by increasing the size.
|
||||
|
||||
// | Insert here
|
||||
// ˇ
|
||||
// |-----------------------------------------------|
|
||||
// 0 ID: AAA
|
||||
//
|
||||
//
|
||||
// |-----------------------|-----------------------|
|
||||
// 0 ID: BBB 1 - ID: AAA
|
||||
// We directly get the new index of 0 in this example from qml
|
||||
|
||||
auto newTimelineSection = std::make_shared<WallpaperTimelineSection>();
|
||||
QObject::connect(newTimelineSection.get(), &WallpaperTimelineSection::requestSaveProfiles, this, &ScreenPlayTimelineManager::requestSaveProfiles);
|
||||
newTimelineSection->settings = m_settings;
|
||||
newTimelineSection->globalVariables = m_globalVariables;
|
||||
newTimelineSection->index = index;
|
||||
newTimelineSection->identifier = identifier;
|
||||
newTimelineSection->endTime = newStopPositionTime;
|
||||
// In case we do a full reset, we must set the start time manually
|
||||
if (m_wallpaperTimelineSectionsList.empty()) {
|
||||
newTimelineSection->startTime = QTime::fromString("00:00:00", m_timelineTimeFormat);
|
||||
} else {
|
||||
|
||||
// We can use the given index here, because it points
|
||||
// the the current item at that index, and we have not yet
|
||||
// added our new timelineSection to our list.
|
||||
newTimelineSection->startTime = m_wallpaperTimelineSectionsList.at(index)->startTime;
|
||||
}
|
||||
|
||||
const bool isLast = (m_wallpaperTimelineSectionsList.length() - 1) == index;
|
||||
if (isLast) {
|
||||
m_wallpaperTimelineSectionsList.last()->startTime = newTimelineSection->endTime;
|
||||
}
|
||||
|
||||
m_wallpaperTimelineSectionsList.append(newTimelineSection);
|
||||
|
||||
updateIndices();
|
||||
printTimelines();
|
||||
emit requestSaveProfiles();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Qml function that removes all Timeline sections. Qml then creates
|
||||
a new default section.
|
||||
*/
|
||||
QCoro::Task<bool> ScreenPlayTimelineManager::removeAllTimlineSections()
|
||||
{
|
||||
|
||||
// First check if there is any active wallpaper and disable it
|
||||
auto activeTimelineSection = findActiveWallpaperTimelineSection();
|
||||
if (activeTimelineSection) {
|
||||
// First deactivate so the wallpaper has time to shutdown
|
||||
co_await activeTimelineSection->deactivateTimeline();
|
||||
}
|
||||
|
||||
// After we have disconnected or timed out we remove the wallpaper
|
||||
m_wallpaperTimelineSectionsList.clear();
|
||||
|
||||
// Do not call requestSaveProfiles, because qml will add
|
||||
// the default timeline after this function
|
||||
co_return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Removes a timeline at a given index. Expands the timeline next to it
|
||||
to fill the space.
|
||||
*/
|
||||
bool ScreenPlayTimelineManager::removeTimelineAt(const int index)
|
||||
{
|
||||
printTimelines();
|
||||
const auto timelineCount = m_wallpaperTimelineSectionsList.size();
|
||||
if (timelineCount == 0) {
|
||||
qCritical() << "Timeline empty";
|
||||
return false;
|
||||
}
|
||||
if (timelineCount == 1) {
|
||||
qCritical() << "Timeline must always have at least one element, that span across the whole timeline from 00:00:00 to 23:59:59.";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto& wallpapterTimelineSection = m_wallpaperTimelineSectionsList.at(index);
|
||||
|
||||
// When we have two timelines, we know that only the first
|
||||
// timeline can be removed and the second one will then span
|
||||
// across the whole timeline
|
||||
// remove <- expand
|
||||
// |-----------|-----------|
|
||||
// 0 1
|
||||
if (timelineCount == 2) {
|
||||
if (index != 0) {
|
||||
qCritical() << "Removing the last timeline is not allowed. This must always span the whole timeline";
|
||||
return false;
|
||||
}
|
||||
m_wallpaperTimelineSectionsList.removeAt(index);
|
||||
m_wallpaperTimelineSectionsList.first()->startTime = QTime::fromString("00:00:00", m_timelineTimeFormat);
|
||||
updateIndices();
|
||||
printTimelines();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Now handle all states where we have more than two wallpaper
|
||||
// There is no timeline before if we want to remove
|
||||
// the timeline at index 0. We do not need to make the same
|
||||
// check for the timelineAfter, because the last timeline
|
||||
// cannot be deleted
|
||||
QTime endTime;
|
||||
if (index == 0) {
|
||||
endTime = QTime::fromString("00:00:00", m_timelineTimeFormat);
|
||||
} else {
|
||||
endTime = m_wallpaperTimelineSectionsList.at(index - 1)->endTime;
|
||||
}
|
||||
auto timelineAfter = m_wallpaperTimelineSectionsList.at(index + 1);
|
||||
// before remove <- expand
|
||||
// |-----------|-----------|-----------|
|
||||
// 0 1 2
|
||||
// Now when removing timeline at index 1, the next (after)
|
||||
// wallpaper gets the remaining space
|
||||
timelineAfter->startTime = endTime;
|
||||
m_wallpaperTimelineSectionsList.removeAt(index);
|
||||
updateIndices();
|
||||
printTimelines();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScreenPlayTimelineManager::printTimelines()
|
||||
{
|
||||
std::cout << "#############################\n";
|
||||
for (auto& timeline : m_wallpaperTimelineSectionsList) {
|
||||
std::cout << timeline->index << ": " << timeline->identifier.toStdString() << "\t"
|
||||
<< timeline->relativePosition
|
||||
<< " start: " << timeline->startTime.toString().toStdString()
|
||||
<< " end: " << timeline->endTime.toString().toStdString() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool ScreenPlayTimelineManager::setWallpaperAtTimelineIndex(WallpaperData wallpaperData, const int timelineIndex, const QString& identifier)
|
||||
{
|
||||
bool found = false;
|
||||
for (auto& timelineSection : m_wallpaperTimelineSectionsList) {
|
||||
const bool sameIndex = timelineSection->index == timelineIndex;
|
||||
const bool sameIdentifier = timelineSection->identifier == identifier;
|
||||
if (sameIndex && sameIdentifier) {
|
||||
found = true;
|
||||
|
||||
// Check if we already have a wallpaper at the same position or on one or more of the specified monitors
|
||||
auto it = std::find_if(timelineSection->wallpaperDataList.begin(), timelineSection->wallpaperDataList.end(),
|
||||
[&wallpaperData](const WallpaperData& existingWallpaper) {
|
||||
return std::any_of(wallpaperData.monitors.begin(), wallpaperData.monitors.end(),
|
||||
[&existingWallpaper](int monitor) {
|
||||
return existingWallpaper.monitors.contains(monitor);
|
||||
});
|
||||
});
|
||||
|
||||
if (it != timelineSection->wallpaperDataList.end()) {
|
||||
// Overwrite the existing wallpaper
|
||||
*it = wallpaperData;
|
||||
} else {
|
||||
// Append the new wallpaper data
|
||||
timelineSection->wallpaperDataList.push_back(wallpaperData);
|
||||
// Start all wallpaper
|
||||
timelineSection->activateTimeline();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
QJsonArray ScreenPlayTimelineManager::initialSectionsList()
|
||||
{
|
||||
QJsonArray sectionPositions;
|
||||
for (const auto& timelineSection : m_wallpaperTimelineSectionsList) {
|
||||
sectionPositions.push_back(timelineSection->serialize());
|
||||
}
|
||||
return sectionPositions;
|
||||
}
|
||||
|
||||
QJsonArray ScreenPlayTimelineManager::timelineWallpaperList()
|
||||
{
|
||||
QJsonArray timelineWallpaperList {};
|
||||
for (const auto& activeTimelineWallpaper : std::as_const(m_wallpaperTimelineSectionsList)) {
|
||||
QJsonObject timelineWallpaper;
|
||||
timelineWallpaper.insert("startTime", activeTimelineWallpaper->startTime.toString());
|
||||
timelineWallpaper.insert("endTime", activeTimelineWallpaper->endTime.toString());
|
||||
QJsonArray wallpaper;
|
||||
// Every timeline section can have multiple wallpaper
|
||||
for (const auto& wallpaperData : activeTimelineWallpaper->wallpaperDataList) {
|
||||
wallpaper.append(wallpaperData.serialize());
|
||||
}
|
||||
timelineWallpaper.insert("wallpaper", wallpaper);
|
||||
|
||||
timelineWallpaperList.append(timelineWallpaper);
|
||||
}
|
||||
return timelineWallpaperList;
|
||||
}
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only
|
||||
#include "ScreenPlay/screenplaywallpaper.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
|
||||
#include "util.h"
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFileInfoList>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
@ -259,7 +262,7 @@ void ScreenPlayWallpaper::setSDKConnection(std::unique_ptr<SDKConnection> connec
|
||||
std::optional<bool> running = m_processManager.isRunning(m_processID);
|
||||
|
||||
if (running.has_value()) {
|
||||
// qInfo() << "running:" << running.value();
|
||||
qInfo() << "running:" << running.value();
|
||||
} else {
|
||||
qInfo() << "INVALID PID:" << m_processID;
|
||||
}
|
||||
|
@ -1,5 +1,9 @@
|
||||
// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only
|
||||
#include "ScreenPlay/screenplaywidget.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
@ -115,7 +119,7 @@ void ScreenPlayWidget::setSDKConnection(std::unique_ptr<SDKConnection> connectio
|
||||
std::optional<bool> running = m_processManager.isRunning(m_processID);
|
||||
|
||||
if (running.has_value()) {
|
||||
qInfo() << "running:" << running.value();
|
||||
// qInfo() << "running:" << running.value();
|
||||
} else {
|
||||
qInfo() << "INVALID PID:" << m_processID;
|
||||
}
|
||||
|
@ -1,5 +1,13 @@
|
||||
// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only
|
||||
#include "ScreenPlay/sdkconnection.h"
|
||||
#include "ScreenPlay/globalvariables.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonValue>
|
||||
#include <QLocalServer>
|
||||
#include <QTimer>
|
||||
#include <QWebSocketServer>
|
||||
|
||||
namespace ScreenPlay {
|
||||
|
||||
@ -90,7 +98,7 @@ void ScreenPlay::SDKConnection::readyRead()
|
||||
emit jsonMessageReceived(doc.object());
|
||||
|
||||
} else {
|
||||
qInfo() << "### Message from: " << m_appID << ": " << msg;
|
||||
// qInfo() << "### Message from: " << m_appID << ": " << msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,33 @@
|
||||
// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only
|
||||
#include "ScreenPlay/settings.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
#include <QFileInfo>
|
||||
#include <QSysInfo>
|
||||
|
||||
#include "ScreenPlay/CMakeVariables.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QDomDocument>
|
||||
#include <QDomElement>
|
||||
#include <QDomNodeList>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QFontDatabase>
|
||||
#include <QGuiApplication>
|
||||
#include <QIODevice>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QPair>
|
||||
#include <QProcess>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QQmlPropertyMap>
|
||||
#include <QStandardPaths>
|
||||
#include <QSysInfo>
|
||||
#include <QTextStream>
|
||||
#include <QThread>
|
||||
#include <QUrl>
|
||||
#include <QVector>
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <QtGlobal>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <qt_windows.h>
|
||||
|
@ -1,10 +1,147 @@
|
||||
#include "wallpapertimelinesection.h"
|
||||
#include "ScreenPlay/wallpapertimelinesection.h"
|
||||
#include "ScreenPlay/screenplaywallpaper.h"
|
||||
#include "ScreenPlay/wallpaperdata.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFileInfoList>
|
||||
#include <QGuiApplication>
|
||||
#include <QObject>
|
||||
|
||||
bool ScreenPlay::WallpaperTimelineSection::close(){
|
||||
for (auto& wallpaper : activeWallpaperList) {
|
||||
wallpaper->close();
|
||||
namespace ScreenPlay {
|
||||
|
||||
bool WallpaperTimelineSection::containsTime(const QTime& time) const
|
||||
{
|
||||
if (endTime < startTime) { // Timeline spans midnight
|
||||
return (time >= startTime || time < endTime);
|
||||
} else {
|
||||
return (time >= startTime && time < endTime);
|
||||
}
|
||||
}
|
||||
|
||||
QJsonObject WallpaperTimelineSection::serialize() const
|
||||
{
|
||||
QJsonObject data;
|
||||
data.insert("identifier", identifier);
|
||||
data.insert("index", index);
|
||||
data.insert("relativePosition", relativePosition);
|
||||
data.insert("startTime", startTime.toString());
|
||||
data.insert("endTime", endTime.toString());
|
||||
|
||||
// Serialize vector<WallpaperData>
|
||||
QJsonArray wallpaperDataArray;
|
||||
for (const auto& wallpaper : wallpaperDataList) {
|
||||
QJsonObject wallpaperObject = wallpaper.serialize(); // Assuming WallpaperData has a serialize method
|
||||
wallpaperDataArray.append(wallpaperObject);
|
||||
}
|
||||
data.insert("wallpaperData", wallpaperDataArray);
|
||||
|
||||
// Serialize vector<std::shared_ptr<ScreenPlayWallpaper>>
|
||||
// QJsonArray activeWallpaperArray;
|
||||
// for (const auto& wallpaper : activeWallpaperList) {
|
||||
// QJsonObject wallpaperObject = wallpaper->serialize(); // Assuming ScreenPlayWallpaper has a serialize method
|
||||
// activeWallpaperArray.append(wallpaperObject);
|
||||
// }
|
||||
// data.insert("activeWallpaperList", activeWallpaperArray);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
// Start all ScreenPlayWallpaper processes of this current timeline
|
||||
bool WallpaperTimelineSection::activateTimeline()
|
||||
{
|
||||
status = Status::Active;
|
||||
// TODO: this can be called if the timeline is already active.
|
||||
// Add a check to only launch new
|
||||
for (auto& wallpaperData : wallpaperDataList) {
|
||||
|
||||
const int screenCount = QGuiApplication::screens().count();
|
||||
|
||||
QJsonArray monitors;
|
||||
for (const int index : wallpaperData.monitors) {
|
||||
monitors.append(index);
|
||||
if (index > screenCount - 1) {
|
||||
qWarning() << "Configuration contains invalid monitor with index: " << index << " screen count: " << screenCount;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove file:///
|
||||
wallpaperData.absolutePath = QUrl::fromUserInput(wallpaperData.absolutePath).toLocalFile();
|
||||
const QString appID = Util().generateRandomString();
|
||||
qInfo() << "Start wallpaper" << wallpaperData.absolutePath << appID;
|
||||
|
||||
// Only support remove wallpaper that spans over 1 monitor
|
||||
// if (wallpaper.monitors.length() == 1) {
|
||||
// int i = 0;
|
||||
// for (auto& wallpaper : m_screenPlayWallpapers) {
|
||||
// if (wallpaper->monitors().length() == 1) {
|
||||
// if (monitors.at(0) == wallpaper->monitors().at(0)) {
|
||||
// return wallpaper->replace(
|
||||
// wallpaper,
|
||||
// settings->checkWallpaperVisible());
|
||||
// m_monitorListModel->setWallpaperMonitor(wallpaper, wallpaper.monitors);
|
||||
// }
|
||||
// }
|
||||
// i++;
|
||||
// }
|
||||
// }
|
||||
|
||||
auto screenPlayWallpaper = std::make_shared<ScreenPlayWallpaper>(
|
||||
globalVariables,
|
||||
appID,
|
||||
wallpaperData,
|
||||
settings);
|
||||
|
||||
QObject::connect(screenPlayWallpaper.get(), &ScreenPlayWallpaper::requestSave, this, [this]() {
|
||||
// &ScreenPlayManager::requestSaveProfiles
|
||||
emit requestSaveProfiles();
|
||||
});
|
||||
QObject::connect(screenPlayWallpaper.get(), &ScreenPlayWallpaper::requestClose, this, []() {
|
||||
// , &ScreenPlayManager::removeWallpaper);
|
||||
});
|
||||
|
||||
// QObject::connect(screenPlayWallpaper.get(), &ScreenPlayWallpaper::error, this, this, []() {
|
||||
// // , &ScreenPlayManager::displayErrorPopup);
|
||||
// });
|
||||
if (!screenPlayWallpaper->start()) {
|
||||
return false;
|
||||
}
|
||||
// m_monitorListModel->setWallpaperMonitor(wallpaper, wallpaperData.monitors);
|
||||
activeWallpaperList.push_back(screenPlayWallpaper);
|
||||
}
|
||||
activeWallpaperList.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
QCoro::Task<bool> WallpaperTimelineSection::deactivateTimeline()
|
||||
{
|
||||
|
||||
status = Status::Closing;
|
||||
for (auto& activeWallpaper : activeWallpaperList) {
|
||||
activeWallpaper->close();
|
||||
}
|
||||
QTimer timer;
|
||||
timer.start(250);
|
||||
const int maxRetries = 30;
|
||||
for (int i = 1; i <= maxRetries; ++i) {
|
||||
// Wait for the timer to tick
|
||||
co_await timer;
|
||||
bool wallpaperStillActive = false;
|
||||
for (auto& activeWallpaper : activeWallpaperList) {
|
||||
if (activeWallpaper->isConnected()) {
|
||||
wallpaperStillActive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!wallpaperStillActive) {
|
||||
status = Status::Inactive;
|
||||
// Clear all active wallpaper connections, but do not
|
||||
// clear WallpaperData in case we need it again later
|
||||
activeWallpaperList.clear();
|
||||
co_return true;
|
||||
}
|
||||
}
|
||||
co_return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,23 @@
|
||||
// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only
|
||||
#include "ScreenPlay/wizards.h"
|
||||
#include "ScreenPlay/CMakeVariables.h"
|
||||
#include "ScreenPlayUtil/util.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QFont>
|
||||
#include <QFutureWatcher>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonParseError>
|
||||
#include <QLinearGradient>
|
||||
#include <QPainter>
|
||||
#include <QTextOption>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
#include <QtMath>
|
||||
|
||||
namespace ScreenPlay {
|
||||
/*!
|
||||
|
@ -134,6 +134,7 @@ public:
|
||||
Q_INVOKABLE void requestAllLicenses();
|
||||
Q_INVOKABLE void requestDataProtection();
|
||||
Q_INVOKABLE bool fileExists(const QString& filePath) const;
|
||||
Q_INVOKABLE float calculateRelativePosition(const QTime& endTime) const;
|
||||
|
||||
Q_INVOKABLE void setNavigation(QString nav)
|
||||
{
|
||||
@ -151,6 +152,11 @@ public:
|
||||
emit requestToggleWallpaperConfiguration();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Converts a range from 0.0f - 1.0f to 00:00:00 0 23:59:59
|
||||
*/
|
||||
Q_INVOKABLE QString getTimeString(double relativeLinePosition);
|
||||
|
||||
signals:
|
||||
void extractionProgressChanged(QString file, int proc, int total, qint64 br, qint64 bt);
|
||||
void extractionFinished();
|
||||
|
@ -608,6 +608,58 @@ bool Util::fileExists(const QString& filePath) const
|
||||
return file.isFile();
|
||||
}
|
||||
|
||||
float Util::calculateRelativePosition(const QTime& endTime) const
|
||||
{
|
||||
QTime startTime(0, 0, 0); // Start of the day
|
||||
QTime maxTime(23, 59, 59); // End of the day range
|
||||
|
||||
// Total number of seconds from startTime to maxTime
|
||||
int totalSeconds = startTime.secsTo(maxTime);
|
||||
|
||||
// Seconds from startTime to the given endTime
|
||||
int endTimeSeconds = startTime.secsTo(endTime);
|
||||
|
||||
// Calculate the relative position
|
||||
float relativePosition = static_cast<float>(endTimeSeconds) / totalSeconds;
|
||||
|
||||
// Round to four decimal places
|
||||
return qRound(relativePosition * 10000.0) / 10000.0;
|
||||
}
|
||||
|
||||
QString Util::getTimeString(double relativeLinePosition)
|
||||
{
|
||||
if (relativeLinePosition == 1.0) {
|
||||
// We overwrite the endTime here
|
||||
return "23:59:59";
|
||||
}
|
||||
const double totalHours = relativeLinePosition * 24;
|
||||
int hours = static_cast<int>(std::floor(totalHours)); // Gets the whole hour part
|
||||
double fractionalHours = totalHours - hours;
|
||||
int minutes = static_cast<int>(std::floor(fractionalHours * 60)); // Calculates the minutes
|
||||
double fractionalMinutes = fractionalHours * 60 - minutes;
|
||||
int seconds = static_cast<int>(std::round(fractionalMinutes * 60)); // Calculates the seconds
|
||||
|
||||
// Adjust minutes and seconds if seconds rolled over to 60
|
||||
if (seconds == 60) {
|
||||
seconds = 0;
|
||||
minutes += 1;
|
||||
}
|
||||
|
||||
// Adjust hours and minutes if minutes rolled over to 60
|
||||
if (minutes == 60) {
|
||||
minutes = 0;
|
||||
hours += 1;
|
||||
}
|
||||
|
||||
// Ensure hours wrap correctly at 24
|
||||
if (hours == 24) {
|
||||
hours = 0;
|
||||
}
|
||||
|
||||
// Format the output to "HH:MM:SS"
|
||||
return QString("%1:%2:%3").arg(hours, 2, 10, QChar('0')).arg(minutes, 2, 10, QChar('0')).arg(seconds, 2, 10, QChar('0'));
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Takes reference to \a obj. If the copy of the thumbnail is successful,
|
||||
it adds the corresponding settings entry to the json object reference.
|
||||
|
124
Tools/pre-commit/ollama_code_review.py
Normal file
124
Tools/pre-commit/ollama_code_review.py
Normal file
@ -0,0 +1,124 @@
|
||||
# File: Tools/pre-commit/ollama_code_review.py
|
||||
|
||||
import sys
|
||||
import asyncio
|
||||
import subprocess
|
||||
import re
|
||||
from typing import Optional, Sequence, List, Tuple
|
||||
from ollama import AsyncClient
|
||||
|
||||
MODEL_NAME = 'glm4' # You can change this to any model you prefer
|
||||
ANALYSIS_TIMEOUT = 60 # Timeout in seconds for each file analysis
|
||||
|
||||
def get_git_staged_diff() -> str:
|
||||
"""Get the git diff of staged changes."""
|
||||
try:
|
||||
result = subprocess.run(['git', 'diff', '--cached'], capture_output=True, text=True, check=True)
|
||||
return result.stdout
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error getting git diff: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
def parse_git_diff(diff: str) -> List[Tuple[str, str]]:
|
||||
"""Parse git diff and return a list of (filename, file_diff) tuples."""
|
||||
file_diffs = []
|
||||
current_file = None
|
||||
current_diff = []
|
||||
|
||||
for line in diff.split('\n'):
|
||||
if line.startswith('diff --git'):
|
||||
if current_file:
|
||||
file_diffs.append((current_file, '\n'.join(current_diff)))
|
||||
current_file = re.search(r'b/(.+)$', line).group(1)
|
||||
current_diff = [line]
|
||||
elif current_file:
|
||||
current_diff.append(line)
|
||||
|
||||
if current_file:
|
||||
file_diffs.append((current_file, '\n'.join(current_diff)))
|
||||
|
||||
return file_diffs
|
||||
|
||||
|
||||
async def analyze_file_with_ollama(filename: str, file_diff: str) -> None:
|
||||
"""Send a single file diff to Ollama for analysis and stream the response."""
|
||||
prompt = f"""
|
||||
Analyze the following git diff for the file '{filename}'.
|
||||
|
||||
Focus only on:
|
||||
1. Copy-paste errors: Look for actual repeated code blocks or patterns that suggest copy-pasting, ignoring the '+' and '-' at the start of lines.
|
||||
2. Spelling issues: Identify any misspelled words or typos in comments and strings. Ignore variable names, function names, and other code identifiers.
|
||||
|
||||
Use the following emoji system to indicate the severity of issues:
|
||||
🟢 - No issues found
|
||||
🟡 - Minor issues (e.g., a few typos or small repeated code segments)
|
||||
🔴 - Significant issues (e.g., large blocks of copied code or numerous spelling errors)
|
||||
|
||||
Start your response with one of these emojis to indicate the overall status.
|
||||
Then provide a concise summary of findings, if any. If no issues are found, just state that.
|
||||
|
||||
Git diff for {filename}:
|
||||
{file_diff}
|
||||
"""
|
||||
|
||||
try:
|
||||
client = AsyncClient()
|
||||
print(f"\nAnalyzing {file_diff}:")
|
||||
|
||||
full_response = []
|
||||
async def process_stream():
|
||||
async for response in await client.generate(model=MODEL_NAME, prompt=prompt, stream=True):
|
||||
chunk = response['response']
|
||||
full_response.append(chunk)
|
||||
print(chunk, end='', flush=True)
|
||||
|
||||
await asyncio.wait_for(process_stream(), timeout=ANALYSIS_TIMEOUT)
|
||||
print() # New line after complete response
|
||||
except asyncio.TimeoutError:
|
||||
print(f"\nAnalysis for {filename} timed out after {ANALYSIS_TIMEOUT} seconds.")
|
||||
except Exception as e:
|
||||
print(f"\nError communicating with Ollama for {filename}: {e}")
|
||||
|
||||
async def check_and_pull_model() -> bool:
|
||||
"""Check if the model exists, and pull it if it doesn't."""
|
||||
client = AsyncClient()
|
||||
try:
|
||||
# Check if the model exists
|
||||
models = await client.list()
|
||||
if MODEL_NAME not in [model['name'] for model in models['models']]:
|
||||
print(f"Model '{MODEL_NAME}' not found. Pulling it now...")
|
||||
await client.pull(model=MODEL_NAME)
|
||||
print(f"Model '{MODEL_NAME}' has been pulled successfully.")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error checking or pulling the model: {e}")
|
||||
return False
|
||||
|
||||
async def main(argv: Optional[Sequence[str]] = None) -> int:
|
||||
# First, check and pull the model if necessary
|
||||
if not await check_and_pull_model():
|
||||
print("Failed to ensure the model is available. Exiting.")
|
||||
return 1
|
||||
|
||||
full_diff = get_git_staged_diff()
|
||||
if not full_diff:
|
||||
print("No staged changes to analyze.")
|
||||
return 0
|
||||
|
||||
file_diffs = parse_git_diff(full_diff)
|
||||
|
||||
for filename, file_diff in file_diffs:
|
||||
await analyze_file_with_ollama(filename, file_diff)
|
||||
|
||||
# Ask user if they want to proceed with the commit
|
||||
while True:
|
||||
answer = input("\nDo you want to proceed with the commit? (y/n): ").lower()
|
||||
if answer in ['y', 'yes']:
|
||||
return 0 # Proceed with commit
|
||||
elif answer in ['n', 'no']:
|
||||
return 1 # Abort commit
|
||||
else:
|
||||
print("Please answer 'y' or 'n'.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(asyncio.run(main()))
|
Loading…
Reference in New Issue
Block a user