diff options
author | Sefa Eyeoglu <contact@scrumplex.net> | 2022-12-14 23:22:27 +0100 |
---|---|---|
committer | Sefa Eyeoglu <contact@scrumplex.net> | 2022-12-14 23:22:27 +0100 |
commit | 849b92665e0762a38a7e17403015e2b037318aec (patch) | |
tree | 2fbeac111297727aa6613aacc08e80dcec5c3724 /launcher/ui/MainWindow.cpp | |
parent | fdbd8d9d2b2e04cd68fd800882309b40c05aba2c (diff) | |
parent | d193ed9eebb392b259edb88a227dce4cee773df6 (diff) | |
download | PrismLauncher-849b92665e0762a38a7e17403015e2b037318aec.tar.gz PrismLauncher-849b92665e0762a38a7e17403015e2b037318aec.tar.bz2 PrismLauncher-849b92665e0762a38a7e17403015e2b037318aec.zip |
Merge branch 'develop' into remove-updater
Diffstat (limited to 'launcher/ui/MainWindow.cpp')
-rw-r--r-- | launcher/ui/MainWindow.cpp | 237 |
1 files changed, 209 insertions, 28 deletions
diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp index 0595634f..6eaaac97 100644 --- a/launcher/ui/MainWindow.cpp +++ b/launcher/ui/MainWindow.cpp @@ -39,6 +39,7 @@ #include "Application.h" #include "BuildConfig.h" +#include "FileSystem.h" #include "MainWindow.h" @@ -71,6 +72,7 @@ #include <BaseInstance.h> #include <InstanceList.h> +#include <minecraft/MinecraftInstance.h> #include <MMCZip.h> #include <icons/IconList.h> #include <java/JavaUtils.h> @@ -103,8 +105,14 @@ #include "ui/dialogs/CopyInstanceDialog.h" #include "ui/dialogs/EditAccountDialog.h" #include "ui/dialogs/ExportInstanceDialog.h" +#include "ui/dialogs/ImportResourcePackDialog.h" #include "ui/themes/ITheme.h" +#include <minecraft/mod/ResourcePackFolderModel.h> +#include <minecraft/mod/tasks/LocalResourcePackParseTask.h> +#include <minecraft/mod/TexturePackFolderModel.h> +#include <minecraft/mod/tasks/LocalTexturePackParseTask.h> + #include "KonamiCode.h" #include "InstanceImportTask.h" @@ -235,6 +243,7 @@ public: TranslatedAction actionLaunchInstanceOffline; TranslatedAction actionLaunchInstanceDemo; TranslatedAction actionExportInstance; + TranslatedAction actionCreateInstanceShortcut; QVector<TranslatedAction *> all_actions; LabeledToolButton *renameButton = nullptr; @@ -535,8 +544,9 @@ public: fileMenu->addAction(actionChangeInstGroup); fileMenu->addAction(actionViewSelectedInstFolder); fileMenu->addAction(actionExportInstance); - fileMenu->addAction(actionDeleteInstance); fileMenu->addAction(actionCopyInstance); + fileMenu->addAction(actionDeleteInstance); + fileMenu->addAction(actionCreateInstanceShortcut); fileMenu->addSeparator(); fileMenu->addAction(actionSettings); @@ -622,6 +632,7 @@ public: actionExportInstance->setEnabled(enabled); actionDeleteInstance->setEnabled(enabled); actionCopyInstance->setEnabled(enabled); + actionCreateInstanceShortcut->setEnabled(enabled); } void createStatusBar(QMainWindow *MainWindow) @@ -760,6 +771,13 @@ 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->setIcon(APPLICATION->getThemedIcon("shortcut")); + all_actions.append(&actionCreateInstanceShortcut); + setInstanceActionsEnabled(false); } @@ -798,6 +816,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++) { @@ -1586,7 +1606,7 @@ InstanceView background-image: url(:/backgrounds/%1); background-attachment: fixed; background-clip: padding; - background-position: bottom left; + background-position: bottom right; background-repeat: none; background-color:palette(base); })") @@ -1717,17 +1737,41 @@ void MainWindow::on_actionAddInstance_triggered() void MainWindow::droppedURLs(QList<QUrl> urls) { - for(auto & url:urls) - { - if(url.isLocalFile()) - { - addInstance(url.toLocalFile()); - } - else - { + // NOTE: This loop only processes one dropped file! + for (auto& url : urls) { + // The isLocalFile() check below doesn't work as intended without an explicit scheme. + if (url.scheme().isEmpty()) + url.setScheme("file"); + + if (!url.isLocalFile()) { // probably instance/modpack addInstance(url.toString()); + break; + } + + auto localFileName = url.toLocalFile(); + QFileInfo localFileInfo(localFileName); + + bool isResourcePack = ResourcePackUtils::validate(localFileInfo); + bool isTexturePack = TexturePackUtils::validate(localFileInfo); + + if (!isResourcePack && !isTexturePack) { // probably instance/modpack + addInstance(localFileName); + break; } - // Only process one dropped file... + + ImportResourcePackDialog dlg(this); + + if (dlg.exec() != QDialog::Accepted) + break; + + qDebug() << "Adding resource/texture pack" << localFileName << "to" << dlg.selectedInstanceKey; + + auto inst = APPLICATION->instances()->getInstanceById(dlg.selectedInstanceKey); + auto minecraftInst = std::dynamic_pointer_cast<MinecraftInstance>(inst); + if (isResourcePack) + minecraftInst->resourcePackList()->installResource(localFileName); + else if (isTexturePack) + minecraftInst->texturePackList()->installResource(localFileName); break; } } @@ -1965,27 +2009,25 @@ void MainWindow::on_actionAbout_triggered() void MainWindow::on_actionDeleteInstance_triggered() { - if (!m_selectedInstance) - { + if (!m_selectedInstance) { return; } auto id = m_selectedInstance->id(); - if (APPLICATION->instances()->trashInstance(id)) { - ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething()); - return; - } - - auto response = CustomMessageBox::selectable( - this, - tr("CAREFUL!"), - tr("About to delete: %1\nThis is permanent and will completely delete the instance.\n\nAre you sure?").arg(m_selectedInstance->name()), - QMessageBox::Warning, - QMessageBox::Yes | QMessageBox::No, - QMessageBox::No - )->exec(); - if (response == QMessageBox::Yes) - { + + auto response = + CustomMessageBox::selectable(this, tr("CAREFUL!"), + tr("About to delete: %1\nThis may be permanent and will completely delete the instance.\n\nAre you sure?") + .arg(m_selectedInstance->name()), + QMessageBox::Warning, QMessageBox::Yes | QMessageBox::No, QMessageBox::No) + ->exec(); + + if (response == QMessageBox::Yes) { + if (APPLICATION->instances()->trashInstance(id)) { + ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething()); + return; + } + APPLICATION->instances()->deleteInstance(id); } } @@ -2083,6 +2125,145 @@ 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; + } + + QString desktopFilePath = FS::PathCombine(desktopPath, m_selectedInstance->name() + ".desktop"); + QStringList args; + if (DesktopServices::isFlatpak()) { + QFileDialog fileDialog; + // workaround to make sure the portal file dialog opens in the desktop directory + fileDialog.setDirectoryUrl(desktopPath); + desktopFilePath = fileDialog.getSaveFileName( + this, tr("Create Shortcut"), desktopFilePath, + tr("Desktop Entries (*.desktop)")); + if (desktopFilePath.isEmpty()) + return; // file dialog canceled by user + appPath = "flatpak"; + QString flatpakAppId = BuildConfig.LAUNCHER_DESKTOPFILENAME; + flatpakAppId.remove(".desktop"); + args.append({ "run", flatpakAppId }); + } + args.append({ "--launch", m_selectedInstance->id() }); + if (FS::createShortcut(desktopFilePath, appPath, args, 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(); |