mirror of
https://gitlab.com/kelteseth/ScreenPlay.git
synced 2024-11-25 20:22:39 +01:00
Fix project deletion when content (preview.gif) was in use
This commit is contained in:
parent
2226ed1b7e
commit
c0d528048b
@ -34,11 +34,17 @@ ApplicationWindow {
|
||||
function switchPage(name) {
|
||||
if (nav.currentNavigationName === name) {
|
||||
if (name === "Installed")
|
||||
ScreenPlay.installedListModel.reset();
|
||||
|
||||
ScreenPlay.installedListModel.reset()
|
||||
}
|
||||
stackView.replace("qrc:/qml/" + name + "/" + name + ".qml");
|
||||
sidebar.state = "inactive";
|
||||
|
||||
if (name === "Installed") {
|
||||
stackView.replace("qrc:/qml/" + name + "/" + name + ".qml", {
|
||||
"sidebar": sidebar
|
||||
})
|
||||
return
|
||||
}
|
||||
stackView.replace("qrc:/qml/" + name + "/" + name + ".qml")
|
||||
sidebar.state = "inactive"
|
||||
}
|
||||
|
||||
color: Material.theme === Material.Dark ? Qt.darker(Material.background) : Material.background
|
||||
|
@ -13,6 +13,7 @@ Item {
|
||||
|
||||
property bool refresh: false
|
||||
property bool enabled: true
|
||||
property Sidebar sidebar
|
||||
|
||||
signal setNavigationItem(var pos)
|
||||
signal setSidebarActive(var active)
|
||||
@ -102,6 +103,36 @@ Item {
|
||||
onDragStarted: isDragging = true
|
||||
onDragEnded: isDragging = false
|
||||
model: ScreenPlay.installedListFilter
|
||||
removeDisplaced: Transition {
|
||||
SequentialAnimation {
|
||||
PauseAnimation {
|
||||
duration: 150
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "x,y"
|
||||
duration: 250
|
||||
easing.type: Easing.InOutQuart
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remove: Transition {
|
||||
SequentialAnimation {
|
||||
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
to: 0
|
||||
duration: 200
|
||||
easing.type: Easing.InOutQuart
|
||||
}
|
||||
NumberAnimation {
|
||||
properties: "y"
|
||||
to: 100
|
||||
duration: 200
|
||||
easing.type: Easing.InOutQuart
|
||||
}
|
||||
}
|
||||
}
|
||||
onContentYChanged: {
|
||||
if (contentY <= -180)
|
||||
gridView.headerItem.isVisible = true;
|
||||
@ -262,8 +293,8 @@ Item {
|
||||
enabled: contextMenu.publishedFileID !== 0
|
||||
icon.source: "qrc:/assets/icons/icon_steam.svg"
|
||||
onClicked: {
|
||||
print(contextMenu.publishedFileID)
|
||||
Qt.openUrlExternally("steam://url/CommunityFilePage/" + contextMenu.publishedFileID);
|
||||
Qt.openUrlExternally(
|
||||
"steam://url/CommunityFilePage/" + contextMenu.publishedFileID)
|
||||
}
|
||||
}
|
||||
|
||||
@ -271,15 +302,16 @@ Item {
|
||||
|
||||
Dialog {
|
||||
id: deleteDialog
|
||||
|
||||
property int currentItemIndex: 0
|
||||
|
||||
title: qsTr("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(currentItemIndex)
|
||||
onAccepted: {
|
||||
root.sidebar.clear()
|
||||
ScreenPlay.installedListModel.deinstallItemAt(
|
||||
contextMenu.absoluteStoragePath)
|
||||
}
|
||||
}
|
||||
|
||||
Navigation {
|
||||
|
@ -29,6 +29,14 @@ Item {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// This is used for removing wallpaper. We need to clear
|
||||
// the preview image/gif so we can release the file for deletion.
|
||||
function clear(){
|
||||
image.source = ""
|
||||
txtHeadline.text = ""
|
||||
root.state = "inactive"
|
||||
}
|
||||
|
||||
width: 400
|
||||
state: "inactive"
|
||||
onContentFolderNameChanged: {
|
||||
@ -48,8 +56,10 @@ Item {
|
||||
btnSetWallpaper.enabled = false;
|
||||
}
|
||||
|
||||
|
||||
Connections {
|
||||
function onSetSidebarItem(folderName, type) {
|
||||
|
||||
// Toggle sidebar if clicked on the same content twice
|
||||
if (root.contentFolderName === folderName && root.state !== "inactive") {
|
||||
root.state = "inactive";
|
||||
@ -152,10 +162,12 @@ Item {
|
||||
|
||||
AnimatedImage {
|
||||
id: image
|
||||
|
||||
// Do NOT enable async image loading!
|
||||
// Otherwhise it will still hold the file
|
||||
// when calling InstalledListModel::deinstallItemAt
|
||||
asynchronous: false
|
||||
playing: true
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
asynchronous: true
|
||||
anchors.fill: parent
|
||||
onStatusChanged: {
|
||||
if (image.status === Image.Error)
|
||||
|
@ -45,27 +45,65 @@ void InstalledListModel::init()
|
||||
|
||||
/*!
|
||||
\brief Deleted the item from the local storage and removes it from the
|
||||
installed list.
|
||||
installed list. We wait for the qml engine to free all resources before
|
||||
we proceed. This like the preview.gif will be in use when clicking on an item
|
||||
*/
|
||||
bool InstalledListModel::deinstallItemAt(const int index)
|
||||
void InstalledListModel::deinstallItemAt(const QString& absoluteStoragePath)
|
||||
{
|
||||
if (index < 0 || index >= m_screenPlayFiles.count()) {
|
||||
qWarning() << "remove folder error, invalid index " << index;
|
||||
return false;
|
||||
}
|
||||
QTimer::singleShot(1000, this, [this, absoluteStoragePath]() {
|
||||
int index = -1;
|
||||
for (int i = 0; i < m_screenPlayFiles.size(); ++i) {
|
||||
if (m_screenPlayFiles.at(i).m_absoluteStoragePath.toString() == absoluteStoragePath) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
beginRemoveRows(QModelIndex(), index, index);
|
||||
const QString path = QUrl::fromUserInput(m_screenPlayFiles.at(index).m_absoluteStoragePath.toString()).toLocalFile();
|
||||
if (index < 0 || index >= m_screenPlayFiles.count()) {
|
||||
qWarning() << "Remove folder error, invalid index " << index;
|
||||
return;
|
||||
}
|
||||
|
||||
QDir dir(path);
|
||||
const bool success = dir.removeRecursively();
|
||||
beginRemoveRows(QModelIndex(), index, index);
|
||||
m_screenPlayFiles.removeAt(index);
|
||||
endRemoveRows();
|
||||
|
||||
if (!success)
|
||||
qWarning() << "Could not remove folder: " << m_screenPlayFiles.at(index).m_absoluteStoragePath.toString();
|
||||
const QString path = ScreenPlayUtil::toLocal(absoluteStoragePath);
|
||||
|
||||
m_screenPlayFiles.removeAt(index);
|
||||
endRemoveRows();
|
||||
return success;
|
||||
QDir dir(path);
|
||||
bool success = true;
|
||||
if (!dir.exists()) {
|
||||
qWarning() << "Directory does not exist!" << dir;
|
||||
return;
|
||||
}
|
||||
|
||||
// We must pause the QFileSystemWatcher to not trigger
|
||||
// a reload for every removed file
|
||||
m_fileSystemWatcher.blockSignals(true);
|
||||
for (auto& item : dir.entryInfoList(QDir::Files)) {
|
||||
if (!QFile::remove(item.absoluteFilePath())) {
|
||||
qWarning() << "Unable to remove file:" << item;
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
qWarning() << "Could not remove folder content at: " << path;
|
||||
loadInstalledContent();
|
||||
}
|
||||
|
||||
if (!dir.rmdir(path)) {
|
||||
qWarning() << "Could not remove folder at: " << path;
|
||||
return;
|
||||
}
|
||||
|
||||
// Add delay to the watcher, because it was trigger by
|
||||
// something when enabling after the removal.
|
||||
QTimer::singleShot(3000, this, [this]() {
|
||||
m_fileSystemWatcher.blockSignals(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -156,11 +194,17 @@ void InstalledListModel::append(const QJsonObject& obj, const QString& folderNam
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief Loads all installed content. Skips projects.json without a "type" field.
|
||||
\brief Loads all installed content.
|
||||
- Skips if the loadContentFuture is already running.
|
||||
- Skips projects.json without a "type" field.
|
||||
*/
|
||||
void InstalledListModel::loadInstalledContent()
|
||||
{
|
||||
QtConcurrent::run([this]() {
|
||||
qInfo() << "loadInstalledContent";
|
||||
if (m_loadContentFuture.isRunning())
|
||||
return;
|
||||
|
||||
m_loadContentFuture = QtConcurrent::run([this]() {
|
||||
QFileInfoList list = QDir(m_globalVariables->localStoragePath().toLocalFile()).entryInfoList(QDir::NoDotAndDotDot | QDir::AllDirs);
|
||||
int counter = 0;
|
||||
|
||||
@ -198,27 +242,33 @@ void InstalledListModel::loadInstalledContent()
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief .
|
||||
\brief Used for receiving values from qml. One must add all new fields
|
||||
when adding new roles to this model.
|
||||
*/
|
||||
QVariantMap InstalledListModel::get(const QString& folderId) const
|
||||
QVariantMap InstalledListModel::get(const QString& folderName) const
|
||||
{
|
||||
|
||||
if (m_screenPlayFiles.count() == 0)
|
||||
return {};
|
||||
|
||||
QVariantMap map;
|
||||
for (int i = 0; i < m_screenPlayFiles.count(); i++) {
|
||||
const QString localInstalledPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString());
|
||||
|
||||
if (m_screenPlayFiles[i].m_folderId == folderId) {
|
||||
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_publishedFileID", m_screenPlayFiles[i].m_publishedFileID);
|
||||
map.insert("m_isNew", m_screenPlayFiles[i].m_isNew);
|
||||
map.insert("m_lastModified", m_screenPlayFiles[i].m_lastModified);
|
||||
if (!QDir(localInstalledPath + "/" + folderName).exists()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
for (const auto& item : m_screenPlayFiles) {
|
||||
if (item.m_folderId == folderName) {
|
||||
QVariantMap map;
|
||||
map.insert("m_title", item.m_title);
|
||||
map.insert("m_preview", item.m_preview);
|
||||
map.insert("m_previewGIF", item.m_previewGIF);
|
||||
map.insert("m_file", item.m_file);
|
||||
map.insert("m_type", QVariant::fromValue(item.m_type));
|
||||
map.insert("m_absoluteStoragePath", item.m_absoluteStoragePath);
|
||||
map.insert("m_publishedFileID", item.m_publishedFileID);
|
||||
map.insert("m_isNew", item.m_isNew);
|
||||
map.insert("m_lastModified", item.m_lastModified);
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@ -227,7 +277,7 @@ QVariantMap InstalledListModel::get(const QString& folderId) const
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief .
|
||||
\brief Removes all entires and loads it again.
|
||||
*/
|
||||
void InstalledListModel::reset()
|
||||
{
|
||||
|
@ -99,13 +99,13 @@ public:
|
||||
}
|
||||
|
||||
public slots:
|
||||
QVariantMap get(const QString& folderId) const;
|
||||
QVariantMap get(const QString& folderName) const;
|
||||
|
||||
void loadInstalledContent();
|
||||
void append(const QJsonObject&, const QString&, const bool isNew, const QDateTime& lastModified);
|
||||
void reset();
|
||||
void init();
|
||||
bool deinstallItemAt(const int index);
|
||||
void deinstallItemAt(const QString& absoluteStoragePath);
|
||||
|
||||
void setCount(int count)
|
||||
{
|
||||
@ -124,6 +124,7 @@ private:
|
||||
QFileSystemWatcher m_fileSystemWatcher;
|
||||
QVector<ProjectFile> m_screenPlayFiles;
|
||||
int m_count { 0 };
|
||||
QFuture<void> m_loadContentFuture;
|
||||
|
||||
const std::shared_ptr<GlobalVariables>& m_globalVariables;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user