Akonadi

standarddirs.cpp
1 /*
2  SPDX-FileCopyrightText: 2011 Volker Krause <[email protected]>
3  SPDX-FileCopyrightText: 2018 Daniel Vr├ítil <[email protected]>
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 <QStandardPaths>
17 #include <QVector>
18 
19 using namespace Akonadi;
20 
21 namespace
22 {
23 QString 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 += QLatin1String("/instance/") + Akonadi::Instance::identifier();
36  }
37  if (!relPath.isEmpty()) {
38  fullRelPath += QLatin1Char('/') + relPath;
39  }
40  return fullRelPath;
41 }
42 
43 } // namespace
44 
45 QString 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 
52  auto path = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QLatin1String("akonadi/") + configFile);
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 
70 QString StandardDirs::serverConfigFile(FileAccessMode openMode)
71 {
72  return configFile(QStringLiteral("akonadiserverrc"), openMode);
73 }
74 
75 QString StandardDirs::connectionConfigFile(FileAccessMode openMode)
76 {
77  return configFile(QStringLiteral("akonadiconnectionrc"), openMode);
78 }
79 
80 QString StandardDirs::agentsConfigFile(FileAccessMode openMode)
81 {
82  return configFile(QStringLiteral("agentsrc"), openMode);
83 }
84 
85 QString StandardDirs::agentConfigFile(const QString &identifier, FileAccessMode openMode)
86 {
87  return configFile(QStringLiteral("agent_config_") + identifier, openMode);
88 }
89 
90 QString 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 
124 QString 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) {
131  genericLocation = QStandardPaths::GenericConfigLocation;
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  // First try instance-specific path in generic locations
160  auto path = locateFile(genericLocation, fullRelPath);
161  if (!path.isEmpty()) {
162  return path;
163  }
164 
165  // Fallback to global instance path in generic locations
166  path = locateFile(genericLocation, QLatin1String("/akonadi/") + relPath);
167  if (!path.isEmpty()) {
168  return path;
169  }
170 
171  return {};
172 }
173 
174 QStringList StandardDirs::locateAllResourceDirs(const QString &relPath)
175 {
177 }
178 
179 QString StandardDirs::findExecutable(const QString &executableName)
180 {
181  QString executable = QStandardPaths::findExecutable(executableName, {qApp->applicationDirPath()});
182  if (executable.isEmpty()) {
183  executable = QStandardPaths::findExecutable(executableName);
184  }
185  return executable;
186 }
QVariant location(const QVariant &res)
bool copy(const QString &newName)
QString writableLocation(QStandardPaths::StandardLocation type)
QString locate(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options)
QString findExecutable(const QString &executableName, const QStringList &paths)
QString fromLocal8Bit(const char *str, int size)
QDir home()
bool isEmpty() const const
KIOCORE_EXPORT MkpathJob * mkpath(const QUrl &url, const QUrl &baseUrl=QUrl(), JobFlags flags=DefaultFlags)
QStringList locateAll(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options)
Helper integration between Akonadi and Qt.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Sat Jun 25 2022 06:00:33 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.