Merge pull request #246 from DanielSvoboda/Create-Shortcut
Create shortcut
This commit is contained in:
commit
3f3acc5543
|
@ -3,15 +3,31 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
|
#include <QFile>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
|
#include <QImage>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QStandardPaths>
|
||||||
#include <QTableWidget>
|
#include <QTableWidget>
|
||||||
|
#include <QTextStream>
|
||||||
#include <QTreeWidget>
|
#include <QTreeWidget>
|
||||||
#include <QTreeWidgetItem>
|
#include <QTreeWidgetItem>
|
||||||
|
|
||||||
#include "game_info.h"
|
#include "game_info.h"
|
||||||
#include "trophy_viewer.h"
|
#include "trophy_viewer.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
#include <ShlObj.h>
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <objbase.h>
|
||||||
|
#include <shlguid.h>
|
||||||
|
#include <shobjidl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
class GuiContextMenus : public QObject {
|
class GuiContextMenus : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
|
@ -27,13 +43,16 @@ public:
|
||||||
|
|
||||||
// Setup menu.
|
// Setup menu.
|
||||||
QMenu menu(widget);
|
QMenu menu(widget);
|
||||||
|
QAction createShortcut("Create Shortcut", widget);
|
||||||
QAction openFolder("Open Game Folder", widget);
|
QAction openFolder("Open Game Folder", widget);
|
||||||
QAction openSfoViewer("SFO Viewer", widget);
|
QAction openSfoViewer("SFO Viewer", widget);
|
||||||
QAction openTrophyViewer("Trophy Viewer", widget);
|
QAction openTrophyViewer("Trophy Viewer", widget);
|
||||||
|
|
||||||
|
menu.addAction(&createShortcut);
|
||||||
menu.addAction(&openFolder);
|
menu.addAction(&openFolder);
|
||||||
menu.addAction(&openSfoViewer);
|
menu.addAction(&openSfoViewer);
|
||||||
menu.addAction(&openTrophyViewer);
|
menu.addAction(&openTrophyViewer);
|
||||||
|
|
||||||
// Show menu.
|
// Show menu.
|
||||||
auto selected = menu.exec(global_pos);
|
auto selected = menu.exec(global_pos);
|
||||||
if (!selected) {
|
if (!selected) {
|
||||||
|
@ -105,6 +124,69 @@ public:
|
||||||
connect(widget->parent(), &QWidget::destroyed, trophyViewer,
|
connect(widget->parent(), &QWidget::destroyed, trophyViewer,
|
||||||
[widget, trophyViewer]() { trophyViewer->deleteLater(); });
|
[widget, trophyViewer]() { trophyViewer->deleteLater(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (selected == &createShortcut) {
|
||||||
|
QString targetPath = QString::fromStdString(m_games[itemID].path);
|
||||||
|
QString ebootPath = targetPath + "/eboot.bin";
|
||||||
|
|
||||||
|
// Get the full path to the icon
|
||||||
|
QString iconPath = QString::fromStdString(m_games[itemID].icon_path);
|
||||||
|
QFileInfo iconFileInfo(iconPath);
|
||||||
|
QString icoPath = iconFileInfo.absolutePath() + "/" + iconFileInfo.baseName() + ".ico";
|
||||||
|
|
||||||
|
// Path to shortcut/link
|
||||||
|
QString linkPath;
|
||||||
|
|
||||||
|
// Path to the shadps4.exe executable
|
||||||
|
QString exePath;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
linkPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/" +
|
||||||
|
QString::fromStdString(m_games[itemID].name) + ".lnk";
|
||||||
|
|
||||||
|
exePath = QCoreApplication::applicationFilePath().replace("\\", "/");
|
||||||
|
|
||||||
|
#else
|
||||||
|
linkPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/" +
|
||||||
|
QString::fromStdString(m_games[itemID].name);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Convert the icon to .ico if necessary
|
||||||
|
if (iconFileInfo.suffix().toLower() == "png") {
|
||||||
|
// Convert icon from PNG to ICO
|
||||||
|
if (convertPngToIco(iconPath, icoPath)) {
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
if (createShortcutWin(linkPath, ebootPath, icoPath, exePath)) {
|
||||||
|
#else
|
||||||
|
if (createShortcutLinux(linkPath, ebootPath, iconPath)) {
|
||||||
|
#endif
|
||||||
|
QMessageBox::information(
|
||||||
|
nullptr, "Shortcut Creation",
|
||||||
|
QString("Shortcut created successfully:\n %1").arg(linkPath));
|
||||||
|
} else {
|
||||||
|
QMessageBox::critical(
|
||||||
|
nullptr, "Error",
|
||||||
|
QString("Error creating shortcut:\n %1").arg(linkPath));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QMessageBox::critical(nullptr, "Error", "Failed to convert icon.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// If the icon is already in ICO format, we just create the shortcut
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
if (createShortcutWin(linkPath, ebootPath, iconPath, exePath)) {
|
||||||
|
#else
|
||||||
|
if (createShortcutLinux(linkPath, ebootPath, iconPath)) {
|
||||||
|
#endif
|
||||||
|
QMessageBox::information(
|
||||||
|
nullptr, "Shortcut Creation",
|
||||||
|
QString("Shortcut created successfully:\n %1").arg(linkPath));
|
||||||
|
} else {
|
||||||
|
QMessageBox::critical(nullptr, "Error",
|
||||||
|
QString("Error creating shortcut:\n %1").arg(linkPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetRowIndex(QTreeWidget* treeWidget, QTreeWidgetItem* item) {
|
int GetRowIndex(QTreeWidget* treeWidget, QTreeWidgetItem* item) {
|
||||||
|
@ -155,4 +237,88 @@ public:
|
||||||
InstallDragDropPkg(path, 1, 1);
|
InstallDragDropPkg(path, 1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool convertPngToIco(const QString& pngFilePath, const QString& icoFilePath) {
|
||||||
|
// Load the PNG image
|
||||||
|
QImage image(pngFilePath);
|
||||||
|
if (image.isNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale the image to the default icon size (256x256 pixels)
|
||||||
|
QImage scaledImage =
|
||||||
|
image.scaled(QSize(256, 256), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
|
|
||||||
|
// Convert the image to QPixmap
|
||||||
|
QPixmap pixmap = QPixmap::fromImage(scaledImage);
|
||||||
|
|
||||||
|
// Save the pixmap as an ICO file
|
||||||
|
if (pixmap.save(icoFilePath, "ICO")) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
bool createShortcutWin(const QString& linkPath, const QString& targetPath,
|
||||||
|
const QString& iconPath, const QString& exePath) {
|
||||||
|
CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||||
|
|
||||||
|
// Create the ShellLink object
|
||||||
|
IShellLink* pShellLink = nullptr;
|
||||||
|
HRESULT hres = CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER,
|
||||||
|
IID_IShellLink, (LPVOID*)&pShellLink);
|
||||||
|
if (SUCCEEDED(hres)) {
|
||||||
|
// Defines the path to the program executable
|
||||||
|
pShellLink->SetPath((LPCWSTR)exePath.utf16());
|
||||||
|
|
||||||
|
// Sets the home directory ("Start in")
|
||||||
|
pShellLink->SetWorkingDirectory((LPCWSTR)QFileInfo(exePath).absolutePath().utf16());
|
||||||
|
|
||||||
|
// Set arguments, eboot.bin file location
|
||||||
|
QString arguments = QString("\"%1\"").arg(targetPath);
|
||||||
|
pShellLink->SetArguments((LPCWSTR)arguments.utf16());
|
||||||
|
|
||||||
|
// Set the icon for the shortcut
|
||||||
|
pShellLink->SetIconLocation((LPCWSTR)iconPath.utf16(), 0);
|
||||||
|
|
||||||
|
// Save the shortcut
|
||||||
|
IPersistFile* pPersistFile = nullptr;
|
||||||
|
hres = pShellLink->QueryInterface(IID_IPersistFile, (LPVOID*)&pPersistFile);
|
||||||
|
if (SUCCEEDED(hres)) {
|
||||||
|
hres = pPersistFile->Save((LPCWSTR)linkPath.utf16(), TRUE);
|
||||||
|
pPersistFile->Release();
|
||||||
|
}
|
||||||
|
pShellLink->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
CoUninitialize();
|
||||||
|
|
||||||
|
return SUCCEEDED(hres);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
bool createShortcutLinux(const QString& linkPath, const QString& targetPath,
|
||||||
|
const QString& iconPath) {
|
||||||
|
QFile shortcutFile(linkPath);
|
||||||
|
if (!shortcutFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
|
QMessageBox::critical(nullptr, "Error",
|
||||||
|
QString("Error creating shortcut:\n %1").arg(linkPath));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextStream out(&shortcutFile);
|
||||||
|
out << "[Desktop Entry]\n";
|
||||||
|
out << "Version=1.0\n";
|
||||||
|
out << "Name=" << QFileInfo(targetPath).baseName() << "\n";
|
||||||
|
out << "Exec=" << QCoreApplication::applicationFilePath() << " \"" << targetPath << "\"\n";
|
||||||
|
out << "Icon=" << iconPath << "\n";
|
||||||
|
out << "Terminal=false\n";
|
||||||
|
out << "Type=Application\n";
|
||||||
|
shortcutFile.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,10 +8,16 @@
|
||||||
#include "qt_gui/game_install_dialog.h"
|
#include "qt_gui/game_install_dialog.h"
|
||||||
#include "qt_gui/main_window.h"
|
#include "qt_gui/main_window.h"
|
||||||
|
|
||||||
|
#include <emulator.h>
|
||||||
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
// Custom message handler to ignore Qt logs
|
||||||
void customMessageHandler(QtMsgType, const QMessageLogContext&, const QString&) {}
|
void customMessageHandler(QtMsgType, const QMessageLogContext&, const QString&) {}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
|
|
||||||
|
// Load configurations and initialize Qt application
|
||||||
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
|
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
|
||||||
Config::load(config_dir / "config.toml");
|
Config::load(config_dir / "config.toml");
|
||||||
QString gameDataPath = qApp->applicationDirPath() + "/game_data/";
|
QString gameDataPath = qApp->applicationDirPath() + "/game_data/";
|
||||||
|
@ -23,14 +29,25 @@ int main(int argc, char* argv[]) {
|
||||||
#endif
|
#endif
|
||||||
std::filesystem::create_directory(path);
|
std::filesystem::create_directory(path);
|
||||||
|
|
||||||
|
// Check if the game install directory is set
|
||||||
if (Config::getGameInstallDir() == "") {
|
if (Config::getGameInstallDir() == "") {
|
||||||
GameInstallDialog dlg;
|
GameInstallDialog dlg;
|
||||||
dlg.exec();
|
dlg.exec();
|
||||||
}
|
}
|
||||||
qInstallMessageHandler(customMessageHandler); // ignore qt logs.
|
|
||||||
|
|
||||||
|
// Ignore Qt logs
|
||||||
|
qInstallMessageHandler(customMessageHandler);
|
||||||
|
|
||||||
|
// Initialize the main window
|
||||||
MainWindow* m_main_window = new MainWindow(nullptr);
|
MainWindow* m_main_window = new MainWindow(nullptr);
|
||||||
m_main_window->Init();
|
m_main_window->Init();
|
||||||
|
|
||||||
|
// Check for command line arguments
|
||||||
|
if (argc > 1) {
|
||||||
|
Core::Emulator emulator;
|
||||||
|
emulator.Run(argv[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the Qt application
|
||||||
return a.exec();
|
return a.exec();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue