GitLab Commit is coming up on August 3-4. Learn how to innovate together using GitLab, the DevOps platform. Register for free: gitlabcommitvirtual2021.com

Commit 9e95b402 authored by Elias Steurer's avatar Elias Steurer 🇪🇺
Browse files

Refactor install list QML & C++

Move right click popup out of _every_ ScreenPlayItem.
This was a hughe performance hit.

Change (and rename) enum InstalledRole to  enum class ScreenPlayItem
parent 1d11f697
......@@ -76,10 +76,11 @@ Item {
id: gridView
boundsBehavior: Flickable.DragOverBounds
maximumFlickVelocity: 2500
flickDeceleration: 2500
flickDeceleration: 500
anchors.fill: parent
cellWidth: 340
cellHeight: 200
cacheBuffer: 160
interactive: pageInstalled.enabled
anchors {
topMargin: 0
......@@ -178,20 +179,70 @@ Item {
delegate: ScreenPlayItem {
id: delegate
focus: true
customTitle: screenTitle
type: screenType
screenId: screenFolderId
absoluteStoragePath: screenAbsoluteStoragePath
workshopID: screenWorkshopID
customTitle: m_title
type: m_type
screenId: m_folderId
absoluteStoragePath: m_absoluteStoragePath
workshopID: m_workshopID
itemIndex: index
}
onOpenContextMenu: {
// Set the menu to the current item informations
contextMenu.workshopID = delegate.workshopID
contextMenu.absoluteStoragePath = delegate.absoluteStoragePath
const pos = delegate.mapToItem(pageInstalled, position.x,
position.y)
contextMenu.popup(pos.x, pos.y)
}
}
ScrollBar.vertical: ScrollBar {
snapMode: ScrollBar.SnapOnRelease
}
}
Menu {
id: contextMenu
property int workshopID: 0
property url absoluteStoragePath
MenuItem {
text: qsTr("Open containing folder")
icon.source: "qrc:/assets/icons/icon_folder_open.svg"
onClicked: {
ScreenPlay.util.openFolderInExplorer(contextMenu.absoluteStoragePath)
}
}
MenuItem {
text: qsTr("Deinstall Item")
icon.source: "qrc:/assets/icons/icon_delete.svg"
enabled: contextMenu.workshopID === 0
onClicked: {
deleteDialog.open()
}
}
MenuItem {
id: miWorkshop
text: qsTr("Open workshop Page")
enabled: contextMenu.workshopID !== 0
icon.source: "qrc:/assets/icons/icon_steam.svg"
onClicked: {
Qt.openUrlExternally(
"steam://url/CommunityFilePage/" + workshopID)
}
}
}
Dialog {
id: deleteDialog
title: "Are you sure you want to delete this item?"
standardButtons: Dialog.Ok | Dialog.Cancel
modal: true
dim: true
anchors.centerIn: Overlay.overlay
onAccepted: ScreenPlay.installedListModel.deinstallItemAt(
screenPlayItem.itemIndex)
}
Navigation {
id: navWrapper
height: 115
......
......@@ -6,7 +6,7 @@ import ScreenPlay 1.0
import ScreenPlay.Enums.InstalledType 1.0
Item {
id: screenPlayItem
id: root
width: 320
height: 180
opacity: 0
......@@ -14,11 +14,12 @@ Item {
property string customTitle: "name here"
property url absoluteStoragePath
property var type
property bool hasMenuOpen: false
property int workshopID: 0
property int itemIndex
property string screenId: ""
signal openContextMenu(point position)
onTypeChanged: {
switch (type) {
case InstalledType.Unknown:
......@@ -35,6 +36,7 @@ Item {
return
}
}
Timer {
id: timerAnim
interval: {
......@@ -46,7 +48,6 @@ Item {
}
running: true
repeat: false
onTriggered: showAnim.start()
}
......@@ -84,7 +85,7 @@ Item {
property: "angle"
}
PropertyAnimation {
target: screenPlayItem
target: root
from: 0
to: 1
duration: 800
......@@ -123,6 +124,7 @@ Item {
spread: 0.2
color: "black"
opacity: 0.4
cornerRadius: 15
}
......@@ -135,7 +137,7 @@ Item {
Image {
id: mask
source: "qrc:/assets/images/Window.svg"
sourceSize: Qt.size(screenPlayItem.width, screenPlayItem.height)
sourceSize: Qt.size(root.width, root.height)
visible: false
smooth: true
fillMode: Image.PreserveAspectFit
......@@ -149,16 +151,9 @@ Item {
ScreenPlayItemImage {
id: screenPlayItemImage
anchors.fill: parent
sourceImage: Qt.resolvedUrl(
screenPlayItem.absoluteStoragePath + "/" + screenPreview)
sourceImageGIF: {
if (screenPreviewGIF === undefined) {
return ""
} else {
return Qt.resolvedUrl(
screenPlayItem.absoluteStoragePath + "/" + screenPreviewGIF)
}
}
sourceImage: m_preview
sourceImageGIF: m_previewGIF
absoluteStoragePath: m_absoluteStoragePath
}
Image {
......@@ -198,71 +193,25 @@ Item {
cursorShape: Qt.PointingHandCursor
acceptedButtons: Qt.LeftButton | Qt.RightButton
onEntered: {
if (!hasMenuOpen) {
screenPlayItem.state = "hover"
screenPlayItemImage.state = "hover"
screenPlayItemImage.enter()
}
root.state = "hover"
screenPlayItemImage.state = "hover"
screenPlayItemImage.enter()
}
onExited: {
if (!hasMenuOpen) {
screenPlayItem.state = ""
screenPlayItemImage.state = "loaded"
screenPlayItemImage.exit()
}
root.state = ""
screenPlayItemImage.state = "loaded"
screenPlayItemImage.exit()
}
onClicked: {
if (mouse.button === Qt.LeftButton) {
ScreenPlay.util.setSidebarItem(screenPlayItem.screenId,
screenPlayItem.type)
ScreenPlay.util.setSidebarItem(root.screenId, root.type)
} else if (mouse.button === Qt.RightButton) {
contextMenu.popup()
hasMenuOpen = true
root.openContextMenu(Qt.point(mouseX, mouseY))
}
}
}
}
Menu {
id: contextMenu
onClosed: hasMenuOpen = false
MenuItem {
text: qsTr("Open containing folder")
icon.source: "qrc:/assets/icons/icon_folder_open.svg"
onClicked: {
ScreenPlay.util.openFolderInExplorer(absoluteStoragePath)
}
}
MenuItem {
text: qsTr("Deinstall Item")
icon.source: "qrc:/assets/icons/icon_delete.svg"
enabled: screenPlayItem.workshopID === 0
onClicked: {
deleteDialog.open()
}
}
MenuItem {
id: miWorkshop
text: qsTr("Open workshop Page")
enabled: screenPlayItem.workshopID !== 0
icon.source: "qrc:/assets/icons/icon_steam.svg"
onClicked: {
Qt.openUrlExternally(
"steam://url/CommunityFilePage/" + workshopID)
}
}
}
Dialog {
id: deleteDialog
title: "Are you sure you want to delete this item?"
standardButtons: Dialog.Ok | Dialog.Cancel
modal: true
dim: true
anchors.centerIn: Overlay.overlay
onAccepted: ScreenPlay.installedListModel.deinstallItemAt(
screenPlayItem.itemIndex)
}
}
states: [
......
import QtQuick 2.12
Item {
id: screenPlayItemImage
id: root
width: 320
height: 121
state: "loading"
property string sourceImage: ""
property string sourceImageGIF: ""
property string absoluteStoragePath
property string sourceImage
property string sourceImageGIF
function enter() {
if (screenPlayItemImage.sourceImageGIF != "") {
imgGIFPreview.playing = true
imgGIFPreview.source = screenPlayItemImage.sourceImageGIF.trim()
imgGIFPreview.enabled = true
if (root.sourceImageGIF != "") {
loader_imgGIFPreview.sourceComponent = component_imgGIFPreview
}
}
function exit() {
imgGIFPreview.playing = false
root.state = "loaded"
loader_imgGIFPreview.sourceComponent = null
}
Image {
......@@ -27,26 +27,36 @@ Item {
asynchronous: true
cache: true
fillMode: Image.PreserveAspectCrop
source: screenPlayItemImage.sourceImage.trim()
source: root.screenPreview
=== "" ? "qrc:/assets/images/missingPreview.png" : Qt.resolvedUrl(
absoluteStoragePath + "/" + root.sourceImage)
onStatusChanged: {
if (image.status === Image.Ready) {
screenPlayItemImage.state = "loaded"
root.state = "loaded"
} else if (image.status === Image.Error) {
source = "qrc:/assets/images/missingPreview.png"
screenPlayItemImage.state = "loaded"
root.state = "loaded"
}
}
}
AnimatedImage {
id: imgGIFPreview
enabled: false
asynchronous: true
playing: false
opacity: 0
Component {
id: component_imgGIFPreview
AnimatedImage {
id: imgGIFPreview
asynchronous: true
playing: true
source: root.sourceImageGIF
=== "" ? "qrc:/assets/images/missingPreview.png" : Qt.resolvedUrl(
absoluteStoragePath + "/" + root.sourceImageGIF)
fillMode: Image.PreserveAspectCrop
}
}
Loader {
id: loader_imgGIFPreview
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
opacity: 0
}
states: [
......@@ -70,7 +80,7 @@ Item {
name: "hover"
PropertyChanges {
target: imgGIFPreview
target: loader_imgGIFPreview
opacity: 1
}
}
......@@ -94,7 +104,7 @@ Item {
reversible: true
PropertyAnimation {
target: imgGIFPreview
target: loader_imgGIFPreview
property: "opacity"
duration: 400
easing.type: Easing.OutQuart
......
......@@ -24,22 +24,22 @@ Item {
onContentFolderNameChanged: {
txtHeadline.text = ScreenPlay.installedListModel.get(
root.contentFolderName).screenTitle
root.contentFolderName).m_title
const hasPreviewGif = ScreenPlay.installedListModel.get(
root.contentFolderName).screenPreviewGIF !== undefined
root.contentFolderName).m_previewGIF !== undefined
if (!hasPreviewGif) {
image.source = Qt.resolvedUrl(
ScreenPlay.globalVariables.localStoragePath + "/"
+ root.contentFolderName + "/" + ScreenPlay.installedListModel.get(
root.contentFolderName).screenPreview)
root.contentFolderName).m_preview)
image.playing = false
} else {
image.source = Qt.resolvedUrl(
ScreenPlay.globalVariables.localStoragePath + "/"
+ root.contentFolderName + "/" + ScreenPlay.installedListModel.get(
root.contentFolderName).screenPreviewGIF)
root.contentFolderName).m_previewGIF)
image.playing = true
}
......
......@@ -13,7 +13,7 @@ Item {
property string monitorManufacturer
property string monitorName
property string monitorID
property string previewImage: ""
property string previewImage
property string appID
property var installedType: InstalledType.QMLWallpaper
property bool monitorWithoutContentSelectable: true
......
......@@ -32,6 +32,7 @@ Item {
}
}
Image {
id: image
width: 24
......
......@@ -19,7 +19,7 @@ InstalledListFilter::InstalledListFilter(const std::shared_ptr<InstalledListMode
, m_ilm(ilm)
{
setSourceModel(m_ilm.get());
setFilterRole(InstalledListModel::InstalledRole::TitleRole);
setFilterRole(static_cast<int>(InstalledListModel::ScreenPlayItem::Title));
}
/*!
......@@ -28,7 +28,7 @@ InstalledListFilter::InstalledListFilter(const std::shared_ptr<InstalledListMode
*/
void InstalledListFilter::sortByName(const QString& name)
{
setFilterRole(InstalledListModel::InstalledRole::TitleRole);
setFilterRole(static_cast<int>(InstalledListModel::ScreenPlayItem::Title));
setFilterCaseSensitivity(Qt::CaseInsensitive);
setFilterFixedString(name);
sort(0);
......@@ -40,7 +40,7 @@ void InstalledListFilter::sortBySearchType(const ScreenPlay::SearchType::SearchT
resetFilter();
return;
}
setFilterRole(InstalledListModel::InstalledRole::SearchTypeRole);
setFilterRole(static_cast<int>(InstalledListModel::ScreenPlayItem::SearchType));
setFilterFixedString(QVariant::fromValue(searchType).toString());
sort(0);
}
......@@ -50,7 +50,7 @@ void InstalledListFilter::sortBySearchType(const ScreenPlay::SearchType::SearchT
*/
void InstalledListFilter::resetFilter()
{
setFilterRole(InstalledListModel::InstalledRole::TitleRole);
setFilterRole(static_cast<int>(InstalledListModel::ScreenPlayItem::Title));
setFilterWildcard("*");
sort(0);
}
......
......@@ -93,25 +93,25 @@ QVariant InstalledListModel::data(const QModelIndex& index, int role) const
if (row < rowCount())
switch (role) {
case TitleRole:
case static_cast<int>(ScreenPlayItem::Title):
return m_screenPlayFiles.at(row).m_title;
case PreviewRole:
case static_cast<int>(ScreenPlayItem::Preview):
return m_screenPlayFiles.at(row).m_preview;
case PreviewGIFRole:
case static_cast<int>(ScreenPlayItem::PreviewGIF):
return m_screenPlayFiles.at(row).m_previewGIF;
case TypeRole:
case static_cast<int>(ScreenPlayItem::Type):
return QVariant::fromValue(m_screenPlayFiles.at(row).m_type);
case FolderIdRole:
case static_cast<int>(ScreenPlayItem::FolderId):
return m_screenPlayFiles.at(row).m_folderId;
case FileIdRole:
case static_cast<int>(ScreenPlayItem::FileId):
return m_screenPlayFiles.at(row).m_file;
case AbsoluteStoragePathRole:
case static_cast<int>(ScreenPlayItem::AbsoluteStoragePath):
return m_screenPlayFiles.at(row).m_absoluteStoragePath;
case WorkshopIDRole:
case static_cast<int>(ScreenPlayItem::WorkshopID):
return m_screenPlayFiles.at(row).m_workshopID;
case TagsRole:
case static_cast<int>(ScreenPlayItem::Tags):
return m_screenPlayFiles.at(row).m_tags;
case SearchTypeRole:
case static_cast<int>(ScreenPlayItem::SearchType):
return QVariant::fromValue(m_screenPlayFiles.at(row).m_searchType);
default:
return QVariant();
......@@ -124,17 +124,18 @@ QVariant InstalledListModel::data(const QModelIndex& index, int role) const
*/
QHash<int, QByteArray> InstalledListModel::roleNames() const
{
static const QHash<int, QByteArray> roles {
{ TitleRole, "screenTitle" },
{ TypeRole, "screenType" },
{ PreviewRole, "screenPreview" },
{ PreviewGIFRole, "screenPreviewGIF" },
{ FolderIdRole, "screenFolderId" },
{ FileIdRole, "screenFile" },
{ AbsoluteStoragePathRole, "screenAbsoluteStoragePath" },
{ WorkshopIDRole, "screenWorkshopID" },
{ TagsRole, "screenTags" },
{ SearchTypeRole, "screenSearchType" },
{ static_cast<int>(ScreenPlayItem::Title), "m_title" },
{ static_cast<int>(ScreenPlayItem::Type), "m_type" },
{ static_cast<int>(ScreenPlayItem::Preview), "m_preview" },
{ static_cast<int>(ScreenPlayItem::PreviewGIF), "m_previewGIF" },
{ static_cast<int>(ScreenPlayItem::FolderId), "m_folderId" },
{ static_cast<int>(ScreenPlayItem::FileId), "m_file" },
{ static_cast<int>(ScreenPlayItem::AbsoluteStoragePath), "m_absoluteStoragePath" },
{ static_cast<int>(ScreenPlayItem::WorkshopID), "m_workshopID" },
{ static_cast<int>(ScreenPlayItem::Tags), "m_tags" },
{ static_cast<int>(ScreenPlayItem::SearchType), "m_searchType" },
};
return roles;
}
......@@ -183,27 +184,28 @@ void InstalledListModel::loadInstalledContent()
});
}
QVariantMap InstalledListModel::get(QString folderId) const
QVariantMap InstalledListModel::get(const QString& folderId) const
{
QVariantMap map;
if (m_screenPlayFiles.count() == 0)
return map;
return {};
QVariantMap map;
for (int i = 0; i < m_screenPlayFiles.count(); i++) {
if (m_screenPlayFiles[i].m_folderId == folderId) {
map.insert("screenTitle", m_screenPlayFiles[i].m_title);
map.insert("screenPreview", m_screenPlayFiles[i].m_preview);
map.insert("screenPreviewGIF", m_screenPlayFiles[i].m_previewGIF);
map.insert("screenFile", m_screenPlayFiles[i].m_file);
map.insert("screenType", QVariant::fromValue(m_screenPlayFiles[i].m_type));
map.insert("screenAbsoluteStoragePath", m_screenPlayFiles[i].m_absoluteStoragePath);
map.insert("screenWorkshopID", m_screenPlayFiles[i].m_workshopID);
map.insert("m_title", m_screenPlayFiles[i].m_title);
map.insert("m_preview", m_screenPlayFiles[i].m_preview);
map.insert("m_previewGIF", m_screenPlayFiles[i].m_previewGIF);
map.insert("m_file", m_screenPlayFiles[i].m_file);
map.insert("m_type", QVariant::fromValue(m_screenPlayFiles[i].m_type));
map.insert("m_absoluteStoragePath", m_screenPlayFiles[i].m_absoluteStoragePath);
map.insert("m_workshopID", m_screenPlayFiles[i].m_workshopID);
return map;
}
}
return map;
return {};
}
void InstalledListModel::reset()
......
......@@ -76,19 +76,19 @@ public:
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;
enum InstalledRole {
TitleRole = Qt::UserRole,
TypeRole,
PreviewRole,
PreviewGIFRole,
FolderIdRole,
FileIdRole,
AbsoluteStoragePathRole,
WorkshopIDRole,
TagsRole,
SearchTypeRole,
enum class ScreenPlayItem {
Title = Qt::UserRole,
Type,
Preview,
PreviewGIF,
FolderId,
FileId,
AbsoluteStoragePath,
WorkshopID,
Tags,
SearchType,
};
Q_ENUM(InstalledRole)
Q_ENUM(ScreenPlayItem)
int count() const
{
......@@ -96,11 +96,12 @@ public:
}
public slots:
QVariantMap get(const QString &folderId) const;
void loadInstalledContent();
void append(const QJsonObject&, const QString&);
void reset();
void init();
QVariantMap get(QString folderId) const;
bool deinstallItemAt(const int index);
void setCount(int count)
......@@ -111,12 +112,10 @@ public slots:
m_count = count;
emit countChanged(m_count);