diff --git a/src/app/tape/mapplication.cpp b/src/app/tape/mapplication.cpp index 98b245bc8..f69427993 100644 --- a/src/app/tape/mapplication.cpp +++ b/src/app/tape/mapplication.cpp @@ -53,6 +53,10 @@ #include #include +#if defined(APPIMAGE) && defined(Q_OS_LINUX) +# include "../vmisc/appimage.h" +#endif // defined(APPIMAGE) && defined(Q_OS_LINUX) + QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wmissing-prototypes") QT_WARNING_DISABLE_INTEL(1418) @@ -542,7 +546,12 @@ QString MApplication::diagramsPath() const } else { +#if defined(APPIMAGE) && defined(Q_OS_LINUX) + /* Fix path to diagrams when run inside AppImage. */ + return AppImageRoot() + PKGDATADIR + dPath; +#else return PKGDATADIR + dPath; +#endif // defined(APPIMAGE) && defined(Q_OS_LINUX) } #endif } diff --git a/src/libs/vmisc/appimage.cpp b/src/libs/vmisc/appimage.cpp index 97920ac71..dc74dce34 100644 --- a/src/libs/vmisc/appimage.cpp +++ b/src/libs/vmisc/appimage.cpp @@ -29,12 +29,37 @@ #include #include +#include +#include #include +#include extern "C" { #include "binreloc.h" } +#include "../vmisc/def.h" +#include "compatibility.h" +namespace +{ +//--------------------------------------------------------------------------------------------------------------------- +QStringList ReverseList(const QStringList &list) +{ + if (list.isEmpty()) + { + return list; + } + QVector reversedList(list.size()); + qint32 j = 0; + for (qint32 i = list.size() - 1; i >= 0; --i) + { + reversedList.replace(j, list.at(i)); + ++j; + } + return ConvertToList(reversedList); +} +} +//--------------------------------------------------------------------------------------------------------------------- /* When deploying with AppImage based on OpenSuse, the ICU library has a hardcoded path to the icudt*.dat file. * This prevents the library from using shared in memory data. There are few ways to resolve this issue. According * to documentation we can either use ICU_DATA environment variable or the function u_setDataDirectory(). @@ -61,3 +86,45 @@ char* IcuDataPath(const char* correction) return data_path; } + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief AppImageRoot returns path to AppImage root folder. Because after mount path to /usr folder looks like + * /tmp/.mount_valentXwmbwE/usr, the root part must be extracted to fix all paths when application is in AppImage + * format. + * + * Function we return empty if expected path is not compatible with current application directory path. + * @return path to AppImage root folder + */ +QString AppImageRoot() +{ + return AppImageRoot(QCoreApplication::applicationDirPath(), QString(BINDIR)); +} + +//--------------------------------------------------------------------------------------------------------------------- +QString AppImageRoot(const QString &applicationDir, const QString &defaultAppDir) +{ + QStringList appSub = SplitFilePaths(applicationDir); + QStringList defaultSub = SplitFilePaths(defaultAppDir); + + if (appSub.isEmpty() || defaultSub.isEmpty() || appSub.size() <= defaultSub.size()) + { + return QString(); + } + + appSub = ReverseList(appSub); + defaultSub = ReverseList(defaultSub); + + for (int i = 0; i < defaultSub.size(); ++i) + { + if (defaultSub.at(i) != appSub.at(i)) + { + return QString(); + } + } + + QStringList rootSub = appSub.mid(defaultSub.size()); + rootSub = ReverseList(rootSub); + + return '/' + rootSub.join('/'); +} diff --git a/src/libs/vmisc/appimage.h b/src/libs/vmisc/appimage.h index fa5c8d243..0ec6a3adc 100644 --- a/src/libs/vmisc/appimage.h +++ b/src/libs/vmisc/appimage.h @@ -28,6 +28,11 @@ #ifndef APPIMAGE_H #define APPIMAGE_H +class QString; + char* IcuDataPath(const char* correction); +QString AppImageRoot(); +QString AppImageRoot(const QString &applicationDir, const QString &defaultAppDir); + #endif // APPIMAGE_H diff --git a/src/libs/vmisc/def.cpp b/src/libs/vmisc/def.cpp index fcc0a33ed..7584da3af 100644 --- a/src/libs/vmisc/def.cpp +++ b/src/libs/vmisc/def.cpp @@ -791,3 +791,25 @@ IncrementType StringToIncrementType(const QString &value) } return IncrementType::Increment; } + +//--------------------------------------------------------------------------------------------------------------------- +QStringList SplitFilePaths(const QString &path) +{ + QStringList result; + QString subPath = QDir::cleanPath(path); + QString lastFileName; + + do + { + QFileInfo fileInfo(subPath); + lastFileName = fileInfo.fileName(); + if (not lastFileName.isEmpty()) + { + result.prepend(lastFileName); + subPath = fileInfo.path(); + } + } + while(not lastFileName.isEmpty()); + + return result; +} diff --git a/src/libs/vmisc/def.h b/src/libs/vmisc/def.h index f37bfe35d..384af6fb2 100644 --- a/src/libs/vmisc/def.h +++ b/src/libs/vmisc/def.h @@ -597,6 +597,8 @@ Q_REQUIRED_RESULT QString StrippedName(const QString &fullFileName); Q_REQUIRED_RESULT QString RelativeMPath(const QString &patternPath, const QString &absoluteMPath); Q_REQUIRED_RESULT QString AbsoluteMPath(const QString &patternPath, const QString &relativeMPath); +QStringList SplitFilePaths(const QString &path); + Q_REQUIRED_RESULT QSharedPointer PreparePrinter(const QPrinterInfo &info, QPrinter::PrinterMode mode = QPrinter::ScreenResolution); diff --git a/src/libs/vmisc/vabstractapplication.cpp b/src/libs/vmisc/vabstractapplication.cpp index 181f73a01..f201134e7 100644 --- a/src/libs/vmisc/vabstractapplication.cpp +++ b/src/libs/vmisc/vabstractapplication.cpp @@ -49,6 +49,10 @@ # include #endif +#if defined(APPIMAGE) && defined(Q_OS_LINUX) +# include "appimage.h" +#endif // defined(APPIMAGE) && defined(Q_OS_LINUX) + const QString VAbstractApplication::patternMessageSignature = QStringLiteral("[PATTERN MESSAGE]"); //--------------------------------------------------------------------------------------------------------------------- @@ -175,7 +179,12 @@ QString VAbstractApplication::translationsPath(const QString &locale) const } else { +#if defined(APPIMAGE) && defined(Q_OS_LINUX) + /* Fix path to trasnaltions when run inside AppImage. */ + return AppImageRoot() + PKGDATADIR + trPath; +#else return PKGDATADIR + trPath; +#endif // defined(APPIMAGE) && defined(Q_OS_LINUX) } #endif } diff --git a/src/libs/vwidgets/vabstractmainwindow.cpp b/src/libs/vwidgets/vabstractmainwindow.cpp index 10f62dba8..9c0d2b108 100644 --- a/src/libs/vwidgets/vabstractmainwindow.cpp +++ b/src/libs/vwidgets/vabstractmainwindow.cpp @@ -30,6 +30,7 @@ #include "../vpropertyexplorer/checkablemessagebox.h" #include "../vmisc/vabstractapplication.h" #include "../vmisc/compatibility.h" +#include "../vmisc/def.h" #include "dialogs/dialogexporttocsv.h" #include @@ -44,28 +45,6 @@ namespace { -//--------------------------------------------------------------------------------------------------------------------- -QStringList SplitFilePaths(const QString &path) -{ - QStringList result; - QString subPath = QDir::cleanPath(path); - QString lastFileName; - - do - { - QFileInfo fileInfo(subPath); - lastFileName = fileInfo.fileName(); - if (not lastFileName.isEmpty()) - { - result.prepend(lastFileName); - subPath = fileInfo.path(); - } - } - while(not lastFileName.isEmpty()); - - return result; -} - //--------------------------------------------------------------------------------------------------------------------- QStringList ReverseList(const QStringList &list) {