Akonadi

standarddirs.cpp
1 /*
2  Copyright (c) 2011 Volker Krause <[email protected]>
3  Copyright (c) 2018 Daniel Vrátil <[email protected]>
4 
5  This library is free software; you can redistribute it and/or modify it
6  under the terms of the GNU Library General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or (at your
8  option) any later version.
9 
10  This library is distributed in the hope that it will be useful, but WITHOUT
11  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13  License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to the
17  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  02110-1301, USA.
19 */
20 
21 #include "standarddirs_p.h"
22 #include "instance_p.h"
23 #include "akonadiprivate_debug.h"
24 
25 #include <QCoreApplication>
26 #include <QStandardPaths>
27 #include <QFile>
28 #include <QFileInfo>
29 #include <QVector>
30 #include <QDir>
31 
32 using namespace Akonadi;
33 
34 namespace {
35 
36 QString buildFullRelPath(const char *resource, const QString &relPath)
37 {
38  QString fullRelPath = QStringLiteral("/akonadi");
39 #ifdef Q_OS_WIN
40  // On Windows all Generic*Location fall into ~/AppData/Local so we need to disambiguate
41  // inside the "akonadi" folder whether it's data or config.
42  fullRelPath += QLatin1Char('/') + QString::fromLocal8Bit(resource);
43 #else
44  Q_UNUSED(resource);
45 #endif
46 
47  if (Akonadi::Instance::hasIdentifier()) {
48  fullRelPath += QLatin1String("/instance/") + Akonadi::Instance::identifier();
49  }
50  if (!relPath.isEmpty()) {
51  fullRelPath += QLatin1Char('/') + relPath;
52  }
53  return fullRelPath;
54 }
55 
56 }
57 
58 QString StandardDirs::configFile(const QString &configFile, FileAccessMode openMode)
59 {
60  const QString savePath = StandardDirs::saveDir("config") + QLatin1Char('/') + configFile;
61  if (openMode == WriteOnly) {
62  return savePath;
63  }
64 
65 
66  auto path = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, QLatin1String("akonadi/") + configFile);
67  // HACK: when using instance namespaces, ignore the non-namespaced file
68  if (Akonadi::Instance::hasIdentifier() && path.startsWith(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation))) {
69  path.clear();
70  }
71 
72  if (path.isEmpty()) {
73  return savePath;
74  } else if (openMode == ReadOnly || path == savePath) {
75  return path;
76  }
77 
78  // file found in system paths and mode is ReadWrite, thus
79  // we copy to the home path location and return this path
80  QFile::copy(path, savePath);
81  return savePath;
82 }
83 
84 QString StandardDirs::serverConfigFile(FileAccessMode openMode)
85 {
86  return configFile(QStringLiteral("akonadiserverrc"), openMode);
87 }
88 
89 QString StandardDirs::connectionConfigFile(FileAccessMode openMode)
90 {
91  return configFile(QStringLiteral("akonadiconnectionrc"), openMode);
92 }
93 
94 QString StandardDirs::agentsConfigFile(FileAccessMode openMode)
95 {
96  return configFile(QStringLiteral("agentsrc"), openMode);
97 }
98 
99 QString StandardDirs::agentConfigFile(const QString &identifier, FileAccessMode openMode)
100 {
101  return configFile(QStringLiteral("agent_config_") + identifier, openMode);
102 }
103 
104 QString StandardDirs::saveDir(const char *resource, const QString &relPath)
105 {
106  const QString fullRelPath = buildFullRelPath(resource, relPath);
107  QString fullPath;
108  if (qstrncmp(resource, "config", 6) == 0) {
109  fullPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + fullRelPath;
110  } else if (qstrncmp(resource, "data", 4) == 0) {
111  fullPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + fullRelPath;
112  } else if (qstrncmp(resource, "runtime", 7) == 0) {
113  fullPath = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation) + fullRelPath;
114  } else {
115  qt_assert_x(__FUNCTION__, "Invalid resource type", __FILE__, __LINE__);
116  return {};
117  }
118 
119  // ensure directory exists or is created
120  QFileInfo fileInfo(fullPath);
121  if (fileInfo.exists()) {
122  if (fileInfo.isDir()) {
123  return fullPath;
124  } else {
125  qCWarning(AKONADIPRIVATE_LOG) << "StandardDirs::saveDir: '" << fileInfo.absoluteFilePath()
126  << "' exists but is not a directory";
127  }
128  } else {
129  if (!QDir::home().mkpath(fileInfo.absoluteFilePath())) {
130  qCWarning(AKONADIPRIVATE_LOG) << "StandardDirs::saveDir: failed to create directory '"
131  << fileInfo.absoluteFilePath() << "'";
132  } else {
133  return fullPath;
134  }
135  }
136 
137  return {};
138 }
139 
140 QString StandardDirs::locateResourceFile(const char *resource, const QString &relPath)
141 {
142  const QString fullRelPath = buildFullRelPath(resource, relPath);
144  QStandardPaths::StandardLocation genericLocation;
145  if (qstrncmp(resource, "config", 6) == 0) {
146  userLocations = { QStandardPaths::AppConfigLocation,
147  QStandardPaths::ConfigLocation };
148  genericLocation = QStandardPaths::GenericConfigLocation;
149  } else if (qstrncmp(resource, "data", 4) == 0) {
150  userLocations = { QStandardPaths::AppLocalDataLocation,
151  QStandardPaths::AppDataLocation };
152  genericLocation = QStandardPaths::GenericDataLocation;
153  } else {
154  qt_assert_x(__FUNCTION__, "Invalid resource type", __FILE__, __LINE__);
155  return {};
156  }
157 
158  const auto locateFile = [](QStandardPaths::StandardLocation location, const QString &relPath) -> QString {
159  const auto path = QStandardPaths::locate(location, relPath);
160  if (!path.isEmpty()) {
161  QFileInfo file(path);
162  if (file.exists() && file.isFile() && file.isReadable()) {
163  return path;
164  }
165  }
166  return {};
167  };
168 
169  // Always honor instance in user-specific locations
170  for (const auto location : qAsConst(userLocations)) {
171  const auto path = locateFile(location, fullRelPath);
172  if (!path.isEmpty()) {
173  return path;
174  }
175  }
176 
177  // First try instance-specific path in generic locations
178  auto path = locateFile(genericLocation, fullRelPath);
179  if (!path.isEmpty()) {
180  return path;
181  }
182 
183  // Fallback to global instance path in generic locations
184  path = locateFile(genericLocation, QLatin1String("/akonadi/") + relPath);
185  if (!path.isEmpty()) {
186  return path;
187  }
188 
189  return {};
190 }
191 
192 QStringList StandardDirs::locateAllResourceDirs(const QString &relPath)
193 {
194  return QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, relPath,
195  QStandardPaths::LocateDirectory);
196 }
197 
198 QString StandardDirs::findExecutable(const QString &executableName)
199 {
200  QString executable = QStandardPaths::findExecutable(executableName, {qApp->applicationDirPath()});
201  if (executable.isEmpty()) {
202  executable = QStandardPaths::findExecutable(executableName);
203  }
204  return executable;
205 }
QString writableLocation(QStandardPaths::StandardLocation type)
QStringList locateAll(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options)
KIOCORE_EXPORT MkpathJob * mkpath(const QUrl &url, const QUrl &baseUrl=QUrl(), JobFlags flags=DefaultFlags)
QVariant location(const QVariant &res)
QString findExecutable(const QString &executableName, const QStringList &paths)
bool copy(const QString &newName)
QString fromLocal8Bit(const char *str, int size)
bool isEmpty() const const
Definition: item.h:44
Helper integration between Akonadi and Qt.
QDir home()
QString locate(QStandardPaths::StandardLocation type, const QString &fileName, QStandardPaths::LocateOptions options)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed May 27 2020 22:43:40 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.