Skip to content

Commit

Permalink
Linux Portable: add proper desktop integration
Browse files Browse the repository at this point in the history
The Linux portable will now ask if you want to integrate Friction with your desktop environment.

A better solution than using AppImage IMHO.

The portable will now integrate with the desktop and offer true portability with settings etc located in the same folder as the app.

TODO: add "uninstall".
  • Loading branch information
rodlie committed Aug 17, 2024
1 parent 94783cc commit a9731e3
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 0 deletions.
15 changes: 15 additions & 0 deletions src/app/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,21 @@ int main(int argc, char *argv[])

ThemeSupport::setupTheme(eSizesUI::widget);

#ifdef Q_OS_LINUX
if (AppSupport::isAppPortable()) {
if (!AppSupport::hasXDGDesktopIntegration()) {
const auto ask = QMessageBox::question(nullptr,
QObject::tr("Setup Desktop Integration?"),
QObject::tr("Would you like to setup desktop integration?"
" This will add Friction to your application launcher"
" and add mime type for project files."));
if (ask == QMessageBox::Yes) {
AppSupport::setupXDGDesktopIntegration();
}
}
}
#endif

//#ifdef QT_DEBUG
// const qint64 pId = QCoreApplication::applicationPid();
// QProcess * const process = new QProcess(&w);
Expand Down
3 changes: 3 additions & 0 deletions src/app/resources.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,8 @@
<file>presets/render/003-friction-preset-prores-444.conf</file>
<file>presets/render/002-friction-preset-mp4-h264-mp3.conf</file>
<file>presets/render/001-friction-preset-mp4-h264.conf</file>
<file>xdg/friction.xml</file>
<file>xdg/friction.desktop</file>
<file>icons/hicolor/scalable/apps/graphics.friction.Friction.svg</file>
</qresource>
</RCC>
13 changes: 13 additions & 0 deletions src/app/xdg/friction.desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[Desktop Entry]
Version=1.0
Name=Friction
Exec=__FRICTION__ %f
Icon=graphics.friction.Friction
Comment=Motion graphics and animation
GenericName=Friction Graphics
StartupNotify=true
Terminal=false
Type=Application
Categories=Graphics;
MimeType=application/x-graphics.friction.Friction;
StartupWMClass=friction
7 changes: 7 additions & 0 deletions src/app/xdg/friction.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0"?>
<mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'>
<mime-type type="application/x-graphics.friction.Friction">
<comment>Friction</comment>
<glob pattern="*.friction"/>
</mime-type>
</mime-info>
180 changes: 180 additions & 0 deletions src/core/appsupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,3 +682,183 @@ bool AppSupport::isAppPortable()
{
return QFile::exists(QString("%1/portable.txt").arg(getAppPath()));
}

bool AppSupport::hasXDGDesktopIntegration()
{
QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
if (path.isEmpty() ||
!path.startsWith(QDir::homePath())) { path = QString("%1/.local/share").arg(QDir::homePath()); }

QStringList files;
QString desktop = "applications/graphics.friction.Friction.desktop";
files << desktop;
files << "mime/packages/graphics.friction.Friction.xml";
files << "icons/hicolor/scalable/apps/graphics.friction.Friction.svg";
files << "icons/hicolor/256x256/apps/graphics.friction.Friction.png";
files << "icons/hicolor/scalable/mimetypes/application-x-graphics.friction.Friction.svg";
files << "icons/hicolor/256x256/mimetypes/application-x-graphics.friction.Friction.png";

for (const auto &file : files) {
if (!QFile::exists(QString("%1/%2").arg(path, file))) {
qDebug() << "not found!" << file;
return false;
}
}

QString desktopFilePath(QString("%1/%2").arg(path, desktop));
if (QFile::exists(desktopFilePath)) {
QSettings dotDesktop(desktopFilePath, QSettings::IniFormat);
dotDesktop.beginGroup("Desktop Entry");
QString exec = dotDesktop.value("Exec").toString().simplified();
dotDesktop.endGroup();
if (exec.isEmpty() || !exec.startsWith(getAppPath())) { return false; }
}
return true;
}

