Shortcuts on macOS (#1081)

Co-authored-by: TheKodeToad <TheKodeToad@proton.me>
This commit is contained in:
Nathan 2023-07-10 11:26:25 -07:00 committed by GitHub
parent 9aedb5afff
commit 99ba02afb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 8 deletions

View File

@ -778,9 +778,43 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
destination = PathCombine(getDesktopDir(), RemoveInvalidFilenameChars(name)); destination = PathCombine(getDesktopDir(), RemoveInvalidFilenameChars(name));
} }
#if defined(Q_OS_MACOS) #if defined(Q_OS_MACOS)
destination += ".command"; // Create the Application
QDir applicationDirectory = QStandardPaths::writableLocation(QStandardPaths::ApplicationsLocation) + "/" + BuildConfig.LAUNCHER_NAME + " Instances/";
QFile f(destination); if (!applicationDirectory.mkpath(".")) {
qWarning() << "Couldn't create application directory";
return false;
}
QDir application = applicationDirectory.path() + "/" + name + ".app/";
if (application.exists()) {
qWarning() << "Application already exists!";
return false;
}
if (!application.mkpath(".")) {
qWarning() << "Couldn't create application";
return false;
}
QDir content = application.path() + "/Contents/";
QDir resources = content.path() + "/Resources/";
QDir binaryDir = content.path() + "/MacOS/";
QFile info = content.path() + "/Info.plist";
if (!(content.mkpath(".") && resources.mkpath(".") && binaryDir.mkpath("."))) {
qWarning() << "Couldn't create directories within application";
return false;
}
info.open(QIODevice::WriteOnly | QIODevice::Text);
QFile(icon).rename(resources.path() + "/Icon.icns");
// Create the Command file
QString exec = binaryDir.path() + "/Run.command";
QFile f(exec);
f.open(QIODevice::WriteOnly | QIODevice::Text); f.open(QIODevice::WriteOnly | QIODevice::Text);
QTextStream stream(&f); QTextStream stream(&f);
@ -797,6 +831,28 @@ bool createShortcut(QString destination, QString target, QStringList args, QStri
f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther); f.setPermissions(f.permissions() | QFileDevice::ExeOwner | QFileDevice::ExeGroup | QFileDevice::ExeOther);
// Generate the Info.plist
QTextStream infoStream(&info);
infoStream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?> \n"
"<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
"\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">"
"<plist version=\"1.0\">\n"
"<dict>\n"
" <key>CFBundleExecutable</key>\n"
" <string>Run.command</string>\n" // The path to the executable
" <key>CFBundleIconFile</key>\n"
" <string>Icon.icns</string>\n"
" <key>CFBundleName</key>\n"
" <string>" << name << "</string>\n" // Name of the application
" <key>CFBundlePackageType</key>\n"
" <string>APPL</string>\n"
" <key>CFBundleShortVersionString</key>\n"
" <string>1.0</string>\n"
" <key>CFBundleVersion</key>\n"
" <string>1.0</string>\n"
"</dict>\n"
"</plist>";
return true; return true;
#elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) #elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
if (!destination.endsWith(".desktop")) // in case of isFlatpak destination is already populated if (!destination.endsWith(".desktop")) // in case of isFlatpak destination is already populated

View File

@ -1536,11 +1536,39 @@ void MainWindow::on_actionCreateInstanceShortcut_triggered()
QString iconPath; QString iconPath;
QStringList args; QStringList args;
#if defined(Q_OS_MACOS) #if defined(Q_OS_MACOS)
if (appPath.startsWith("/private/var/")) { appPath = QApplication::applicationFilePath();
QMessageBox::critical(this, tr("Create instance shortcut"), if (appPath.startsWith("/private/var/")) {
tr("The launcher is in the folder it was extracted from, therefore it cannot create shortcuts.")); QMessageBox::critical(this, tr("Create instance shortcut"),
return; 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) #elif defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
if (appPath.startsWith("/tmp/.mount_")) { if (appPath.startsWith("/tmp/.mount_")) {
// AppImage! // AppImage!
@ -1623,7 +1651,11 @@ void MainWindow::on_actionCreateInstanceShortcut_triggered()
#endif #endif
args.append({ "--launch", m_selectedInstance->id() }); args.append({ "--launch", m_selectedInstance->id() });
if (FS::createShortcut(desktopFilePath, appPath, args, m_selectedInstance->name(), iconPath)) { 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!")); #if not defined(Q_OS_MACOS)
QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance on your desktop!"));
#else
QMessageBox::information(this, tr("Create instance shortcut"), tr("Created a shortcut to this instance!"));
#endif
} else { } else {
#if not defined(Q_OS_MACOS) #if not defined(Q_OS_MACOS)
iconFile.remove(); iconFile.remove();