Changed: Write shortcuts under OS X

This commit is contained in:
kervala 2016-10-09 15:08:37 +02:00
parent 962c6f0798
commit d3a72f1506
9 changed files with 252 additions and 24 deletions

View file

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>shortcut.sh</string>
<key>CFBundleGetInfoString</key>
<string>$NAME</string>
<key>CFBundleIconFile</key>
<string>ryzom.icns</string>
<key>CFBundleIdentifier</key>
<string>$IDENTIFIER</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>fr</string>
<string>de</string>
<string>ru</string>
<string>es</string>
</array>
<key>CFBundleLongVersionString</key>
<string>$VERSION</string>
<key>CFBundleName</key>
<string>$NAME</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>$VERSION</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>LSApplicationCategoryType</key>
<string>public.app-category.role-playing-games</string>
<key>LSFileQuarantineEnabled</key>
<false/>
<key>LSMinimumSystemVersion</key>
<string>10.6</string>
<key>LSRequiresCarbon</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>$COPYRIGHT</string>
</dict>
</plist>

View file

@ -0,0 +1 @@
APPL????

View file

@ -4,10 +4,13 @@
</qresource> </qresource>
<qresource prefix="/icons"> <qresource prefix="/icons">
<file>ryzom.ico</file> <file>ryzom.ico</file>
<file>ryzom_installer.png</file> <file>ryzom.png</file>
<file>ryzom.icns</file>
</qresource> </qresource>
<qresource prefix="/templates"> <qresource prefix="/templates">
<file>template.desktop</file> <file>template.desktop</file>
<file>ryzom_installer.ini</file> <file>ryzom_installer.ini</file>
<file>Info.plist</file>
<file>PkgInfo</file>
</qresource> </qresource>
</RCC> </RCC>

Binary file not shown.

View file

@ -0,0 +1,4 @@
#!/bin/bash
# autogenerated file - do not edit
$COMMAND

View file

@ -791,15 +791,18 @@ QStringList CConfigFile::getInstallerRequiredFiles() const
// unsupported compiler // unsupported compiler
#endif #endif
// include current executable
files << QFileInfo(QApplication::applicationFilePath()).fileName();
#elif defined(Q_OS_MAC) #elif defined(Q_OS_MAC)
// TODO: for OS X // everything is in a directory
files << "Ryzom Installer.app";
#else #else
// icon under Linux // icon under Linux
files << "ryzom_installer.png"; files << "ryzom_installer.png";
#endif
// include current executable // include current executable
files << QFileInfo(QApplication::applicationFilePath()).fileName(); files << QFileInfo(QApplication::applicationFilePath()).fileName();
#endif
return files; return files;
} }

View file

@ -788,6 +788,8 @@ void COperationDialog::copyInstaller()
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN32
// under Windows, icon is included in executable // under Windows, icon is included in executable
icon = executable; icon = executable;
#elif defined(Q_OS_MAC)
// everything is in bundle
#else #else
// icon is in the same directory as installer // icon is in the same directory as installer
icon = config->getInstallationDirectory() + "/ryzom_installer.png"; icon = config->getInstallationDirectory() + "/ryzom_installer.png";

View file

@ -16,6 +16,7 @@
#include "stdpch.h" #include "stdpch.h"
#include "utils.h" #include "utils.h"
#include "configfile.h"
#include "nel/misc/path.h" #include "nel/misc/path.h"
@ -40,6 +41,36 @@ QString qBytesToHumanReadable(qint64 bytes)
return QString::fromUtf8(NLMISC::bytesToHumanReadableUnits(bytes, units).c_str()); return QString::fromUtf8(NLMISC::bytesToHumanReadableUnits(bytes, units).c_str());
} }
QString nameToId(const QString &name)
{
QString res;
// only allows simple characters
QRegExp allowedCharacters("^[0-9a-zA-Z-]$");
for (int i = 0, len = name.length(); i < len; ++i)
{
if (allowedCharacters.indexIn(name.at(i)) > -1)
{
// allowed character
res += name[i];
}
else
{
// not allowed, replace by a space
res += " ";
}
}
// simplify all spaces
res = res.simplified();
// replace spaces by minus
res.replace(" ", "-");
return res;
}
bool isDirectoryEmpty(const QString &directory, bool recursize) bool isDirectoryEmpty(const QString &directory, bool recursize)
{ {
bool res = true; bool res = true;
@ -250,37 +281,89 @@ bool resolveShortcut(const QWidget &window, const QString &shortcut, QString &pa
return SUCCEEDED(hres); return SUCCEEDED(hres);
} }
#elif defined(NL_OS_MAC)
bool createShortcut(const QString &shortcut, const QString &name, const QString &executable, const QString &arguments, const QString &icon, const QString &workingDir)
{
QString appPath(shortcut + ".app");
// directories
QString contentsPath(appPath + "/Contents");
QString binaryPath(contentsPath + "/MacOS");
QString dataPath(contentsPath + "/Resources");
// files
QString binaryFile(binaryPath + "/shortcut.sh");
QString iconFile(dataPath + "/ryzom.icns");
QString pkgInfoFile(contentsPath + "/PkgInfo");
QString plistFile(contentsPath + "/Info.plist");
// silently create directories
QDir().mkpath(binaryPath);
QDir().mkpath(dataPath);
if (!isDirectoryWritable(binaryPath) || !isDirectoryWritable(dataPath)) return false;
// write icon
if (!writeResource(":/icons/ryzom.icns", iconFile)) return false;
// write PkgInfo
if (!writeResource(":/templates/PkgInfo", pkgInfoFile)) return false;
// variables
QMap<QString, QString> strings;
// build command
QString command = QString("open \"%1\"").arg(executable);
if (!arguments.isEmpty()) command += " --args " + arguments;
strings.clear();
strings["COMMAND"] = command;
// write shortcut.sh
if (!writeResourceWithTemplates(":/templates/shortcut.sh", binaryFile, strings)) return false;
// set executable flags to .sh
QFile::setPermissions(binaryFile, QFile::permissions(binaryFile) | QFile::ExeGroup | QFile::ExeUser | QFile::ExeOther);
CConfigFile *config = CConfigFile::getInstance();
strings.clear();
strings["NAME"] = name;
strings["COPYRIGHT"] = config->getProductPublisher();
strings["VERSION"] = QApplication::applicationVersion();
strings["IDENTIFIER"] = "com.winchgate.Ryzom-" + nameToId(name);
// write Info.plist
if (!writeResourceWithTemplates(":/templates/Info.plist", plistFile, strings)) return false;
return true;
}
bool resolveShortcut(const QWidget &window, const QString &pathLink, QString &pathObj)
{
return false;
}
#else #else
bool createShortcut(const QString &shortcut, const QString &name, const QString &executable, const QString &arguments, const QString &icon, const QString &workingDir) bool createShortcut(const QString &shortcut, const QString &name, const QString &executable, const QString &arguments, const QString &icon, const QString &workingDir)
{ {
// open template
QFile file(":/templates/template.desktop");
if (!file.open(QFile::ReadOnly)) return false;
QString data = QString::fromUtf8(file.readAll());
file.close();
// build command // build command
QString command = executable; QString command = executable;
if (!arguments.isEmpty()) command += " " + arguments; if (!arguments.isEmpty()) command += " " + arguments;
// replace strings // variables
data.replace("$NAME", name); QMap<QString, QString> strings;
data.replace("$COMMAND", command); strings["NAME"] = name;
data.replace("$ICON", icon); strings["COMMAND"] = command;
strings["ICON"] = icon;
// destination file
QString path(shortcut + ".desktop"); QString path(shortcut + ".desktop");
// write file // replace strings
file.setFileName(path); if (!writeResourceWithTemplates(":/templates/template.desktop", path, strings)) return false;
if (!file.open(QFile::WriteOnly)) return false;
file.write(data.toUtf8());
file.close();
// set executable flags to .desktop // set executable flags to .desktop
QFile::setPermissions(path, QFile::permissions(path) | QFile::ExeGroup | QFile::ExeUser | QFile::ExeOther); QFile::setPermissions(path, QFile::permissions(path) | QFile::ExeGroup | QFile::ExeUser | QFile::ExeOther);
@ -307,7 +390,13 @@ bool removeShortcut(const QString &shortcut)
if (!NLMISC::CFile::isExists(qToUtf8(fullPath))) return false; if (!NLMISC::CFile::isExists(qToUtf8(fullPath))) return false;
// remove it // remove it
#if defined(Q_OS_MAC)
// under OS X, it's a directory
return QDir(fullPath).removeRecursively();
#else
// a file under other platforms
return QFile::remove(fullPath); return QFile::remove(fullPath);
#endif
} }
QString appendShortcutExtension(const QString &shortcut) QString appendShortcutExtension(const QString &shortcut)
@ -317,7 +406,7 @@ QString appendShortcutExtension(const QString &shortcut)
#if defined(Q_OS_WIN32) #if defined(Q_OS_WIN32)
extension = ".lnk"; extension = ".lnk";
#elif defined(Q_OS_MAC) #elif defined(Q_OS_MAC)
// TODO extension = ".app";
#else #else
extension = ".desktop"; extension = ".desktop";
#endif #endif
@ -391,6 +480,75 @@ QString getVersionFromExecutable(const QString &path)
return ""; return "";
} }
bool writeResource(const QString &resource, const QString &path)
{
// all resources start with :/
if (!resource.startsWith(":/")) return false;
// open resource
QFile file(resource);
// unable to open it
if (!file.open(QFile::ReadOnly)) return false;
QByteArray data(file.readAll());
file.close();
// write file
file.setFileName(path);
// unable to write it
if (!file.open(QFile::WriteOnly)) return false;
// problem writting
if (file.write(data) != data.length()) return false;
file.close();
return true;
}
bool writeResourceWithTemplates(const QString &resource, const QString &path, const QMap<QString, QString> &strings)
{
// all resources start with :/
if (!resource.startsWith(":/")) return false;
// open resource
QFile file(resource);
// unable to open it
if (!file.open(QFile::ReadOnly)) return false;
// data are UTF-8 text
QString data = QString::fromUtf8(file.readAll());
file.close();
// write file
file.setFileName(path);
// unable to write it
if (!file.open(QFile::WriteOnly)) return false;
// replace strings
QMap<QString, QString>::ConstIterator it = strings.begin(), iend = strings.end();
while (it != iend)
{
// replace variables with their value
data.replace("$" + it.key(), it.value());
++it;
}
// write
file.write(data.toUtf8());
file.close();
return true;
}
CCOMHelper::CCOMHelper() CCOMHelper::CCOMHelper()
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN

View file

@ -29,6 +29,7 @@
*/ */
QString qBytesToHumanReadable(qint64 bytes); QString qBytesToHumanReadable(qint64 bytes);
QString nameToId(const QString &name);
bool isDirectoryEmpty(const QString &directory, bool recursize); bool isDirectoryEmpty(const QString &directory, bool recursize);
@ -57,6 +58,8 @@ bool resolveShortcut(const QWidget &window, const QString &shortcut, QString &pa
QString appendShortcutExtension(const QString &shortcut); QString appendShortcutExtension(const QString &shortcut);
QString getVersionFromExecutable(const QString &path); QString getVersionFromExecutable(const QString &path);
bool writeResource(const QString &resource, const QString &path);
bool writeResourceWithTemplates(const QString &resource, const QString &path, const QMap<QString, QString> &strings);
class CCOMHelper class CCOMHelper
{ {