Akonadi

standarddirs.cpp
1/*
2 SPDX-FileCopyrightText: 2011 Volker Krause <vkrause@kde.org>
3 SPDX-FileCopyrightText: 2018 Daniel Vrátil <dvratil@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "akonadiprivate_debug.h"
9#include "instance_p.h"
10#include "standarddirs_p.h"
11
12#include <QCoreApplication>
13#include <QDir>
14#include <QFile>
15#include <QFileInfo>
16#include <QList>
17#include <QStandardPaths>
18
19using namespace Akonadi;
20
21namespace
22{
23QString buildFullRelPath(const char *resource, const QString &relPath)
24{
25 QString fullRelPath = QStringLiteral("/akonadi");
26#ifdef Q_OS_WIN
27 // On Windows all Generic*Location fall into ~/AppData/Local so we need to disambiguate
28 // inside the "akonadi" folder whether it's data or config.
29 fullRelPath += QLatin1Char('/') + QString::fromLocal8Bit(resource);
30#else
31 Q_UNUSED(resource)
32#endif
33
34 if (Akonadi::Instance::hasIdentifier()) {
35 fullRelPath += QLatin1StringView("/instance/") + Akonadi::Instance::identifier();
36 }
37 if (!relPath.isEmpty()) {
38 fullRelPath += QLatin1Char('/') + relPath;
39 }
40 return fullRelPath;
41}
42
43} // namespace
44
45QString StandardDirs::configFile(const QString &configFile, FileAccessMode openMode)
46{
47 const QString savePath = StandardDirs::saveDir("config") + QLatin1Char('/') + configFile;
48 if (openMode == WriteOnly) {
49 return savePath;
50 }
51
53 // HACK: when using instance namespaces, ignore the non-namespaced file
54 if (Akonadi::Instance::hasIdentifier() && path.startsWith(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation))) {
55 path.clear();
56 }
57
58 if (path.isEmpty()) {
59 return savePath;
60 } else if (openMode == ReadOnly || path == savePath) {
61 return path;
62 }
63
64 // file found in system paths and mode is ReadWrite, thus
65 // we copy to the home path location and return this path
66 QFile::copy(path, savePath);
67 return savePath;
68}
69
70QString StandardDirs::serverConfigFile(FileAccessMode openMode)
71{
72 return configFile(QStringLiteral("akonadiserverrc"), openMode);
73}
74
75QString StandardDirs::connectionConfigFile(FileAccessMode openMode)
76{
77 return configFile(QStringLiteral("akonadiconnectionrc"), openMode);
78}
79
80QString StandardDirs::agentsConfigFile(FileAccessMode openMode)
81{
82 return configFile(QStringLiteral("agentsrc"), openMode);
83}
84
85QString StandardDirs::agentConfigFile(const QString &identifier, FileAccessMode openMode)
86{
87 return configFile(QStringLiteral("agent_config_") + identifier, openMode);
88}
89
90QString StandardDirs::saveDir(const char *resource, const QString &relPath)
91{
92 const QString fullRelPath = buildFullRelPath(resource, relPath);
93 QString fullPath;
94 if (qstrncmp(resource, "config", 6) == 0) {
96 } else if (qstrncmp(resource, "data", 4) == 0) {
98 } else if (qstrncmp(resource, "runtime", 7) == 0) {
100 } else {
101 qt_assert_x(__FUNCTION__, "Invalid resource type", __FILE__, __LINE__);
102 return {};
103 }
104
105 // ensure directory exists or is created
106 QFileInfo fileInfo(fullPath);
107 if (fileInfo.exists()) {
108 if (fileInfo.isDir()) {
109 return fullPath;
110 } else {
111 qCWarning(AKONADIPRIVATE_LOG) << "StandardDirs::saveDir: '" << fileInfo.absoluteFilePath() << "' exists but is not a directory";
112 }
113 } else {
114 if (!QDir::home().mkpath(fileInfo.absoluteFilePath())) {
115 qCWarning(AKONADIPRIVATE_LOG) << "StandardDirs::saveDir: failed to create directory '" << fileInfo.absoluteFilePath() << "'";
116 } else {
117 return fullPath;
118 }
119 }
120
121 return {};
122}
123
124QString StandardDirs::locateResourceFile(const char *resource, const QString &relPath)
125{
126 const QString fullRelPath = buildFullRelPath(resource, relPath);
128 QStandardPaths::StandardLocation genericLocation;
129 if (qstrncmp(resource, "config", 6) == 0) {
132 } else if (qstrncmp(resource, "data", 4) == 0) {
134 genericLocation = QStandardPaths::GenericDataLocation;
135 } else {
136 qt_assert_x(__FUNCTION__, "Invalid resource type", __FILE__, __LINE__);
137 return {};
138 }
139
140 const auto locateFile = [](QStandardPaths::StandardLocation location, const QString &relPath) -> QString {
141 const auto path = QStandardPaths::locate(location, relPath);
142 if (!path.isEmpty()) {
143 QFileInfo file(path);
144 if (file.exists() && file.isFile() && file.isReadable()) {
145 return path;
146 }
147 }
148 return {};
149 };
150
151 // Always honor instance in user-specific locations
152 for (const auto location : std::as_const(userLocations)) {
153 const auto path = locateFile(location, fullRelPath);
154 if (!path.isEmpty()) {
155 return path;
156 }
157 }
158
159 const auto configPath = QStringLiteral(CONFIG_INSTALL_DIR);
160 if (!configPath.isEmpty()) {
161 QFileInfo file(configPath);
162 if (file.exists() && file.isFile() && file.isReadable()) {
163 return configPath;
164 }
165 }
166
167 // First try instance-specific path in generic locations
168 auto path = locateFile(genericLocation, fullRelPath);
169 if (!path.isEmpty()) {
170 return path;
171 }
172
173 // Fallback to global instance path in generic locations
174 path = locateFile(genericLocation, QLatin1StringView("/akonadi/") + relPath);
175 if (!path.isEmpty()) {
176 return path;
177 }
178
179 return {};
180}
181
182QStringList StandardDirs::locateAllResourceDirs(const QString &relPath)
183{
185}
186
187QString StandardDirs::findExecutable(const QString &executableName)
188{
189 QString executable = QStandardPaths::findExecutable(executableName, {qApp->applicationDirPath()});
190 if (executable.isEmpty()) {
191 executable = QStandardPaths::findExecutable(executableName);
192 }
193 return executable;
194}
Helper integration between Akonadi and Qt.
KIOCORE_EXPORT MkpathJob * mkpath(const QUrl &url, const QUrl &baseUrl=QUrl(), JobFlags flags=DefaultFlags)
QVariant location(const QVariant &res)
QString path(const QString &relativePath)
A glue between Qt and the standard library.
QDir home()
bool copy(const QString &fileName, const QString &newName)
QString findExecutable(const QString &executableName, const QStringList &paths)
QString locate(StandardLocation type, const QString &fileName, LocateOptions options)
QStringList locateAll(StandardLocation type, const QString &fileName, LocateOptions options)
QString writableLocation(StandardLocation type)
void clear()
QString fromLocal8Bit(QByteArrayView str)
bool isEmpty() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:13:38 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.