Windows: implement FS::createShortcut
Signed-off-by: ADudeCalledLeo <7997354+Leo40Git@users.noreply.github.com>
This commit is contained in:
parent
30b266622c
commit
70768189ba
@ -49,6 +49,7 @@
|
|||||||
#include "StringUtils.h"
|
#include "StringUtils.h"
|
||||||
|
|
||||||
#if defined Q_OS_WIN32
|
#if defined Q_OS_WIN32
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <objbase.h>
|
#include <objbase.h>
|
||||||
#include <objidl.h>
|
#include <objidl.h>
|
||||||
#include <shlguid.h>
|
#include <shlguid.h>
|
||||||
@ -339,12 +340,12 @@ QString getDesktopDir()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Cross-platform Shortcut creation
|
// 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)
|
#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
|
||||||
location = PathCombine(location, name + ".desktop");
|
destination = PathCombine(destination, name + ".desktop");
|
||||||
|
|
||||||
QFile f(location);
|
QFile f(destination);
|
||||||
f.open(QIODevice::WriteOnly | QIODevice::Text);
|
f.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||||
QTextStream stream(&f);
|
QTextStream stream(&f);
|
||||||
|
|
||||||
@ -356,10 +357,13 @@ bool createShortCut(QString location, QString dest, QStringList args, QString na
|
|||||||
<< "\n";
|
<< "\n";
|
||||||
stream << "Type=Application"
|
stream << "Type=Application"
|
||||||
<< "\n";
|
<< "\n";
|
||||||
stream << "TryExec=" << dest.toLocal8Bit() << "\n";
|
stream << "TryExec=" << target.toLocal8Bit() << "\n";
|
||||||
stream << "Exec=" << dest.toLocal8Bit() << argstring.toLocal8Bit() << "\n";
|
stream << "Exec=" << target.toLocal8Bit() << argstring.toLocal8Bit() << "\n";
|
||||||
stream << "Name=" << name.toLocal8Bit() << "\n";
|
stream << "Name=" << name.toLocal8Bit() << "\n";
|
||||||
|
if (!icon.isEmpty())
|
||||||
|
{
|
||||||
stream << "Icon=" << icon.toLocal8Bit() << "\n";
|
stream << "Icon=" << icon.toLocal8Bit() << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
stream.flush();
|
stream.flush();
|
||||||
f.close();
|
f.close();
|
||||||
@ -368,24 +372,121 @@ bool createShortCut(QString location, QString dest, QStringList args, QString na
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
#elif defined Q_OS_WIN
|
#elif defined Q_OS_WIN
|
||||||
// TODO: Fix
|
QFileInfo targetInfo(target);
|
||||||
// QFile file(PathCombine(location, name + ".lnk"));
|
|
||||||
// WCHAR *file_w;
|
|
||||||
// WCHAR *dest_w;
|
|
||||||
// WCHAR *args_w;
|
|
||||||
// file.fileName().toWCharArray(file_w);
|
|
||||||
// dest.toWCharArray(dest_w);
|
|
||||||
|
|
||||||
// QString argStr;
|
if (!targetInfo.exists())
|
||||||
// for (int i = 0; i < args.count(); i++)
|
{
|
||||||
// {
|
qWarning() << "Target file does not exist!";
|
||||||
// argStr.append(args[i]);
|
|
||||||
// argStr.append(" ");
|
|
||||||
// }
|
|
||||||
// argStr.toWCharArray(args_w);
|
|
||||||
|
|
||||||
// return SUCCEEDED(CreateLink(file_w, dest_w, args_w));
|
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
WCHAR wsz[MAX_PATH];
|
||||||
|
|
||||||
|
// ...yes, you need to initialize the entire COM stack to make a shortcut in Windows
|
||||||
|
CoInitialize(nullptr);
|
||||||
|
|
||||||
|
HRESULT hres;
|
||||||
|
IShellLink* psl;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!icon.isEmpty())
|
||||||
|
{
|
||||||
|
wmemset(wsz, 0, MAX_PATH);
|
||||||
|
icon.toWCharArray(wsz);
|
||||||
|
psl->SetIconLocation(wsz, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoUninitialize();
|
||||||
|
|
||||||
|
return SUCCEEDED(hres);
|
||||||
#else
|
#else
|
||||||
qWarning("Desktop Shortcuts not supported on your platform!");
|
qWarning("Desktop Shortcuts not supported on your platform!");
|
||||||
return false;
|
return false;
|
||||||
|
@ -156,4 +156,9 @@ QString getDesktopDir();
|
|||||||
// Overrides one folder with the contents of another, preserving items exclusive to the first folder
|
// Overrides one folder with the contents of another, preserving items exclusive to the first folder
|
||||||
// Equivalent to doing QDir::rename, but allowing for overrides
|
// Equivalent to doing QDir::rename, but allowing for overrides
|
||||||
bool overrideFolder(QString overwritten_path, QString override_path);
|
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,6 +39,7 @@
|
|||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "BuildConfig.h"
|
#include "BuildConfig.h"
|
||||||
|
#include "FileSystem.h"
|
||||||
|
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
|
||||||
@ -739,9 +740,9 @@ public:
|
|||||||
|
|
||||||
actionCreateInstanceShortcut = TranslatedAction(MainWindow);
|
actionCreateInstanceShortcut = TranslatedAction(MainWindow);
|
||||||
actionCreateInstanceShortcut->setObjectName(QStringLiteral("actionCreateInstanceShortcut"));
|
actionCreateInstanceShortcut->setObjectName(QStringLiteral("actionCreateInstanceShortcut"));
|
||||||
actionCreateInstanceShortcut.setTextId(QT_TRANSLATE_NOOP("MainWindow", "Create shortcut"));
|
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.setTooltipId(QT_TRANSLATE_NOOP("MainWindow", "Creates a shortcut on your desktop to launch the selected instance."));
|
||||||
actionCreateInstanceShortcut->setShortcut(QKeySequence(tr("Ctrl+D")));
|
//actionCreateInstanceShortcut->setShortcut(QKeySequence(tr("Ctrl+D"))); // TODO
|
||||||
//actionCreateInstanceShortcut->setIcon(APPLICATION->getThemedIcon("copy")); // TODO
|
//actionCreateInstanceShortcut->setIcon(APPLICATION->getThemedIcon("copy")); // TODO
|
||||||
all_actions.append(&actionCreateInstanceShortcut);
|
all_actions.append(&actionCreateInstanceShortcut);
|
||||||
|
|
||||||
@ -793,7 +794,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceToolBar->addAction(actionCreateInstanceShortcut);
|
instanceToolBar->addAction(actionCreateInstanceShortcut); // TODO find better position for this
|
||||||
|
|
||||||
all_toolbars.append(&instanceToolBar);
|
all_toolbars.append(&instanceToolBar);
|
||||||
MainWindow->addToolBar(Qt::RightToolBarArea, instanceToolBar);
|
MainWindow->addToolBar(Qt::RightToolBarArea, instanceToolBar);
|
||||||
@ -2087,76 +2088,39 @@ void MainWindow::on_actionKillInstance_triggered()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include "windows.h"
|
|
||||||
#include "winnls.h"
|
|
||||||
#include "shobjidl.h"
|
|
||||||
#include "objbase.h"
|
|
||||||
#include "objidl.h"
|
|
||||||
#include "shlguid.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void MainWindow::on_actionCreateInstanceShortcut_triggered()
|
void MainWindow::on_actionCreateInstanceShortcut_triggered()
|
||||||
{
|
{
|
||||||
if (m_selectedInstance)
|
if (m_selectedInstance)
|
||||||
{
|
{
|
||||||
auto desktopDir = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
|
auto desktopPath = FS::getDesktopDir();
|
||||||
if (desktopDir.isEmpty()) {
|
if (desktopPath.isEmpty()) {
|
||||||
// TODO come up with an alternative solution (open "save file" dialog)
|
// TODO come up with an alternative solution (open "save file" dialog)
|
||||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Couldn't find desktop!"));
|
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Couldn't find desktop?!"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_MACOS)
|
||||||
// Windows
|
|
||||||
WCHAR wsz[MAX_PATH];
|
|
||||||
|
|
||||||
// ...yes, you need to initialize the entire COM stack to make a shortcut in Windows.
|
|
||||||
// I hate it.
|
|
||||||
CoInitialize(nullptr);
|
|
||||||
|
|
||||||
HRESULT hres;
|
|
||||||
IShellLink* psl;
|
|
||||||
|
|
||||||
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
|
|
||||||
if (SUCCEEDED(hres))
|
|
||||||
{
|
|
||||||
IPersistFile* ppf;
|
|
||||||
|
|
||||||
QApplication::applicationFilePath().left(MAX_PATH - 1).toWCharArray(wsz);
|
|
||||||
psl->SetPath(wsz);
|
|
||||||
|
|
||||||
wmemset(wsz, 0, MAX_PATH);
|
|
||||||
QStringLiteral("--launch %1").arg(m_selectedInstance->id()).left(MAX_PATH - 1).toWCharArray(wsz);
|
|
||||||
psl->SetArguments(wsz);
|
|
||||||
|
|
||||||
// TODO set icon
|
|
||||||
|
|
||||||
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hres))
|
|
||||||
{
|
|
||||||
wmemset(wsz, 0, MAX_PATH);
|
|
||||||
|
|
||||||
desktopDir
|
|
||||||
.append('/')
|
|
||||||
.append(QStringLiteral("%1.lnk").arg(m_selectedInstance->name()))
|
|
||||||
.left(MAX_PATH - 1).toWCharArray(wsz);
|
|
||||||
|
|
||||||
hres = ppf->Save(wsz, TRUE);
|
|
||||||
ppf->Release();
|
|
||||||
}
|
|
||||||
psl->Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
CoUninitialize();
|
|
||||||
#elif defined(Q_OS_LINUX)
|
|
||||||
// Linux
|
|
||||||
#elif defined(Q_OS_MACOS)
|
|
||||||
// macOSX
|
// macOSX
|
||||||
// TODO actually write this path
|
// TODO actually write this path
|
||||||
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Not supported on macOSX yet!"));
|
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Not supported on macOSX yet!"));
|
||||||
|
#else
|
||||||
|
QString iconPath;
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
// TODO
|
||||||
|
// need to convert icon to ICO format and save it somewhere...
|
||||||
|
iconPath = "";
|
||||||
|
#elif defined(Q_OS_UNIX)
|
||||||
|
iconPath = ""; // TODO get instance icon path
|
||||||
|
#endif
|
||||||
|
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
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!"));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user