bool AppSupport::setupXDGDesktopIntegration()
{
QString path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
if (path.isEmpty() ||
!path.startsWith(QDir::homePath())) { path = QString("%1/.local/share").arg(QDir::homePath()); }

if (!QFile::exists(path)) {
QDir dir(path);
if (!dir.mkpath(path)) { return false; }
}

const QString resDesktop = ":/xdg/friction.desktop";
const QString resMime = ":/xdg/friction.xml";
const QString resSvg = ":/icons/hicolor/scalable/apps/graphics.friction.Friction.svg";
const QString resPng = ":/icons/hicolor/256x256/apps/graphics.friction.Friction.png";

{
const QString dirName(QString("%1/applications").arg(path));
const QString fileName(QString("%1/graphics.friction.Friction.desktop").arg(dirName));
qDebug() << "Checking:" << fileName;
if (!QFile::exists(dirName)) {
QDir dir(dirName);
if (!dir.mkpath(dirName)) { return false; }
}
bool wrongPath = false;
QSettings desktop(fileName, QSettings::IniFormat);
desktop.beginGroup("Desktop Entry");
QString exec = desktop.value("Exec").toString().simplified();
if (!exec.startsWith(getAppPath())) { wrongPath = true; }
desktop.endGroup();
if (!QFile::exists(fileName) || wrongPath) {
QFile file(fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) {
QFile res(resDesktop);
if (res.open(QIODevice::ReadOnly | QIODevice::Text)) {
file.write(res.readAll().replace("__FRICTION__",
qApp->applicationFilePath().toUtf8()));
res.close();
} else { return false; }
file.close();
} else { return false; }
}
}
{
const QString dirName(QString("%1/mime/packages").arg(path));
const QString fileName(QString("%1/graphics.friction.Friction.xml").arg(dirName));
qDebug() << "Checking:" << fileName;
if (!QFile::exists(dirName)) {
QDir dir(dirName);
if (!dir.mkpath(dirName)) { return false; }
}
if (!QFile::exists(fileName)) {
QFile file(fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QFile res(resMime);
if (res.open(QIODevice::ReadOnly | QIODevice::Text)) {
file.write(res.readAll());
res.close();
} else { return false; }
file.close();
} else { return false; }
}
}
{
const QString dirName(QString("%1/icons/hicolor/scalable/apps").arg(path));
const QString fileName(QString("%1/graphics.friction.Friction.svg").arg(dirName));
qDebug() << "Checking:" << fileName;
if (!QFile::exists(dirName)) {
QDir dir(dirName);
if (!dir.mkpath(dirName)) { return false; }
}
if (!QFile::exists(fileName)) {
QFile file(fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QFile res(resSvg);
if (res.open(QIODevice::ReadOnly | QIODevice::Text)) {
file.write(res.readAll());
res.close();
} else { return false; }
file.close();
} else { return false; }
}
}
{
const QString dirName(QString("%1/icons/hicolor/256x256/apps").arg(path));
const QString fileName(QString("%1/graphics.friction.Friction.png").arg(dirName));
qDebug() << "Checking:" << fileName;
if (!QFile::exists(dirName)) {
QDir dir(dirName);
if (!dir.mkpath(dirName)) { return false; }
}
if (!QFile::exists(fileName)) {
QFile file(fileName);
if (file.open(QIODevice::WriteOnly)) {
QFile res(resPng);
if (res.open(QIODevice::ReadOnly)) {
file.write(res.readAll());
res.close();
} else { return false; }
file.close();
} else { return false; }
}
}
{
const QString dirName(QString("%1/icons/hicolor/scalable/mimetypes").arg(path));
const QString fileName(QString("%1/application-x-graphics.friction.Friction.svg").arg(dirName));
qDebug() << "Checking:" << fileName;
if (!QFile::exists(dirName)) {
QDir dir(dirName);
if (!dir.mkpath(dirName)) { return false; }
}
if (!QFile::exists(fileName)) {
QFile file(fileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QFile res(resSvg);
if (res.open(QIODevice::ReadOnly | QIODevice::Text)) {
file.write(res.readAll());
res.close();
} else { return false; }
file.close();
} else { return false; }
}
}
{
const QString dirName(QString("%1/icons/hicolor/256x256/mimetypes").arg(path));
const QString fileName(QString("%1/application-x-graphics.friction.Friction.png").arg(dirName));
qDebug() << dirName << fileName;
if (!QFile::exists(dirName)) {
QDir dir(dirName);
if (!dir.mkpath(dirName)) { return false; }
}
if (!QFile::exists(fileName)) {
QFile file(fileName);
if (file.open(QIODevice::WriteOnly)) {
QFile res(resPng);
if (res.open(QIODevice::ReadOnly)) {
file.write(res.readAll());
res.close();
} else { return false; }
file.close();
} else { return false; }
}
}

return true;
}
2 changes: 2 additions & 0 deletions src/core/appsupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ class CORE_EXPORT AppSupport : public QObject
static int getProjectVersion(const QString &fileName = QString());
static const QPair<QStringList,bool> hasWriteAccess();
static bool isAppPortable();
static bool hasXDGDesktopIntegration();
static bool setupXDGDesktopIntegration();
};

#endif // APPSUPPORT_H

0 comments on commit a9731e3

Please sign in to comment.