Merge pull request #227 from Leo40Git/feature/instance-shortcuts

Closes https://github.com/PrismLauncher/PrismLauncher/issues/210
This commit is contained in:
Sefa Eyeoglu 2022-11-25 13:11:00 +01:00 committed by GitHub
commit fd8b4c5368
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 473 additions and 24 deletions

View File

@ -49,6 +49,7 @@
#include "StringUtils.h"
#if defined Q_OS_WIN32
#define WIN32_LEAN_AND_MEAN
#include <objbase.h>
#include <objidl.h>
#include <shlguid.h>
@ -343,12 +344,37 @@ QString getDesktopDir()
}
// Cross-platform Shortcut creation
bool createShortCut(QString location, QString dest, QStringList args, QString name, QString icon)
bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon)
{
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
location = PathCombine(location, name + ".desktop");
#if defined(Q_OS_MACOS)
destination += ".command";
QFile f(location);
QFile f(destination);
f.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream stream(&f);
QString argstring;
if (!args.empty())
argstring = " \"" + args.join("\" \"") + "\"";
stream << "#!/bin/bash"
<< "\n";
stream << "\""
<< target
<< "\" "
<< argstring
<< "\n";
stream.flush();
f.close();
f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther);
return true;
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
destination += ".desktop";
QFile f(destination);
f.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream stream(&f);
@ -360,10 +386,12 @@ bool createShortCut(QString location, QString dest, QStringList args, QString na
<< "\n";
stream << "Type=Application"
<< "\n";
stream << "TryExec=" << dest.toLocal8Bit() << "\n";
stream << "Exec=" << dest.toLocal8Bit() << argstring.toLocal8Bit() << "\n";
stream << "Exec=\"" << target.toLocal8Bit() << "\"" << argstring.toLocal8Bit() << "\n";
stream << "Name=" << name.toLocal8Bit() << "\n";
if (!icon.isEmpty())
{
stream << "Icon=" << icon.toLocal8Bit() << "\n";
}
stream.flush();
f.close();
@ -371,25 +399,132 @@ bool createShortCut(QString location, QString dest, QStringList args, QString na
f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther);
return true;
#elif defined Q_OS_WIN
// TODO: Fix
// QFile file(PathCombine(location, name + ".lnk"));
// WCHAR *file_w;
// WCHAR *dest_w;
// WCHAR *args_w;
// file.fileName().toWCharArray(file_w);
// dest.toWCharArray(dest_w);
#elif defined(Q_OS_WIN)
QFileInfo targetInfo(target);
// QString argStr;
// for (int i = 0; i < args.count(); i++)
// {
// argStr.append(args[i]);
// argStr.append(" ");
// }
// argStr.toWCharArray(args_w);
// return SUCCEEDED(CreateLink(file_w, dest_w, args_w));
if (!targetInfo.exists())
{
qWarning() << "Target file does not exist!";
return false;
}
target = targetInfo.absoluteFilePath();
if (target.length() >= MAX_PATH)
{
qWarning() << "Target file path is too long!";
return false;
}
if (!icon.isEmpty() && icon.length() >= MAX_PATH)
{
qWarning() << "Icon path is too long!";
return false;
}
destination += ".lnk";
if (destination.length() >= MAX_PATH)
{
qWarning() << "Destination path is too long!";
return false;
}
QString argStr;
int argCount = args.count();
for (int i = 0; i < argCount; i++)
{
if (args[i].contains(' '))
{
argStr.append('"').append(args[i]).append('"');
}
else
{
argStr.append(args[i]);
}
if (i < argCount - 1)
{
argStr.append(" ");
}
}
if (argStr.length() >= MAX_PATH)
{
qWarning() << "Arguments string is too long!";
return false;
}
HRESULT hres;
// ...yes, you need to initialize the entire COM stack just to make a shortcut
hres = CoInitialize(nullptr);
if (FAILED(hres))
{
qWarning() << "Failed to initialize COM!";
return false;
}
WCHAR wsz[MAX_PATH];
IShellLink* psl;
// create an IShellLink instance - this stores the shortcut's attributes
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres))
{
wmemset(wsz, 0, MAX_PATH);
target.toWCharArray(wsz);
psl->SetPath(wsz);
wmemset(wsz, 0, MAX_PATH);
argStr.toWCharArray(wsz);
psl->SetArguments(wsz);
wmemset(wsz, 0, MAX_PATH);
targetInfo.absolutePath().toWCharArray(wsz);
psl->SetWorkingDirectory(wsz); // "Starts in" attribute
if (!icon.isEmpty())
{
wmemset(wsz, 0, MAX_PATH);
icon.toWCharArray(wsz);
psl->SetIconLocation(wsz, 0);
}
// query an IPersistFile interface from our IShellLink instance
// this is the interface that will actually let us save the shortcut to disk!
IPersistFile* ppf;
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres))
{
wmemset(wsz, 0, MAX_PATH);
destination.toWCharArray(wsz);
hres = ppf->Save(wsz, TRUE);
if (FAILED(hres))
{
qWarning() << "IPresistFile->Save() failed";
qWarning() << "hres = " << hres;
}
ppf->Release();
}
else
{
qWarning() << "Failed to query IPersistFile interface from IShellLink instance";
qWarning() << "hres = " << hres;
}
psl->Release();
}
else
{
qWarning() << "Failed to create IShellLink instance";
qWarning() << "hres = " << hres;
}
// go away COM, nobody likes you
CoUninitialize();
return SUCCEEDED(hres);
#else
qWarning("Desktop Shortcuts not supported on your platform!");
return false;

View File

@ -172,4 +172,9 @@ QString getDesktopDir();
// Overrides one folder with the contents of another, preserving items exclusive to the first folder
// Equivalent to doing QDir::rename, but allowing for overrides
bool overrideFolder(QString overwritten_path, QString override_path);
/**
* Creates a shortcut to the specified target file at the specified destination path.
*/
bool createShortcut(QString destination, QString target, QStringList args, QString name, QString icon);
}

View File

@ -39,5 +39,6 @@
<file>scalable/export.svg</file>
<file>scalable/rename.svg</file>
<file>scalable/launch.svg</file>
<file>scalable/shortcut.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve">
<rect fill="none" width="24" height="24"/>
<g id="_x35__1_">
<g>
<path fill="#585858" d="M9.5,9.5C9.8,9.5,10,9.2,10,9l0-2.4l7.6,7.3c0.2,0.2,0.5,0.2,0.7,0c0.2-0.2,0.2-0.5,0-0.7L10.8,6L13,6
c0.3,0,0.5-0.2,0.5-0.5S13.3,5,13,5H9.5C9.2,5,9,5.2,9,5.5V9C9,9.2,9.2,9.5,9.5,9.5z M21,5h-5.5v1H21c0.5,0,1,0.5,1,1l0,10
c0,0.5-0.4,1-1,1l-10,0c-0.5,0-1-0.5-1-1v-5.5H9V17c0,1.1,1.1,2,2.2,2H21c1.1,0,2-0.9,2-2V7.2C23,6.1,22.1,5,21,5z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 886 B

View File

@ -39,5 +39,6 @@
<file>scalable/export.svg</file>
<file>scalable/rename.svg</file>
<file>scalable/launch.svg</file>
<file>scalable/shortcut.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
<g id="_x35__5_">
<g>
<path fill="#3366CC" d="M3,11c0.6,0,1-0.5,1-1l0-4.8l15.2,14.5c0.4,0.4,1,0.4,1.4,0c0.4-0.4,0.4-1,0-1.4L5.6,4L10,4
c0.6,0,1-0.5,1-1s-0.4-1-1-1H3C2.5,2,2,2.4,2,3v7C2,10.5,2.4,11,3,11z M26,2H15v2h11c1.1,0,2,0.9,2,2l0,20.1c0,1.1-0.9,2-2,2L6,28
c-1.1,0-2-0.9-2-2V15H2v11c0,2.2,2.2,4,4.4,4h19.7c2.2,0,3.9-1.8,3.9-3.9V6.4C30,4.2,28.2,2,26,2z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 824 B

View File

