diff --git a/src/app/main.cpp b/src/app/main.cpp
index 6f586ad66..1e7279716 100644
--- a/src/app/main.cpp
+++ b/src/app/main.cpp
@@ -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);
diff --git a/src/app/resources.qrc b/src/app/resources.qrc
index 01f1a133b..c5cc628e1 100644
--- a/src/app/resources.qrc
+++ b/src/app/resources.qrc
@@ -32,5 +32,8 @@
presets/render/003-friction-preset-prores-444.conf
presets/render/002-friction-preset-mp4-h264-mp3.conf
presets/render/001-friction-preset-mp4-h264.conf
+ xdg/friction.xml
+ xdg/friction.desktop
+ icons/hicolor/scalable/apps/graphics.friction.Friction.svg
diff --git a/src/app/xdg/friction.desktop b/src/app/xdg/friction.desktop
new file mode 100644
index 000000000..ba55d1e86
--- /dev/null
+++ b/src/app/xdg/friction.desktop
@@ -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
diff --git a/src/app/xdg/friction.xml b/src/app/xdg/friction.xml
new file mode 100644
index 000000000..2c4f9523c
--- /dev/null
+++ b/src/app/xdg/friction.xml
@@ -0,0 +1,7 @@
+
+
+
+ Friction
+
+
+
diff --git a/src/core/appsupport.cpp b/src/core/appsupport.cpp
index 776ee54cd..051850e0e 100644
--- a/src/core/appsupport.cpp
+++ b/src/core/appsupport.cpp
@@ -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;
+}
diff --git a/src/core/appsupport.h b/src/core/appsupport.h
index 7f1514313..607cdccf6 100644
--- a/src/core/appsupport.h
+++ b/src/core/appsupport.h
@@ -119,6 +119,8 @@ class CORE_EXPORT AppSupport : public QObject
static int getProjectVersion(const QString &fileName = QString());
static const QPair hasWriteAccess();
static bool isAppPortable();
+ static bool hasXDGDesktopIntegration();
+ static bool setupXDGDesktopIntegration();
};
#endif // APPSUPPORT_H