Merge pull request #227 from Leo40Git/feature/instance-shortcuts
Closes https://github.com/PrismLauncher/PrismLauncher/issues/210
This commit is contained in:
commit
fd8b4c5368
@ -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";
|
||||
stream << "Icon=" << icon.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);
|
||||
if (!targetInfo.exists())
|
||||
{
|
||||
qWarning() << "Target file does not exist!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// return SUCCEEDED(CreateLink(file_w, dest_w, args_w));
|
||||
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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>
|
||||
|
14
launcher/resources/OSX/scalable/shortcut.svg
Normal file
14
launcher/resources/OSX/scalable/shortcut.svg
Normal 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 |
@ -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>
|
||||
|
13
launcher/resources/iOS/scalable/shortcut.svg
Normal file
13
launcher/resources/iOS/scalable/shortcut.svg
Normal 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 |
@ -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>
|
||||
|
41
launcher/resources/pe_blue/scalable/shortcut.svg
Normal file
41
launcher/resources/pe_blue/scalable/shortcut.svg
Normal 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 |
@ -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>
|
||||
|
13
launcher/resources/pe_colored/scalable/shortcut.svg
Normal file
13
launcher/resources/pe_colored/scalable/shortcut.svg
Normal 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 |
@ -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>
|
||||
|
41
launcher/resources/pe_dark/scalable/shortcut.svg
Normal file
41
launcher/resources/pe_dark/scalable/shortcut.svg
Normal 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 |
@ -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>
|
||||
|
41
launcher/resources/pe_light/scalable/shortcut.svg
Normal file
41
launcher/resources/pe_light/scalable/shortcut.svg
Normal 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 |
@ -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();
|
||||
|
@ -161,6 +161,8 @@ private slots:
|
||||
|
||||
void on_actionEditInstance_triggered();
|
||||
|
||||
void on_actionCreateInstanceShortcut_triggered();
|
||||
|
||||
void taskEnd();
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user