@ -39,5 +39,6 @@
<file>scalable/export.svg</file>
<file>scalable/rename.svg</file>
<file>scalable/launch.svg</file>
<file>scalable/shortcut.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#3366CC" d="M6,32h20c3.3,0,6-2.7,6-6V6c0-3.3-2.7-6-6-6h-9.1
C17.6,1.2,18,2.6,18,4h8c1.1,0,2,0.9,2,2v20c0,1.1-0.9,2-2,2H6c-1.1,0-2-0.9-2-2v-4.5l-4-3V26C0,29.3,2.7,32,6,32z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#39B54A" d="M8.8,17.6C9.2,17.9,9.6,18,10,18c0.3,0,0.6-0.1,0.9-0.2
c0.7-0.3,1.1-1,1.1-1.8v-1.9V14c6.3,0,11.7,4.2,13.4,10c0.4-1.3,0.6-2.6,0.6-4c0-7.7-6.3-14-14-14V4c0-0.8-0.4-1.5-1.1-1.8
C10.6,2.1,10.3,2,10,2C9.6,2,9.2,2.1,8.8,2.4l-8,6C0.3,8.8,0,9.4,0,10c0,0.6,0.3,1.2,0.8,1.6L8.8,17.6z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -39,5 +39,6 @@
<file>scalable/export.svg</file>
<file>scalable/rename.svg</file>
<file>scalable/launch.svg</file>
<file>scalable/shortcut.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
<g>
<path fill="#39B54A" d="M26,0h-9.1C17.6,1.2,18,2.6,18,4h8c1.1,0,2,0.9,2,2v3h4V6C32,2.7,29.3,0,26,0z"/>
<path fill="#8C6239" d="M28,26c0,1.1-0.9,2-2,2H6c-1.1,0-2-0.9-2-2v-4.5l-4-3V26c0,3.3,2.7,6,6,6h20c3.3,0,6-2.7,6-6V9h-4V26z"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#009245" d="M8.8,17.6C9.2,17.9,9.6,18,10,18c0.3,0,0.6-0.1,0.9-0.2
c0.7-0.3,1.1-1,1.1-1.8v-1.9V14c6.3,0,11.7,4.2,13.4,10c0.4-1.3,0.6-2.6,0.6-4c0-7.7-6.3-14-14-14V4c0-0.8-0.4-1.5-1.1-1.8
C10.6,2.1,10.3,2,10,2C9.6,2,9.2,2.1,8.8,2.4l-8,6C0.3,8.8,0,9.4,0,10c0,0.6,0.3,1.2,0.8,1.6L8.8,17.6z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -39,5 +39,6 @@
<file>scalable/export.svg</file>
<file>scalable/rename.svg</file>
<file>scalable/launch.svg</file>
<file>scalable/shortcut.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6,32h20c3.3,0,6-2.7,6-6V6c0-3.3-2.7-6-6-6h-9.1C17.6,1.2,18,2.6,18,4h8
c1.1,0,2,0.9,2,2v20c0,1.1-0.9,2-2,2H6c-1.1,0-2-0.9-2-2v-4.5l-4-3V26C0,29.3,2.7,32,6,32z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#666666" d="M8.8,17.6C9.2,17.9,9.6,18,10,18c0.3,0,0.6-0.1,0.9-0.2
c0.7-0.3,1.1-1,1.1-1.8v-1.9V14c6.3,0,11.7,4.2,13.4,10c0.4-1.3,0.6-2.6,0.6-4c0-7.7-6.3-14-14-14V4c0-0.8-0.4-1.5-1.1-1.8
C10.6,2.1,10.3,2,10,2C9.6,2,9.2,2.1,8.8,2.4l-8,6C0.3,8.8,0,9.4,0,10c0,0.6,0.3,1.2,0.8,1.6L8.8,17.6z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -39,5 +39,6 @@
<file>scalable/export.svg</file>
<file>scalable/rename.svg</file>
<file>scalable/launch.svg</file>
<file>scalable/shortcut.svg</file>
</qresource>
</RCC>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 32 32" enable-background="new 0 0 32 32" xml:space="preserve">
<path fill-rule="evenodd" clip-rule="evenodd" fill="#F2F2F2" d="M6,32h20c3.3,0,6-2.7,6-6V6c0-3.3-2.7-6-6-6h-9.1
C17.6,1.2,18,2.6,18,4h8c1.1,0,2,0.9,2,2v20c0,1.1-0.9,2-2,2H6c-1.1,0-2-0.9-2-2v-4.5l-4-3V26C0,29.3,2.7,32,6,32z"/>
<path fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" d="M8.8,17.6C9.2,17.9,9.6,18,10,18c0.3,0,0.6-0.1,0.9-0.2
c0.7-0.3,1.1-1,1.1-1.8v-1.9V14c6.3,0,11.7,4.2,13.4,10c0.4-1.3,0.6-2.6,0.6-4c0-7.7-6.3-14-14-14V4c0-0.8-0.4-1.5-1.1-1.8
C10.6,2.1,10.3,2,10,2C9.6,2,9.2,2.1,8.8,2.4l-8,6C0.3,8.8,0,9.4,0,10c0,0.6,0.3,1.2,0.8,1.6L8.8,17.6z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -39,6 +39,7 @@
#include "Application.h"
#include "BuildConfig.h"
#include "FileSystem.h"
#include "MainWindow.h"
@ -239,6 +240,7 @@ public:
TranslatedAction actionLaunchInstanceOffline;
TranslatedAction actionLaunchInstanceDemo;
TranslatedAction actionExportInstance;
TranslatedAction actionCreateInstanceShortcut;
QVector<TranslatedAction *> all_actions;
LabeledToolButton *renameButton = nullptr;
@ -626,6 +628,7 @@ public:
actionExportInstance->setEnabled(enabled);
actionDeleteInstance->setEnabled(enabled);
actionCopyInstance->setEnabled(enabled);
actionCreateInstanceShortcut->setEnabled(enabled);
}
void createStatusBar(QMainWindow *MainWindow)
@ -764,6 +767,15 @@ public:
actionCopyInstance->setIcon(APPLICATION->getThemedIcon("copy"));
all_actions.append(&actionCopyInstance);
actionCreateInstanceShortcut = TranslatedAction(MainWindow);
actionCreateInstanceShortcut->setObjectName(QStringLiteral("actionCreateInstanceShortcut"));
actionCreateInstanceShortcut.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Create Shortcut"));
actionCreateInstanceShortcut.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Creates a shortcut on your desktop to launch the selected instance."));
//actionCreateInstanceShortcut->setShortcut(QKeySequence(tr("Ctrl+D"))); // TODO
// FIXME missing on Legacy, Flat and Flat (White)
actionCreateInstanceShortcut->setIcon(APPLICATION->getThemedIcon("shortcut"));
all_actions.append(&actionCreateInstanceShortcut);
setInstanceActionsEnabled(false);
}
@ -802,6 +814,8 @@ public:
instanceToolBar->addAction(actionCopyInstance);
instanceToolBar->addAction(actionDeleteInstance);
instanceToolBar->addAction(actionCreateInstanceShortcut); // TODO find better position for this
QLayout * lay = instanceToolBar->layout();
for(int i = 0; i < lay->count(); i++)
{
@ -2161,6 +2175,130 @@ void MainWindow::on_actionKillInstance_triggered()
}
}
void MainWindow::on_actionCreateInstanceShortcut_triggered()
{
if (m_selectedInstance)
{
auto desktopPath = FS::getDesktopDir();
if (desktopPath.isEmpty()) {
// TODO come up with an alternative solution (open "save file" dialog)
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Couldn't find desktop?!"));
return;
}
#if defined(Q_OS_MACOS)
QString appPath = QApplication::applicationFilePath();
if (appPath.startsWith("/private/var/")) {
QMessageBox::critical(this, tr("Create instance shortcut"), tr("The launcher is in the folder it was extracted from, therefore it cannot create shortcuts."));
return;
}
if (FS::createShortcut(FS::PathCombine(desktopPath, m_selectedInstance->name()),
appPath, { "--launch", m_selectedInstance->id() },
m_selectedInstance->name(), "")) {
QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!"));
}
else
{
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!"));
}
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
QString appPath = QApplication::applicationFilePath();
if (appPath.startsWith("/tmp/.mount_")) {
// AppImage!
appPath = QProcessEnvironment::systemEnvironment().value(QStringLiteral("APPIMAGE"));
if (appPath.isEmpty())
{
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Launcher is running as misconfigured AppImage? ($APPIMAGE environment variable is missing)"));
}
else if (appPath.endsWith("/"))
{
appPath.chop(1);
}
}
auto icon = APPLICATION->icons()->icon(m_selectedInstance->iconKey());
if (icon == nullptr)
{
icon = APPLICATION->icons()->icon("grass");
}
QString iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "icon.png");
QFile iconFile(iconPath);
if (!iconFile.open(QFile::WriteOnly))
{
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut."));
return;
}
bool success = icon->icon().pixmap(64, 64).save(&iconFile, "PNG");
iconFile.close();
if (!success)
{
iconFile.remove();
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut."));
return;
}
if (FS::createShortcut(FS::PathCombine(desktopPath, m_selectedInstance->name()),
appPath, { "--launch", m_selectedInstance->id() },
m_selectedInstance->name(), iconPath)) {
QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!"));
}
else
{
iconFile.remove();
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!"));
}
#elif defined(Q_OS_WIN)
auto icon = APPLICATION->icons()->icon(m_selectedInstance->iconKey());
if (icon == nullptr)
{
icon = APPLICATION->icons()->icon("grass");
}
QString iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "icon.ico");
// part of fix for weird bug involving the window icon being replaced
// dunno why it happens, but this 2-line fix seems to be enough, so w/e
auto appIcon = APPLICATION->getThemedIcon("logo");
QFile iconFile(iconPath);
if (!iconFile.open(QFile::WriteOnly))
{
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut."));
return;
}
bool success = icon->icon().pixmap(64, 64).save(&iconFile, "ICO");
iconFile.close();
// restore original window icon
QGuiApplication::setWindowIcon(appIcon);
if (!success)
{
iconFile.remove();
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create icon for shortcut."));
return;
}
if (FS::createShortcut(FS::PathCombine(desktopPath, m_selectedInstance->name()),
QApplication::applicationFilePath(), { "--launch", m_selectedInstance->id() },
m_selectedInstance->name(), iconPath)) {
QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!"));
}
else
{
iconFile.remove();
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!"));
}
#else
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Not supported on your platform!"));
#endif
}
}
void MainWindow::taskEnd()
{
QObject *sender = QObject::sender();

View File

@ -161,6 +161,8 @@ private slots:
void on_actionEditInstance_triggered();
void on_actionCreateInstanceShortcut_triggered();
void taskEnd();
/**