feat: warnings when instance resources are linked

Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
This commit is contained in:
Rachel Powers
2023-02-12 02:44:39 -07:00
parent 9f441a9678
commit a1053a4c5a
13 changed files with 179 additions and 3 deletions

View File

@ -39,13 +39,17 @@
#include <FileSystem.h>
#include <QDebug>
#include <QFileSystemWatcher>
#include <QIcon>
#include <QMimeData>
#include <QString>
#include <QStyle>
#include <QThreadPool>
#include <QUrl>
#include <QUuid>
#include <algorithm>
#include "Application.h"
#include "minecraft/mod/tasks/LocalModParseTask.h"
#include "minecraft/mod/tasks/ModFolderLoadTask.h"
#include "modplatform/ModIndex.h"
@ -97,8 +101,24 @@ QVariant ModFolderModel::data(const QModelIndex &index, int role) const
}
case Qt::ToolTipRole:
if (column == NAME_COLUMN) {
if (at(row)->isSymLinkUnder(instDirPath())) {
return m_resources[row]->internal_id() +
tr("\nWarning: This resource is symbolicly linked from elsewhere. Editing it will also change the origonal") +
tr("\nCanonical Path: %1").arg(at(row)->fileinfo().canonicalFilePath());
}
if (at(row)->isMoreThanOneHardLink()) {
return m_resources[row]->internal_id() +
tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the origonal");
}
}
return m_resources[row]->internal_id();
case Qt::DecorationRole: {
if (column == NAME_COLUMN && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink()))
return APPLICATION->getThemedIcon("status-yellow");
return {};
}
case Qt::CheckStateRole:
switch (column)
{

View File

@ -1,6 +1,8 @@
#include "Resource.h"
#include <QRegularExpression>
#include <QFileInfo>
#include "FileSystem.h"
@ -152,3 +154,21 @@ bool Resource::destroy()
return FS::deletePath(m_file_info.filePath());
}
bool Resource::isSymLinkUnder(const QString& instPath) const
{
if (isSymLink())
return true;
auto instDir = QDir(instPath);
auto relAbsPath = instDir.relativeFilePath(m_file_info.absoluteFilePath());
auto relCanonPath = instDir.relativeFilePath(m_file_info.canonicalFilePath());
return relAbsPath != relCanonPath;
}
bool Resource::isMoreThanOneHardLink() const
{
return FS::hardLinkCount(m_file_info.absoluteFilePath()) > 1;
}

View File

@ -94,6 +94,19 @@ class Resource : public QObject {
// Delete all files of this resource.
bool destroy();
[[nodiscard]] auto isSymLink() const -> bool { return m_file_info.isSymLink(); }
/**
* @brief Take a instance path, checks if the file pointed to by the resource is a symlink or under a symlink in that instance
*
* @param instPath path to an instance directory
* @return true
* @return false
*/
[[nodiscard]] bool isSymLinkUnder(const QString& instPath) const;
[[nodiscard]] bool isMoreThanOneHardLink() const;
protected:
/* The file corresponding to this resource. */
QFileInfo m_file_info;

View File

@ -2,10 +2,14 @@
#include <QCoreApplication>
#include <QDebug>
#include <QFileInfo>
#include <QIcon>
#include <QMimeData>
#include <QStyle>
#include <QThreadPool>
#include <QUrl>
#include "Application.h"
#include "FileSystem.h"
#include "minecraft/mod/tasks/BasicFolderLoadTask.h"
@ -417,7 +421,25 @@ QVariant ResourceFolderModel::data(const QModelIndex& index, int role) const
return {};
}
case Qt::ToolTipRole:
if (column == NAME_COLUMN) {
if (at(row).isSymLinkUnder(instDirPath())) {
return m_resources[row]->internal_id() +
tr("\nWarning: This resource is symbolicly linked from elsewhere. Editing it will also change the origonal") +
tr("\nCanonical Path: %1").arg(at(row).fileinfo().canonicalFilePath());;
}
if (at(row).isMoreThanOneHardLink()) {
return m_resources[row]->internal_id() +
tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the origonal");
}
}
return m_resources[row]->internal_id();
case Qt::DecorationRole: {
if (column == NAME_COLUMN && (at(row).isSymLinkUnder(instDirPath()) || at(row).isMoreThanOneHardLink()))
return APPLICATION->getThemedIcon("status-yellow");
return {};
}
case Qt::CheckStateRole:
switch (column) {
case ACTIVE_COLUMN:
@ -531,3 +553,7 @@ void ResourceFolderModel::enableInteraction(bool enabled)
return (compare_result.first < 0);
return (compare_result.first > 0);
}
QString ResourceFolderModel::instDirPath() const {
return QFileInfo(m_dir.filePath("../..")).absoluteFilePath();
}

View File

@ -125,6 +125,8 @@ class ResourceFolderModel : public QAbstractListModel {
[[nodiscard]] bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override;
};
QString instDirPath() const;
public slots:
void enableInteraction(bool enabled);
void disableInteraction(bool disabled) { enableInteraction(!disabled); }

View File

@ -36,6 +36,10 @@
#include "ResourcePackFolderModel.h"
#include <QIcon>
#include <QStyle>
#include "Application.h"
#include "Version.h"
#include "minecraft/mod/tasks/BasicFolderLoadTask.h"
@ -78,12 +82,28 @@ QVariant ResourcePackFolderModel::data(const QModelIndex& index, int role) const
default:
return {};
}
case Qt::DecorationRole: {
if (column == NAME_COLUMN && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink()))
return APPLICATION->getThemedIcon("status-yellow");
return {};
}
case Qt::ToolTipRole: {
if (column == PackFormatColumn) {
//: The string being explained by this is in the format: ID (Lower version - Upper version)
return tr("The resource pack format ID, as well as the Minecraft versions it was designed for.");
}
if (column == NAME_COLUMN) {
if (at(row)->isSymLinkUnder(instDirPath())) {
return m_resources[row]->internal_id() +
tr("\nWarning: This resource is symbolicly linked from elsewhere. Editing it will also change the origonal") +
tr("\nCanonical Path: %1").arg(at(row)->fileinfo().canonicalFilePath());;
}
if (at(row)->isMoreThanOneHardLink()) {
return m_resources[row]->internal_id() +
tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the origonal");
}
}
return m_resources[row]->internal_id();
}
case Qt::CheckStateRole: