diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 8714799ff..ea749ca4c 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -701,9 +701,6 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv) m_settings->registerSetting("InstSortMode", "Name"); m_settings->registerSetting("SelectedInstance", QString()); - // Shortcut creation - m_settings->registerSetting("ShortcutCreationMode", "Desktop"); - // Window state and geometry m_settings->registerSetting("MainWindowState", ""); m_settings->registerSetting("MainWindowGeometry", ""); diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 8979667f0..511055b07 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -208,6 +208,13 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi exportInstanceMenu->addAction(ui->actionExportInstanceMrPack); exportInstanceMenu->addAction(ui->actionExportInstanceFlamePack); ui->actionExportInstance->setMenu(exportInstanceMenu); + + auto shortcutInstanceMenu = new QMenu(this); + shortcutInstanceMenu->addAction(ui->actionCreateInstanceShortcutDesktop); + shortcutInstanceMenu->addAction(ui->actionCreateInstanceShortcutApplications); + shortcutInstanceMenu->addAction(ui->actionCreateInstanceShortcutOther); + + ui->actionCreateInstanceShortcut->setMenu(shortcutInstanceMenu); } // hide, disable and show stuff @@ -235,6 +242,13 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWi } ui->actionViewJavaFolder->setEnabled(BuildConfig.JAVA_DOWNLOADER_ENABLED); + +#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) + bool isFlatpak = DesktopServices::isFlatpak(); + + ui->actionCreateInstanceShortcutDesktop->setEnabled(isFlatpak); + ui->actionCreateInstanceShortcutApplications->setEnabled(isFlatpak); +#endif } // add the toolbar toggles to the view menu @@ -1491,167 +1505,169 @@ void MainWindow::on_actionKillInstance_triggered() } } -void MainWindow::on_actionCreateInstanceShortcut_triggered() +void MainWindow::createInstanceShortcut(QString shortcutFilePath) { + + QString appPath = QApplication::applicationFilePath(); + QString iconPath; + QStringList args; +#if defined(Q_OS_MACOS) + 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; + } + + auto pIcon = APPLICATION->icons()->icon(m_selectedInstance->iconKey()); + if (pIcon == nullptr) { + pIcon = APPLICATION->icons()->icon("grass"); + } + + iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "Icon.icns"); + + QFile iconFile(iconPath); + if (!iconFile.open(QFile::WriteOnly)) { + QMessageBox::critical(this, tr("Create instance Application"), tr("Failed to create icon for Application.")); + return; + } + + QIcon icon = pIcon->icon(); + + bool success = icon.pixmap(1024, 1024).save(iconPath, "ICNS"); + iconFile.close(); + + if (!success) { + iconFile.remove(); + QMessageBox::critical(this, tr("Create instance Application"), tr("Failed to create icon for Application.")); + return; + } +#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) + 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"); + } + + 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 (DesktopServices::isFlatpak()) { + appPath = "flatpak"; + QString flatpakAppId = BuildConfig.LAUNCHER_DESKTOPFILENAME; + flatpakAppId.remove(".desktop"); + args.append({ "run", flatpakAppId }); + } + +#elif defined(Q_OS_WIN) + auto icon = APPLICATION->icons()->icon(m_selectedInstance->iconKey()); + if (icon == nullptr) { + icon = APPLICATION->icons()->icon("grass"); + } + + 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; + } + +#else + QMessageBox::critical(this, tr("Create instance shortcut"), tr("Not supported on your platform!")); + return; +#endif + args.append({ "--launch", m_selectedInstance->id() }); + + if (!FS::createShortcut(std::move(shortcutFilePath), appPath, args, m_selectedInstance->name(), iconPath)) { +#if not defined(Q_OS_MACOS) + iconFile.remove(); +#endif + QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!")); + return; + } +} + +void MainWindow::on_actionCreateInstanceShortcutOther_triggered() { + if (!m_selectedInstance) + return; + + QString defaultedDir = FS::getDesktopDir(); +#if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) + QString extension = ".desktop"; +#elif defined(Q_OS_WINDOWS) + QString extension = ".lnk"; +#else + QString extension = ""; +#endif + + QString shortcutFilePath = FS::PathCombine(defaultedDir, FS::RemoveInvalidFilenameChars(m_selectedInstance->name()) + extension); + QFileDialog fileDialog; + // workaround to make sure the portal file dialog opens in the desktop directory + fileDialog.setDirectoryUrl(defaultedDir); + + shortcutFilePath = fileDialog.getSaveFileName(this, tr("Create Shortcut"), shortcutFilePath, tr("Desktop Entries") + " (*.desktop)"); + if (shortcutFilePath.isEmpty()) + return; // file dialog canceled by user + + createInstanceShortcut(shortcutFilePath); + QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance!")); +} + +void MainWindow::on_actionCreateInstanceShortcutDesktop_triggered() { + if (!m_selectedInstance) + return; + + QString shortcutFilePath = FS::PathCombine(FS::getDesktopDir(), FS::RemoveInvalidFilenameChars(m_selectedInstance->name())); + createInstanceShortcut(shortcutFilePath); + QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!")); +} + +void MainWindow::on_actionCreateInstanceShortcutApplications_triggered() { if (!m_selectedInstance) return; - std::vector paths; - QString mode = APPLICATION->settings()->get("ShortcutCreationMode").toString(); - if (mode == "Applications") { - paths.push_back(FS::getApplicationsDir()); - } else if (mode == "Both") { - paths.push_back(FS::getDesktopDir()); - paths.push_back(FS::getApplicationsDir()); - } else { - // Default to desktop - paths.push_back(FS::getDesktopDir()); - } - - for (const QString& shortcutDirPath : paths) { - if (shortcutDirPath.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; - } - - QString shortcutFilePath; - QString appPath = QApplication::applicationFilePath(); - QString iconPath; - QStringList args; -#if defined(Q_OS_MACOS) - 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; - } - - auto pIcon = APPLICATION->icons()->icon(m_selectedInstance->iconKey()); - if (pIcon == nullptr) { - pIcon = APPLICATION->icons()->icon("grass"); - } - - iconPath = FS::PathCombine(m_selectedInstance->instanceRoot(), "Icon.icns"); - - QFile iconFile(iconPath); - if (!iconFile.open(QFile::WriteOnly)) { - QMessageBox::critical(this, tr("Create instance Application"), tr("Failed to create icon for Application.")); - return; - } - - QIcon icon = pIcon->icon(); - - bool success = icon.pixmap(1024, 1024).save(iconPath, "ICNS"); - iconFile.close(); - - if (!success) { - iconFile.remove(); - QMessageBox::critical(this, tr("Create instance Application"), tr("Failed to create icon for Application.")); - return; - } -#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) - 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"); - } - - 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 (DesktopServices::isFlatpak()) { - shortcutFilePath = FS::PathCombine(shortcutDirPath, FS::RemoveInvalidFilenameChars(m_selectedInstance->name()) + ".desktop"); - QFileDialog fileDialog; - // workaround to make sure the portal file dialog opens in the desktop directory - fileDialog.setDirectoryUrl(shortcutDirPath); - shortcutFilePath = - fileDialog.getSaveFileName(this, tr("Create Shortcut"), shortcutFilePath, tr("Desktop Entries") + " (*.desktop)"); - if (shortcutFilePath.isEmpty()) - return; // file dialog canceled by user - appPath = "flatpak"; - QString flatpakAppId = BuildConfig.LAUNCHER_DESKTOPFILENAME; - flatpakAppId.remove(".desktop"); - args.append({ "run", flatpakAppId }); - } - -#elif defined(Q_OS_WIN) - auto icon = APPLICATION->icons()->icon(m_selectedInstance->iconKey()); - if (icon == nullptr) { - icon = APPLICATION->icons()->icon("grass"); - } - - 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; - } - -#else - QMessageBox::critical(this, tr("Create instance shortcut"), tr("Not supported on your platform!")); - return; -#endif - args.append({ "--launch", m_selectedInstance->id() }); - - bool userDefinedShortcutPath = !shortcutFilePath.isEmpty(); - if (shortcutFilePath.isEmpty()) - shortcutFilePath = FS::PathCombine(shortcutDirPath, FS::RemoveInvalidFilenameChars(m_selectedInstance->name())); - if (!FS::createShortcut(shortcutFilePath, appPath, args, m_selectedInstance->name(), iconPath)) { -#if not defined(Q_OS_MACOS) - iconFile.remove(); -#endif - QMessageBox::critical(this, tr("Create instance shortcut"), tr("Failed to create instance shortcut!")); - return; - } - - if(userDefinedShortcutPath) - break; - } -#if not defined(Q_OS_MACOS) - QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance!")); -#else - QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance!")); -#endif + QString shortcutFilePath = FS::PathCombine(FS::getApplicationsDir(), FS::RemoveInvalidFilenameChars(m_selectedInstance->name())); + createInstanceShortcut(shortcutFilePath); + QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance in your applications folder!")); } void MainWindow::taskEnd() diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h index 0e692eda7..bdd4a1890 100644 --- a/launcher/ui/MainWindow.h +++ b/launcher/ui/MainWindow.h @@ -165,7 +165,13 @@ class MainWindow : public QMainWindow { void on_actionEditInstance_triggered(); - void on_actionCreateInstanceShortcut_triggered(); + inline void on_actionCreateInstanceShortcut_triggered() { + on_actionCreateInstanceShortcutDesktop_triggered(); + }; + + void on_actionCreateInstanceShortcutDesktop_triggered(); + void on_actionCreateInstanceShortcutApplications_triggered(); + void on_actionCreateInstanceShortcutOther_triggered(); void taskEnd(); @@ -226,6 +232,7 @@ class MainWindow : public QMainWindow { void setSelectedInstanceById(const QString& id); void updateStatusCenter(); void setInstanceActionsEnabled(bool enabled); + void createInstanceShortcut(QString shortcutDirPath); void runModalTask(Task* task); void instanceFromInstanceTask(InstanceTask* task); diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui index f20c34206..3fa30c97e 100644 --- a/launcher/ui/MainWindow.ui +++ b/launcher/ui/MainWindow.ui @@ -131,7 +131,7 @@ 0 0 800 - 27 + 22 @@ -235,8 +235,7 @@ - - .. + More news... @@ -250,8 +249,7 @@ true - - .. + &Meow @@ -286,8 +284,7 @@ - - .. + Add Instanc&e... @@ -298,8 +295,7 @@ - - .. + &Update... @@ -313,8 +309,7 @@ - - .. + Setti&ngs... @@ -328,8 +323,7 @@ - - .. + &Manage Accounts... @@ -337,8 +331,7 @@ - - .. + &Launch @@ -349,8 +342,7 @@ - - .. + &Kill @@ -364,8 +356,7 @@ - - .. + Rename @@ -376,8 +367,7 @@ - - .. + &Change Group... @@ -399,8 +389,7 @@ - - .. + &Edit... @@ -414,8 +403,7 @@ - - .. + &Folder @@ -426,8 +414,7 @@ - - .. + Dele&te @@ -441,8 +428,7 @@ - - .. + Cop&y... @@ -456,8 +442,7 @@ - - .. + E&xport... @@ -468,8 +453,7 @@ - - .. + Prism Launcher (zip) @@ -477,8 +461,7 @@ - - .. + Modrinth (mrpack) @@ -486,8 +469,7 @@ - - .. + CurseForge (zip) @@ -495,20 +477,18 @@ - - .. + Create Shortcut - Creates a shortcut on your desktop to launch the selected instance. + Creates a shortcut on a selected folder to launch the selected instance. - - .. + No accounts added! @@ -519,8 +499,7 @@ true - - .. + No Default Account @@ -531,8 +510,7 @@ - - .. + Close &Window @@ -546,8 +524,7 @@ - - .. + &Instances @@ -558,8 +535,7 @@ - - .. + Launcher &Root @@ -570,8 +546,7 @@ - - .. + &Central Mods @@ -582,8 +557,7 @@ - - .. + &Skins @@ -594,8 +568,7 @@ - - .. + Instance Icons @@ -606,8 +579,7 @@ - - .. + Logs @@ -623,8 +595,7 @@ - - .. + Report a Bug or Suggest a Feature @@ -635,8 +606,7 @@ - - .. + &Discord Guild @@ -647,8 +617,7 @@ - - .. + &Matrix Space @@ -659,8 +628,7 @@ - - .. + Sub&reddit @@ -671,8 +639,7 @@ - - .. + &About %1 @@ -686,8 +653,7 @@ - - .. + &Clear Metadata Cache @@ -698,8 +664,7 @@ - - .. + Install to &PATH @@ -710,8 +675,7 @@ - - .. + Folders @@ -722,8 +686,7 @@ - - .. + Help @@ -734,8 +697,7 @@ - - .. + Accounts @@ -743,8 +705,7 @@ - - .. + %1 &Help @@ -755,8 +716,7 @@ - - .. + &Widget Themes @@ -767,8 +727,7 @@ - - .. + I&con Theme @@ -779,8 +738,7 @@ - - .. + Cat Packs @@ -791,8 +749,7 @@ - - .. + Java @@ -801,6 +758,39 @@ Open the Java folder in a file browser. Only available if the built-in Java downloader is used. + + + Desktop + + + Creates an shortcut to this instance on your desktop + + + QAction::TextHeuristicRole + + + + + Applications + + + Create a shortcut of this instance on your start menu + + + QAction::TextHeuristicRole + + + + + Other... + + + Creates a shortcut in a folder selected by you + + + QAction::TextHeuristicRole + + diff --git a/launcher/ui/pages/global/LauncherPage.cpp b/launcher/ui/pages/global/LauncherPage.cpp index 90540247e..da4ba9023 100644 --- a/launcher/ui/pages/global/LauncherPage.cpp +++ b/launcher/ui/pages/global/LauncherPage.cpp @@ -65,15 +65,6 @@ enum InstSortMode { Sort_LastLaunch }; -enum ShortcutCreationMode { - // Create a shortcut in the applications - Shortcut_OnlyApplications, - // Create a shortcut in both locations - Shortcut_Both, - // Create a shortcut on the desktop - Shortcut_OnlyDesktop -}; - LauncherPage::LauncherPage(QWidget* parent) : QWidget(parent), ui(new Ui::LauncherPage) { ui->setupUi(this); @@ -263,19 +254,6 @@ void LauncherPage::applySettings() s->set("ModMetadataDisabled", ui->metadataDisableBtn->isChecked()); s->set("ModDependenciesDisabled", ui->dependenciesDisableBtn->isChecked()); s->set("SkipModpackUpdatePrompt", ui->skipModpackUpdatePromptBtn->isChecked()); - - auto shortcutMode = (ShortcutCreationMode) ui->createShortcutActionComboBox->currentIndex(); - switch (shortcutMode) { - case Shortcut_OnlyApplications: - s->set("ShortcutCreationMode", "Applications"); - break; - case Shortcut_Both: - s->set("ShortcutCreationMode", "Both"); - break; - case Shortcut_OnlyDesktop: - s->set("ShortcutCreationMode", "Desktop"); - break; - } } void LauncherPage::loadSettings() { @@ -341,19 +319,6 @@ void LauncherPage::loadSettings() ui->metadataWarningLabel->setHidden(!ui->metadataDisableBtn->isChecked()); ui->dependenciesDisableBtn->setChecked(s->get("ModDependenciesDisabled").toBool()); ui->skipModpackUpdatePromptBtn->setChecked(s->get("SkipModpackUpdatePrompt").toBool()); - - QString shortcutModeStr = s->get("ShortcutCreationMode").toString(); - ShortcutCreationMode shortcutMode = Shortcut_OnlyDesktop; - if(shortcutModeStr == "Applications") { - shortcutMode = Shortcut_OnlyApplications; - } else if(shortcutModeStr == "Desktop") { - // Guess we don't need that, but it's here for completeness - shortcutMode = Shortcut_OnlyDesktop; - } else if(shortcutModeStr == "Both") { - shortcutMode = Shortcut_Both; - } - - ui->createShortcutActionComboBox->setCurrentIndex(shortcutMode); } void LauncherPage::refreshFontPreview() @@ -404,4 +369,4 @@ void LauncherPage::refreshFontPreview() void LauncherPage::retranslate() { ui->retranslateUi(this); -} +} \ No newline at end of file diff --git a/launcher/ui/pages/global/LauncherPage.ui b/launcher/ui/pages/global/LauncherPage.ui index 1e08d8266..ff95bdfbb 100644 --- a/launcher/ui/pages/global/LauncherPage.ui +++ b/launcher/ui/pages/global/LauncherPage.ui @@ -282,23 +282,6 @@ Miscellaneous - - - - 0 - - - - - - - Seconds to wait until the requests are terminated - - - Timeout for HTTP requests - - - @@ -306,27 +289,6 @@ - - - - s - - - - - - - Number of concurrent downloads - - - - - - - Number of manual retries - - - @@ -341,30 +303,42 @@ - - + + - Create shortcut action + Number of concurrent downloads - - - - - Applications only - - - - - Applications & Desktop - - - - - Desktop only - - + + + + Number of manual retries + + + + + + + 0 + + + + + + + Seconds to wait until the requests are terminated + + + Timeout for HTTP requests + + + + + + + s + @@ -694,4 +668,4 @@ - + \ No newline at end of file