From acac092ff30a0cee8ae120b33a26a94e54b000b4 Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Mon, 13 Jul 2020 16:11:57 +0300 Subject: [PATCH] Fix path to AppImage root folder. Valentina relies on absolute paths to find path to components. In case of AppImage path will be mimicked, but root must be corrected to take into account tmp folder AppImage mounts data. --- src/app/tape/mapplication.cpp | 9 +++ src/libs/vmisc/appimage.cpp | 67 +++++++++++++++++++++++ src/libs/vmisc/appimage.h | 5 ++ src/libs/vmisc/def.cpp | 22 ++++++++ src/libs/vmisc/def.h | 2 + src/libs/vmisc/vabstractapplication.cpp | 9 +++ src/libs/vwidgets/vabstractmainwindow.cpp | 23 +------- 7 files changed, 115 insertions(+), 22 deletions(-) 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) {