Delete shortcut when deleting instances
Signed-off-by: Yihe Li <winmikedows@hotmail.com>
This commit is contained in:
parent
0a89f5cfaa
commit
d3f337d6ef
11 changed files with 168 additions and 67 deletions
|
@ -398,6 +398,17 @@ bool BaseInstance::syncInstanceDirName(const QString& newRoot) const
|
||||||
return oldRoot == newRoot || QFile::rename(oldRoot, newRoot);
|
return oldRoot == newRoot || QFile::rename(oldRoot, newRoot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseInstance::registerShortcut(const ShortcutData& data)
|
||||||
|
{
|
||||||
|
m_shortcuts.append(data);
|
||||||
|
qDebug() << "Registering shortcut for instance" << id() << "with name" << data.name << "and path" << data.filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<ShortcutData>& BaseInstance::getShortcuts()
|
||||||
|
{
|
||||||
|
return m_shortcuts;
|
||||||
|
}
|
||||||
|
|
||||||
QString BaseInstance::name() const
|
QString BaseInstance::name() const
|
||||||
{
|
{
|
||||||
return m_settings->get("name").toString();
|
return m_settings->get("name").toString();
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QList>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
@ -66,6 +67,16 @@ class BaseInstance;
|
||||||
// pointer for lazy people
|
// pointer for lazy people
|
||||||
using InstancePtr = std::shared_ptr<BaseInstance>;
|
using InstancePtr = std::shared_ptr<BaseInstance>;
|
||||||
|
|
||||||
|
/// Shortcut saving target representations
|
||||||
|
enum class ShortcutTarget { Desktop, Applications, Other };
|
||||||
|
|
||||||
|
/// Shortcut data representation
|
||||||
|
struct ShortcutData {
|
||||||
|
QString name;
|
||||||
|
QString filePath;
|
||||||
|
ShortcutTarget target;
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Base class for instances.
|
* \brief Base class for instances.
|
||||||
* This class implements many functions that are common between instances and
|
* This class implements many functions that are common between instances and
|
||||||
|
@ -129,6 +140,10 @@ class BaseInstance : public QObject, public std::enable_shared_from_this<BaseIns
|
||||||
/// Sync name and rename instance dir accordingly; returns true if successful
|
/// Sync name and rename instance dir accordingly; returns true if successful
|
||||||
bool syncInstanceDirName(const QString& newRoot) const;
|
bool syncInstanceDirName(const QString& newRoot) const;
|
||||||
|
|
||||||
|
/// Register a created shortcut
|
||||||
|
void registerShortcut(const ShortcutData& data);
|
||||||
|
QList<ShortcutData>& getShortcuts();
|
||||||
|
|
||||||
/// Value used for instance window titles
|
/// Value used for instance window titles
|
||||||
QString windowTitle() const;
|
QString windowTitle() const;
|
||||||
|
|
||||||
|
@ -308,6 +323,8 @@ class BaseInstance : public QObject, public std::enable_shared_from_this<BaseIns
|
||||||
|
|
||||||
SettingsObjectWeakPtr m_global_settings;
|
SettingsObjectWeakPtr m_global_settings;
|
||||||
bool m_specific_settings_loaded = false;
|
bool m_specific_settings_loaded = false;
|
||||||
|
|
||||||
|
QList<ShortcutData> m_shortcuts;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(shared_qobject_ptr<BaseInstance>)
|
Q_DECLARE_METATYPE(shared_qobject_ptr<BaseInstance>)
|
||||||
|
|
|
@ -898,26 +898,26 @@ QString getApplicationsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cross-platform Shortcut creation
|
// Cross-platform Shortcut creation
|
||||||
bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon)
|
QString createShortcut(QString destination, QString target, QStringList args, QString name, QString icon)
|
||||||
{
|
{
|
||||||
if (destination.isEmpty()) {
|
if (destination.isEmpty()) {
|
||||||
destination = PathCombine(getDesktopDir(), RemoveInvalidFilenameChars(name));
|
destination = PathCombine(getDesktopDir(), RemoveInvalidFilenameChars(name));
|
||||||
}
|
}
|
||||||
if (!ensureFilePathExists(destination)) {
|
if (!ensureFilePathExists(destination)) {
|
||||||
qWarning() << "Destination path can't be created!";
|
qWarning() << "Destination path can't be created!";
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
#if defined(Q_OS_MACOS)
|
#if defined(Q_OS_MACOS)
|
||||||
QDir application = destination + ".app/";
|
QDir application = destination + ".app/";
|
||||||
|
|
||||||
if (application.exists()) {
|
if (application.exists()) {
|
||||||
qWarning() << "Application already exists!";
|
qWarning() << "Application already exists!";
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!application.mkpath(".")) {
|
if (!application.mkpath(".")) {
|
||||||
qWarning() << "Couldn't create application";
|
qWarning() << "Couldn't create application";
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
QDir content = application.path() + "/Contents/";
|
QDir content = application.path() + "/Contents/";
|
||||||
|
@ -927,7 +927,7 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
|
||||||
|
|
||||||
if (!(content.mkpath(".") && resources.mkpath(".") && binaryDir.mkpath("."))) {
|
if (!(content.mkpath(".") && resources.mkpath(".") && binaryDir.mkpath("."))) {
|
||||||
qWarning() << "Couldn't create directories within application";
|
qWarning() << "Couldn't create directories within application";
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
info.open(QIODevice::WriteOnly | QIODevice::Text);
|
info.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||||
|
|
||||||
|
@ -976,7 +976,7 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
|
||||||
"</dict>\n"
|
"</dict>\n"
|
||||||
"</plist>";
|
"</plist>";
|
||||||
|
|
||||||
return true;
|
return application.path();
|
||||||
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
||||||
if (!destination.endsWith(".desktop")) // in case of isFlatpak destination is already populated
|
if (!destination.endsWith(".desktop")) // in case of isFlatpak destination is already populated
|
||||||
destination += ".desktop";
|
destination += ".desktop";
|
||||||
|
@ -1002,32 +1002,32 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
|
||||||
|
|
||||||
f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther);
|
f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther);
|
||||||
|
|
||||||
return true;
|
return destination;
|
||||||
#elif defined(Q_OS_WIN)
|
#elif defined(Q_OS_WIN)
|
||||||
QFileInfo targetInfo(target);
|
QFileInfo targetInfo(target);
|
||||||
|
|
||||||
if (!targetInfo.exists()) {
|
if (!targetInfo.exists()) {
|
||||||
qWarning() << "Target file does not exist!";
|
qWarning() << "Target file does not exist!";
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
target = targetInfo.absoluteFilePath();
|
target = targetInfo.absoluteFilePath();
|
||||||
|
|
||||||
if (target.length() >= MAX_PATH) {
|
if (target.length() >= MAX_PATH) {
|
||||||
qWarning() << "Target file path is too long!";
|
qWarning() << "Target file path is too long!";
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!icon.isEmpty() && icon.length() >= MAX_PATH) {
|
if (!icon.isEmpty() && icon.length() >= MAX_PATH) {
|
||||||
qWarning() << "Icon path is too long!";
|
qWarning() << "Icon path is too long!";
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
destination += ".lnk";
|
destination += ".lnk";
|
||||||
|
|
||||||
if (destination.length() >= MAX_PATH) {
|
if (destination.length() >= MAX_PATH) {
|
||||||
qWarning() << "Destination path is too long!";
|
qWarning() << "Destination path is too long!";
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
QString argStr;
|
QString argStr;
|
||||||
|
@ -1046,7 +1046,7 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
|
||||||
|
|
||||||
if (argStr.length() >= MAX_PATH) {
|
if (argStr.length() >= MAX_PATH) {
|
||||||
qWarning() << "Arguments string is too long!";
|
qWarning() << "Arguments string is too long!";
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
@ -1055,7 +1055,7 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
|
||||||
hres = CoInitialize(nullptr);
|
hres = CoInitialize(nullptr);
|
||||||
if (FAILED(hres)) {
|
if (FAILED(hres)) {
|
||||||
qWarning() << "Failed to initialize COM!";
|
qWarning() << "Failed to initialize COM!";
|
||||||
return false;
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
WCHAR wsz[MAX_PATH];
|
WCHAR wsz[MAX_PATH];
|
||||||
|
@ -1109,10 +1109,12 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
|
||||||
// go away COM, nobody likes you
|
// go away COM, nobody likes you
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
|
|
||||||
return SUCCEEDED(hres);
|
if (SUCCEEDED(hres))
|
||||||
|
return destination;
|
||||||
|
return "";
|
||||||
#else
|
#else
|
||||||
qWarning("Desktop Shortcuts not supported on your platform!");
|
qWarning("Desktop Shortcuts not supported on your platform!");
|
||||||
return false;
|
return "";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -362,8 +362,9 @@ bool overrideFolder(QString overwritten_path, QString override_path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a shortcut to the specified target file at the specified destination path.
|
* Creates a shortcut to the specified target file at the specified destination path.
|
||||||
|
* Returns empty string if creation failed; otherwise returns the path to the created shortcut.
|
||||||
*/
|
*/
|
||||||
bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon);
|
QString createShortcut(QString destination, QString target, QStringList args, QString name, QString icon);
|
||||||
|
|
||||||
enum class FilesystemType {
|
enum class FilesystemType {
|
||||||
FAT,
|
FAT,
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
#include "NullInstance.h"
|
#include "NullInstance.h"
|
||||||
#include "WatchLock.h"
|
#include "WatchLock.h"
|
||||||
#include "minecraft/MinecraftInstance.h"
|
#include "minecraft/MinecraftInstance.h"
|
||||||
|
#include "minecraft/ShortcutUtils.h"
|
||||||
#include "settings/INISettingsObject.h"
|
#include "settings/INISettingsObject.h"
|
||||||
|
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN32
|
||||||
|
@ -333,7 +334,7 @@ bool InstanceList::trashInstance(const InstanceId& id)
|
||||||
{
|
{
|
||||||
auto inst = getInstanceById(id);
|
auto inst = getInstanceById(id);
|
||||||
if (!inst) {
|
if (!inst) {
|
||||||
qDebug() << "Cannot trash instance" << id << ". No such instance is present (deleted externally?).";
|
qWarning() << "Cannot trash instance" << id << ". No such instance is present (deleted externally?).";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,26 +349,48 @@ bool InstanceList::trashInstance(const InstanceId& id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!FS::trash(inst->instanceRoot(), &trashedLoc)) {
|
if (!FS::trash(inst->instanceRoot(), &trashedLoc)) {
|
||||||
qDebug() << "Trash of instance" << id << "has not been completely successfully...";
|
qWarning() << "Trash of instance" << id << "has not been completely successful...";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Instance" << id << "has been trashed by the launcher.";
|
qDebug() << "Instance" << id << "has been trashed by the launcher.";
|
||||||
m_trashHistory.push({ id, inst->instanceRoot(), trashedLoc, cachedGroupId });
|
m_trashHistory.push({ id, inst->instanceRoot(), trashedLoc, cachedGroupId });
|
||||||
|
|
||||||
|
// Also trash all of its shortcuts; we remove the shortcuts if trash fails since it is invalid anyway
|
||||||
|
auto& shortcuts = inst->getShortcuts();
|
||||||
|
for (auto it = shortcuts.begin(); it != shortcuts.end();) {
|
||||||
|
const auto& [name, filePath, target] = *it;
|
||||||
|
if (!FS::trash(filePath, &trashedLoc)) {
|
||||||
|
qWarning() << "Trash of shortcut" << name << "at path" << filePath << "for instance" << id
|
||||||
|
<< "has not been successful, trying to delete it instead...";
|
||||||
|
if (!FS::deletePath(filePath)) {
|
||||||
|
qWarning() << "Deletion of shortcut" << name << "at path" << filePath << "for instance" << id
|
||||||
|
<< "has not been successful, given up...";
|
||||||
|
++it;
|
||||||
|
} else {
|
||||||
|
qDebug() << "Shortcut" << name << "at path" << filePath << "for instance" << id << "has been deleted by the launcher.";
|
||||||
|
it = shortcuts.erase(it);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
qDebug() << "Shortcut" << name << "at path" << filePath << "for instance" << id << "has been trashed by the launcher.";
|
||||||
|
m_trashHistory.top().shortcuts.append({ *it, trashedLoc });
|
||||||
|
it = shortcuts.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InstanceList::trashedSomething()
|
bool InstanceList::trashedSomething() const
|
||||||
{
|
{
|
||||||
return !m_trashHistory.empty();
|
return !m_trashHistory.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceList::undoTrashInstance()
|
bool InstanceList::undoTrashInstance()
|
||||||
{
|
{
|
||||||
if (m_trashHistory.empty()) {
|
if (m_trashHistory.empty()) {
|
||||||
qWarning() << "Nothing to recover from trash.";
|
qWarning() << "Nothing to recover from trash.";
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto top = m_trashHistory.pop();
|
auto top = m_trashHistory.pop();
|
||||||
|
@ -377,21 +400,41 @@ void InstanceList::undoTrashInstance()
|
||||||
top.path += "1";
|
top.path += "1";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!QFile(top.trashPath).rename(top.path)) {
|
||||||
|
qWarning() << "Moving" << top.trashPath << "back to" << top.path << "failed!";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
qDebug() << "Moving" << top.trashPath << "back to" << top.path;
|
qDebug() << "Moving" << top.trashPath << "back to" << top.path;
|
||||||
QFile(top.trashPath).rename(top.path);
|
|
||||||
|
bool ok = true;
|
||||||
|
for (const auto& [data, trashPath] : top.shortcuts) {
|
||||||
|
if (QDir(data.filePath).exists()) {
|
||||||
|
// Don't try to append 1 here as the shortcut may have suffixes like .app, just warn and skip it
|
||||||
|
qWarning() << "Shortcut" << trashPath << "original directory" << data.filePath << "already exists!";
|
||||||
|
ok = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!QFile(trashPath).rename(data.filePath)) {
|
||||||
|
qWarning() << "Moving shortcut from" << trashPath << "back to" << data.filePath << "failed!";
|
||||||
|
ok = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
qDebug() << "Moving shortcut from" << trashPath << "back to" << data.filePath;
|
||||||
|
}
|
||||||
|
|
||||||
m_instanceGroupIndex[top.id] = top.groupName;
|
m_instanceGroupIndex[top.id] = top.groupName;
|
||||||
increaseGroupCount(top.groupName);
|
increaseGroupCount(top.groupName);
|
||||||
|
|
||||||
saveGroupList();
|
saveGroupList();
|
||||||
emit instancesChanged();
|
emit instancesChanged();
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceList::deleteInstance(const InstanceId& id)
|
void InstanceList::deleteInstance(const InstanceId& id)
|
||||||
{
|
{
|
||||||
auto inst = getInstanceById(id);
|
auto inst = getInstanceById(id);
|
||||||
if (!inst) {
|
if (!inst) {
|
||||||
qDebug() << "Cannot delete instance" << id << ". No such instance is present (deleted externally?).";
|
qWarning() << "Cannot delete instance" << id << ". No such instance is present (deleted externally?).";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,6 +452,14 @@ void InstanceList::deleteInstance(const InstanceId& id)
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Instance" << id << "has been deleted by the launcher.";
|
qDebug() << "Instance" << id << "has been deleted by the launcher.";
|
||||||
|
|
||||||
|
for (const auto& [name, filePath, target] : inst->getShortcuts()) {
|
||||||
|
if (!FS::deletePath(filePath)) {
|
||||||
|
qWarning() << "Deletion of shortcut" << name << "at path" << filePath << "for instance" << id << "has not been successful...";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
qDebug() << "Shortcut" << name << "at path" << filePath << "for instance" << id << "has been deleted by the launcher.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static QMap<InstanceId, InstanceLocator> getIdMapping(const QList<InstancePtr>& list)
|
static QMap<InstanceId, InstanceLocator> getIdMapping(const QList<InstancePtr>& list)
|
||||||
|
|
|
@ -56,11 +56,17 @@ enum class InstCreateError { NoCreateError = 0, NoSuchVersion, UnknownCreateErro
|
||||||
|
|
||||||
enum class GroupsState { NotLoaded, Steady, Dirty };
|
enum class GroupsState { NotLoaded, Steady, Dirty };
|
||||||
|
|
||||||
|
struct TrashShortcutItem {
|
||||||
|
ShortcutData data;
|
||||||
|
QString trashPath;
|
||||||
|
};
|
||||||
|
|
||||||
struct TrashHistoryItem {
|
struct TrashHistoryItem {
|
||||||
QString id;
|
QString id;
|
||||||
QString path;
|
QString path;
|
||||||
QString trashPath;
|
QString trashPath;
|
||||||
QString groupName;
|
QString groupName;
|
||||||
|
QList<TrashShortcutItem> shortcuts;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InstanceList : public QAbstractListModel {
|
class InstanceList : public QAbstractListModel {
|
||||||
|
@ -111,8 +117,8 @@ class InstanceList : public QAbstractListModel {
|
||||||
void deleteGroup(const GroupId& name);
|
void deleteGroup(const GroupId& name);
|
||||||
void renameGroup(const GroupId& src, const GroupId& dst);
|
void renameGroup(const GroupId& src, const GroupId& dst);
|
||||||
bool trashInstance(const InstanceId& id);
|
bool trashInstance(const InstanceId& id);
|
||||||
bool trashedSomething();
|
bool trashedSomething() const;
|
||||||
void undoTrashInstance();
|
bool undoTrashInstance();
|
||||||
void deleteInstance(const InstanceId& id);
|
void deleteInstance(const InstanceId& id);
|
||||||
|
|
||||||
// Wrap an instance creation task in some more task machinery and make it ready to be used
|
// Wrap an instance creation task in some more task machinery and make it ready to be used
|
||||||
|
|
|
@ -48,10 +48,10 @@
|
||||||
|
|
||||||
namespace ShortcutUtils {
|
namespace ShortcutUtils {
|
||||||
|
|
||||||
void createInstanceShortcut(const Shortcut& shortcut, const QString& filePath)
|
bool createInstanceShortcut(const Shortcut& shortcut, const QString& filePath)
|
||||||
{
|
{
|
||||||
if (!shortcut.instance)
|
if (!shortcut.instance)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
QString appPath = QApplication::applicationFilePath();
|
QString appPath = QApplication::applicationFilePath();
|
||||||
auto icon = APPLICATION->icons()->icon(shortcut.iconKey.isEmpty() ? shortcut.instance->iconKey() : shortcut.iconKey);
|
auto icon = APPLICATION->icons()->icon(shortcut.iconKey.isEmpty() ? shortcut.instance->iconKey() : shortcut.iconKey);
|
||||||
|
@ -64,7 +64,7 @@ void createInstanceShortcut(const Shortcut& shortcut, const QString& filePath)
|
||||||
if (appPath.startsWith("/private/var/")) {
|
if (appPath.startsWith("/private/var/")) {
|
||||||
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"),
|
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"),
|
||||||
QObject::tr("The launcher is in the folder it was extracted from, therefore it cannot create shortcuts."));
|
QObject::tr("The launcher is in the folder it was extracted from, therefore it cannot create shortcuts."));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
iconPath = FS::PathCombine(shortcut.instance->instanceRoot(), "Icon.icns");
|
iconPath = FS::PathCombine(shortcut.instance->instanceRoot(), "Icon.icns");
|
||||||
|
@ -72,7 +72,7 @@ void createInstanceShortcut(const Shortcut& shortcut, const QString& filePath)
|
||||||
QFile iconFile(iconPath);
|
QFile iconFile(iconPath);
|
||||||
if (!iconFile.open(QFile::WriteOnly)) {
|
if (!iconFile.open(QFile::WriteOnly)) {
|
||||||
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Failed to create icon for application."));
|
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Failed to create icon for application."));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QIcon iconObj = icon->icon();
|
QIcon iconObj = icon->icon();
|
||||||
|
@ -82,7 +82,7 @@ void createInstanceShortcut(const Shortcut& shortcut, const QString& filePath)
|
||||||
if (!success) {
|
if (!success) {
|
||||||
iconFile.remove();
|
iconFile.remove();
|
||||||
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Failed to create icon for application."));
|
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Failed to create icon for application."));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
||||||
if (appPath.startsWith("/tmp/.mount_")) {
|
if (appPath.startsWith("/tmp/.mount_")) {
|
||||||
|
@ -102,7 +102,7 @@ void createInstanceShortcut(const Shortcut& shortcut, const QString& filePath)
|
||||||
QFile iconFile(iconPath);
|
QFile iconFile(iconPath);
|
||||||
if (!iconFile.open(QFile::WriteOnly)) {
|
if (!iconFile.open(QFile::WriteOnly)) {
|
||||||
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Failed to create icon for shortcut."));
|
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Failed to create icon for shortcut."));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
bool success = icon->icon().pixmap(64, 64).save(&iconFile, "PNG");
|
bool success = icon->icon().pixmap(64, 64).save(&iconFile, "PNG");
|
||||||
iconFile.close();
|
iconFile.close();
|
||||||
|
@ -110,7 +110,7 @@ void createInstanceShortcut(const Shortcut& shortcut, const QString& filePath)
|
||||||
if (!success) {
|
if (!success) {
|
||||||
iconFile.remove();
|
iconFile.remove();
|
||||||
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Failed to create icon for shortcut."));
|
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Failed to create icon for shortcut."));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DesktopServices::isFlatpak()) {
|
if (DesktopServices::isFlatpak()) {
|
||||||
|
@ -128,7 +128,7 @@ void createInstanceShortcut(const Shortcut& shortcut, const QString& filePath)
|
||||||
QFile iconFile(iconPath);
|
QFile iconFile(iconPath);
|
||||||
if (!iconFile.open(QFile::WriteOnly)) {
|
if (!iconFile.open(QFile::WriteOnly)) {
|
||||||
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Failed to create icon for shortcut."));
|
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Failed to create icon for shortcut."));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
bool success = icon->icon().pixmap(64, 64).save(&iconFile, "ICO");
|
bool success = icon->icon().pixmap(64, 64).save(&iconFile, "ICO");
|
||||||
iconFile.close();
|
iconFile.close();
|
||||||
|
@ -139,51 +139,58 @@ void createInstanceShortcut(const Shortcut& shortcut, const QString& filePath)
|
||||||
if (!success) {
|
if (!success) {
|
||||||
iconFile.remove();
|
iconFile.remove();
|
||||||
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Failed to create icon for shortcut."));
|
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Failed to create icon for shortcut."));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Not supported on your platform!"));
|
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Not supported on your platform!"));
|
||||||
return;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
args.append({ "--launch", shortcut.instance->id() });
|
args.append({ "--launch", shortcut.instance->id() });
|
||||||
args.append(shortcut.extraArgs);
|
args.append(shortcut.extraArgs);
|
||||||
|
|
||||||
if (!FS::createShortcut(filePath, appPath, args, shortcut.name, iconPath)) {
|
QString shortcutPath = FS::createShortcut(filePath, appPath, args, shortcut.name, iconPath);
|
||||||
|
if (shortcutPath.isEmpty()) {
|
||||||
#if not defined(Q_OS_MACOS)
|
#if not defined(Q_OS_MACOS)
|
||||||
iconFile.remove();
|
iconFile.remove();
|
||||||
#endif
|
#endif
|
||||||
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"),
|
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"),
|
||||||
QObject::tr("Failed to create %1 shortcut!").arg(shortcut.targetString));
|
QObject::tr("Failed to create %1 shortcut!").arg(shortcut.targetString));
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void createInstanceShortcutOnDesktop(const Shortcut& shortcut)
|
shortcut.instance->registerShortcut({ shortcut.name, shortcutPath, shortcut.target });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool createInstanceShortcutOnDesktop(const Shortcut& shortcut)
|
||||||
{
|
{
|
||||||
if (!shortcut.instance)
|
if (!shortcut.instance)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
QString desktopDir = FS::getDesktopDir();
|
QString desktopDir = FS::getDesktopDir();
|
||||||
if (desktopDir.isEmpty()) {
|
if (desktopDir.isEmpty()) {
|
||||||
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Couldn't find desktop?!"));
|
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Couldn't find desktop?!"));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString shortcutFilePath = FS::PathCombine(desktopDir, FS::RemoveInvalidFilenameChars(shortcut.name));
|
QString shortcutFilePath = FS::PathCombine(desktopDir, FS::RemoveInvalidFilenameChars(shortcut.name));
|
||||||
createInstanceShortcut(shortcut, shortcutFilePath);
|
if (!createInstanceShortcut(shortcut, shortcutFilePath))
|
||||||
|
return false;
|
||||||
QMessageBox::information(shortcut.parent, QObject::tr("Create Shortcut"),
|
QMessageBox::information(shortcut.parent, QObject::tr("Create Shortcut"),
|
||||||
QObject::tr("Created a shortcut to this %1 on your desktop!").arg(shortcut.targetString));
|
QObject::tr("Created a shortcut to this %1 on your desktop!").arg(shortcut.targetString));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void createInstanceShortcutInApplications(const Shortcut& shortcut)
|
bool createInstanceShortcutInApplications(const Shortcut& shortcut)
|
||||||
{
|
{
|
||||||
if (!shortcut.instance)
|
if (!shortcut.instance)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
QString applicationsDir = FS::getApplicationsDir();
|
QString applicationsDir = FS::getApplicationsDir();
|
||||||
if (applicationsDir.isEmpty()) {
|
if (applicationsDir.isEmpty()) {
|
||||||
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Couldn't find applications folder?!"));
|
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"), QObject::tr("Couldn't find applications folder?!"));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_MACOS) || defined(Q_OS_WIN)
|
#if defined(Q_OS_MACOS) || defined(Q_OS_WIN)
|
||||||
|
@ -193,20 +200,22 @@ void createInstanceShortcutInApplications(const Shortcut& shortcut)
|
||||||
if (!applicationsDirQ.mkpath(".")) {
|
if (!applicationsDirQ.mkpath(".")) {
|
||||||
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"),
|
QMessageBox::critical(shortcut.parent, QObject::tr("Create Shortcut"),
|
||||||
QObject::tr("Failed to create instances folder in applications folder!"));
|
QObject::tr("Failed to create instances folder in applications folder!"));
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QString shortcutFilePath = FS::PathCombine(applicationsDir, FS::RemoveInvalidFilenameChars(shortcut.name));
|
QString shortcutFilePath = FS::PathCombine(applicationsDir, FS::RemoveInvalidFilenameChars(shortcut.name));
|
||||||
createInstanceShortcut(shortcut, shortcutFilePath);
|
if (!createInstanceShortcut(shortcut, shortcutFilePath))
|
||||||
|
return false;
|
||||||
QMessageBox::information(shortcut.parent, QObject::tr("Create Shortcut"),
|
QMessageBox::information(shortcut.parent, QObject::tr("Create Shortcut"),
|
||||||
QObject::tr("Created a shortcut to this %1 in your applications folder!").arg(shortcut.targetString));
|
QObject::tr("Created a shortcut to this %1 in your applications folder!").arg(shortcut.targetString));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void createInstanceShortcutInOther(const Shortcut& shortcut)
|
bool createInstanceShortcutInOther(const Shortcut& shortcut)
|
||||||
{
|
{
|
||||||
if (!shortcut.instance)
|
if (!shortcut.instance)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
QString defaultedDir = FS::getDesktopDir();
|
QString defaultedDir = FS::getDesktopDir();
|
||||||
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
||||||
|
@ -225,13 +234,15 @@ void createInstanceShortcutInOther(const Shortcut& shortcut)
|
||||||
shortcutFilePath = fileDialog.getSaveFileName(shortcut.parent, QObject::tr("Create Shortcut"), shortcutFilePath,
|
shortcutFilePath = fileDialog.getSaveFileName(shortcut.parent, QObject::tr("Create Shortcut"), shortcutFilePath,
|
||||||
QObject::tr("Desktop Entries") + " (*" + extension + ")");
|
QObject::tr("Desktop Entries") + " (*" + extension + ")");
|
||||||
if (shortcutFilePath.isEmpty())
|
if (shortcutFilePath.isEmpty())
|
||||||
return; // file dialog canceled by user
|
return false; // file dialog canceled by user
|
||||||
|
|
||||||
if (shortcutFilePath.endsWith(extension))
|
if (shortcutFilePath.endsWith(extension))
|
||||||
shortcutFilePath = shortcutFilePath.mid(0, shortcutFilePath.length() - extension.length());
|
shortcutFilePath = shortcutFilePath.mid(0, shortcutFilePath.length() - extension.length());
|
||||||
createInstanceShortcut(shortcut, shortcutFilePath);
|
if (!createInstanceShortcut(shortcut, shortcutFilePath))
|
||||||
|
return false;
|
||||||
QMessageBox::information(shortcut.parent, QObject::tr("Create Shortcut"),
|
QMessageBox::information(shortcut.parent, QObject::tr("Create Shortcut"),
|
||||||
QObject::tr("Created a shortcut to this %1!").arg(shortcut.targetString));
|
QObject::tr("Created a shortcut to this %1!").arg(shortcut.targetString));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ShortcutUtils
|
} // namespace ShortcutUtils
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
namespace ShortcutUtils {
|
namespace ShortcutUtils {
|
||||||
|
@ -49,18 +50,19 @@ struct Shortcut {
|
||||||
QWidget* parent = nullptr;
|
QWidget* parent = nullptr;
|
||||||
QStringList extraArgs = {};
|
QStringList extraArgs = {};
|
||||||
QString iconKey = "";
|
QString iconKey = "";
|
||||||
|
ShortcutTarget target;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Create an instance shortcut on the specified file path
|
/// Create an instance shortcut on the specified file path
|
||||||
void createInstanceShortcut(const Shortcut& shortcut, const QString& filePath);
|
bool createInstanceShortcut(const Shortcut& shortcut, const QString& filePath);
|
||||||
|
|
||||||
/// Create an instance shortcut on the desktop
|
/// Create an instance shortcut on the desktop
|
||||||
void createInstanceShortcutOnDesktop(const Shortcut& shortcut);
|
bool createInstanceShortcutOnDesktop(const Shortcut& shortcut);
|
||||||
|
|
||||||
/// Create an instance shortcut in the Applications directory
|
/// Create an instance shortcut in the Applications directory
|
||||||
void createInstanceShortcutInApplications(const Shortcut& shortcut);
|
bool createInstanceShortcutInApplications(const Shortcut& shortcut);
|
||||||
|
|
||||||
/// Create an instance shortcut in other directories
|
/// Create an instance shortcut in other directories
|
||||||
void createInstanceShortcutInOther(const Shortcut& shortcut);
|
bool createInstanceShortcutInOther(const Shortcut& shortcut);
|
||||||
|
|
||||||
} // namespace ShortcutUtils
|
} // namespace ShortcutUtils
|
||||||
|
|
|
@ -1207,7 +1207,10 @@ void MainWindow::renameGroup(QString group)
|
||||||
|
|
||||||
void MainWindow::undoTrashInstance()
|
void MainWindow::undoTrashInstance()
|
||||||
{
|
{
|
||||||
APPLICATION->instances()->undoTrashInstance();
|
if (!APPLICATION->instances()->undoTrashInstance())
|
||||||
|
QMessageBox::warning(
|
||||||
|
this, tr("Failed to undo trashing instance"),
|
||||||
|
tr("Some instances and shortcuts could not be restored.\nPlease check your trashbin to manually restore them."));
|
||||||
ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething());
|
ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1407,7 +1410,7 @@ void MainWindow::on_actionDeleteInstance_triggered()
|
||||||
auto id = m_selectedInstance->id();
|
auto id = m_selectedInstance->id();
|
||||||
|
|
||||||
auto response = CustomMessageBox::selectable(this, tr("Confirm Deletion"),
|
auto response = CustomMessageBox::selectable(this, tr("Confirm Deletion"),
|
||||||
tr("You are about to delete \"%1\".\n"
|
tr("You are about to delete \"%1\" and all of its shortcut(s).\n"
|
||||||
"This may be permanent and will completely delete the instance.\n\n"
|
"This may be permanent and will completely delete the instance.\n\n"
|
||||||
"Are you sure?")
|
"Are you sure?")
|
||||||
.arg(m_selectedInstance->name()),
|
.arg(m_selectedInstance->name()),
|
||||||
|
|
|
@ -83,12 +83,12 @@ CreateShortcutDialog::CreateShortcutDialog(InstancePtr instance, QWidget* parent
|
||||||
QString applicationDir = FS::getApplicationsDir();
|
QString applicationDir = FS::getApplicationsDir();
|
||||||
|
|
||||||
if (!desktopDir.isEmpty())
|
if (!desktopDir.isEmpty())
|
||||||
ui->saveTargetSelectionBox->addItem(tr("Desktop"), QVariant::fromValue(SaveTarget::Desktop));
|
ui->saveTargetSelectionBox->addItem(tr("Desktop"), QVariant::fromValue(ShortcutTarget::Desktop));
|
||||||
|
|
||||||
if (!applicationDir.isEmpty())
|
if (!applicationDir.isEmpty())
|
||||||
ui->saveTargetSelectionBox->addItem(tr("Applications"), QVariant::fromValue(SaveTarget::Applications));
|
ui->saveTargetSelectionBox->addItem(tr("Applications"), QVariant::fromValue(ShortcutTarget::Applications));
|
||||||
}
|
}
|
||||||
ui->saveTargetSelectionBox->addItem(tr("Other..."), QVariant::fromValue(SaveTarget::Other));
|
ui->saveTargetSelectionBox->addItem(tr("Other..."), QVariant::fromValue(ShortcutTarget::Other));
|
||||||
|
|
||||||
// Populate worlds
|
// Populate worlds
|
||||||
if (m_QuickJoinSupported) {
|
if (m_QuickJoinSupported) {
|
||||||
|
@ -206,17 +206,17 @@ void CreateShortcutDialog::createShortcut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto target = ui->saveTargetSelectionBox->currentData().value<SaveTarget>();
|
auto target = ui->saveTargetSelectionBox->currentData().value<ShortcutTarget>();
|
||||||
auto name = ui->instNameTextBox->text();
|
auto name = ui->instNameTextBox->text();
|
||||||
if (name.isEmpty())
|
if (name.isEmpty())
|
||||||
name = ui->instNameTextBox->placeholderText();
|
name = ui->instNameTextBox->placeholderText();
|
||||||
if (ui->overrideAccountCheckbox->isChecked())
|
if (ui->overrideAccountCheckbox->isChecked())
|
||||||
extraArgs.append({ "--profile", ui->accountSelectionBox->currentData().toString() });
|
extraArgs.append({ "--profile", ui->accountSelectionBox->currentData().toString() });
|
||||||
|
|
||||||
ShortcutUtils::Shortcut args{ m_instance.get(), name, targetString, this, extraArgs, InstIconKey };
|
ShortcutUtils::Shortcut args{ m_instance.get(), name, targetString, this, extraArgs, InstIconKey, target };
|
||||||
if (target == SaveTarget::Desktop)
|
if (target == ShortcutTarget::Desktop)
|
||||||
ShortcutUtils::createInstanceShortcutOnDesktop(args);
|
ShortcutUtils::createInstanceShortcutOnDesktop(args);
|
||||||
else if (target == SaveTarget::Applications)
|
else if (target == ShortcutTarget::Applications)
|
||||||
ShortcutUtils::createInstanceShortcutInApplications(args);
|
ShortcutUtils::createInstanceShortcutInApplications(args);
|
||||||
else
|
else
|
||||||
ShortcutUtils::createInstanceShortcutInOther(args);
|
ShortcutUtils::createInstanceShortcutInOther(args);
|
||||||
|
|
|
@ -54,9 +54,6 @@ class CreateShortcutDialog : public QDialog {
|
||||||
InstancePtr m_instance;
|
InstancePtr m_instance;
|
||||||
bool m_QuickJoinSupported = false;
|
bool m_QuickJoinSupported = false;
|
||||||
|
|
||||||
// Index representations
|
|
||||||
enum class SaveTarget { Desktop, Applications, Other };
|
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
void stateChanged();
|
void stateChanged();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue