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.
This commit is contained in:
Roman Telezhynskyi 2020-07-13 16:11:57 +03:00
parent ee29874543
commit acac092ff3
7 changed files with 115 additions and 22 deletions

View File

@ -53,6 +53,10 @@
#include <QSpacerItem>
#include <QThread>
#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
}

View File

@ -29,12 +29,37 @@
#include <stdlib.h>
#include <unicode/putil.h>
#include <QString>
#include <QCoreApplication>
#include <cstring>
#include <QVector>
extern "C" {
#include "binreloc.h"
}
#include "../vmisc/def.h"
#include "compatibility.h"
namespace
{
//---------------------------------------------------------------------------------------------------------------------
QStringList ReverseList(const QStringList &list)
{
if (list.isEmpty())
{
return list;
}
QVector<QString> 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('/');
}

View File

@ -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

View File

@ -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;
}

View File

@ -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<QPrinter> PreparePrinter(const QPrinterInfo &info,
QPrinter::PrinterMode mode = QPrinter::ScreenResolution);

View File

@ -49,6 +49,10 @@
# include <unistd.h>
#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
}

View File

@ -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 <QStyle>
@ -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)
{