1/***************************************************************************
2 * Copyright (C) 2007 by Kevin Krammer <kevin.krammer@gmx.at> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU Library General Public License as *
6 * published by the Free Software Foundation; either version 2 of the *
7 * License, or (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU Library General Public *
15 * License along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
19
20#ifndef XDGBASEDIRS_H
21#define XDGBASEDIRS_H
22
23// Qt includes
24#include <QtCore/QFlags>
25#include <QtCore/QStringList>
26
27#include "akonadiprotocolinternals_export.h"
28
29// forward declarations
30class QString;
31
32namespace Akonadi {
33
34class XdgBaseDirsPrivate;
35
36/**
37 @brief Resource type based handling of standard directories
38
39 Developers of several Free Software desktop projects have created
40 a specification for handling so-called "base directories", i.e.
41 lists of system wide directories and directories within each user's
42 home directory for installing and later finding certain files.
43
44 This class handles the respective behaviour, i.e. environment variables
45 and their defaults, for the following type of resources:
46 - "config"
47 - "data"
48
49 Example: getting the Akonadi server config file "akonadiserverrc", assuming
50 that Akonadi stores its config in an additional subdirectoy called "akonadi"
51 @code
52 QString relativeFileName = QLatin1String( "akonadi/akonadiserverrc" );
53
54 // look for the file "akonadiserverrc" with additional subdirectory "akonadi"
55 // in any directory associated with resource type "config"
56 QString configFile = XdgBaseDirs::findResourceFile( "config", relativeFileName );
57
58 if ( configFile.isEmpty() ) {
59 // No config file yet, get the suitable user specific directory for storing
60 // a new one
61 configFile = XdgBaseDirs::saveDir( "config", QLatin1String( "akonadi" ) );
62 configFile += QLatin1String( "akonadiserverrc" );
63 }
64
65 QSettings serverConfig( configFile );
66 @endcode
67
68 @author Kevin Krammer, <kevin.krammer@gmx.at>
69
70 @see http://www.freedesktop.org/wiki/Specifications/basedir-spec
71 */
72class AKONADIPROTOCOLINTERNALS_EXPORT XdgBaseDirs
73{
74public:
75 /**
76 @brief Creates the instance
77 */
78 XdgBaseDirs();
79
80 /**
81 @brief Destroys the instance
82 */
83 ~XdgBaseDirs();
84
85 /**
86 @brief Returns the user specific directory for the given resource type
87
88 Unless the user's environment has a specific path set as an override
89 this will be the default as defined in the freedesktop.org base-dir-spec
90
91 @note Caches the value of the first call
92
93 @param resource a named resource type, e.g. "config"
94
95 @return a directory path
96
97 @see systemPathList()
98 @see saveDir()
99 */
100 static QString homePath(const char *resource);
101
102 /**
103 @brief Returns the list of system wide directories for a given resource type
104
105 The returned list can contain one or more directory paths. If there are more
106 than one, the list is sorted by falling priority, i.e. if an entry is valid
107 for the respective use case (e.g. contains a file the application looks for)
108 the list should not be processed further.
109
110 @note The user's resource path should, to be compliant with the spec,
111 always be treated as having higher priority than any path in the
112 list of system wide paths
113
114 @note Caches the value of the first call
115
116 @param resource a named resource type, e.g. "config"
117
118 @return a priority sorted list of directory paths
119
120 @see homePath()
121 */
122 static QStringList systemPathList(const char *resource);
123
124 /**
125 @brief Searches the resource specific directories for a given file
126
127 Convenience method for finding a given file (with optional relative path)
128 in any of the configured base directories for a given resource type.
129
130 Will check the user local directory first and then process the system
131 wide path list according to the inherent priority.
132
133 @param resource a named resource type, e.g. "config"
134 @param relPath relative path of a file to look for,
135 e.g."akonadi/akonadiserverrc"
136
137 @returns the file path of the first match, or @c QString() if no such
138 relative path exists in any of the base directories or if
139 a match is not a file
140
141 @see findResourceDir()
142 @see saveDir
143 */
144 static QString findResourceFile(const char *resource, const QString &relPath);
145
146 /**
147 @brief Searches the executable specific directories for a given file
148
149 Convenience method for finding a given executable (with optional relative path)
150 in any of the configured directories for a this special type.
151
152 @note This is not based on the XDG base dir spec, since it does not cover
153 executable
154
155 @param relPath relative path of a file to look for,
156 e.g."akonadiserver"
157 @param searchPath additional paths to search for the executable,
158 only used if the file was not found in PATH and the install prefix
159
160 @returns the file path of the first match, or @c QString() if no such
161 relative path exists in any of the base directories
162
163 @see findResourceFile()
164 */
165 static QString findExecutableFile(const QString &relPath, const QStringList &searchPath = QStringList());
166
167 /**
168 @brief Searches the plugin specific directories for a given file
169
170 Convenience method for finding a given plugin (with optional relative path)
171 in any of the configured directories for a this special type.
172
173 @note This is not based on the XDG base dir spec, since it does not cover
174 plugins
175
176 @param relPath relative path of a file to look for,
177 e.g."akonadi_knut_resource"
178 @param searchPath additional paths to search for the plugin,
179 only used if the file was not found in QT_PLUGIN_PATH and the install prefix
180
181 @returns the file path of the first match, or @c QString() if no such
182 relative path exists in any of the base directories
183
184 @see findResourceFile()
185 */
186 static QString findPluginFile(const QString &relPath, const QStringList &searchPath = QStringList());
187
188 /**
189 @brief Returns plugin specific directories
190
191 Convenience method for listing directories that can be scanned for available
192 plugins.
193
194 @note This is not based on the XDG base dir spec, since it does not cover
195 plugins.
196
197 @return directories where application should look for plugins
198 */
199 static QStringList findPluginDirs();
200
201 /**
202 @brief Searches the resource specific directories for a given subdirectory
203
204 Convenience method for finding a given relative subdirectory in any of
205 the configured base directories for a given resource type.
206
207 Will check the user local directory first and then process the system
208 wide path list according to the inherent priority.
209
210 Use findAllResourceDirs() if looking for all directories with the given
211 subdirectory.
212
213 @param resource a named resource type, e.g. "config"
214 @param relPath relative path of a subdirectory to look for,
215 e.g."akonadi/agents"
216
217 @returns the directory path of the first match, or @c QString() if no such
218 relative path exists in any of the base directories or if
219 a match is not a directory
220
221 @see findResourceFile()
222 @see saveDir()
223 */
224 static QString findResourceDir(const char *resource, const QString &relPath);
225
226 /**
227 @brief Searches the resource specific directories for a given subdirectory
228
229 Convenience method for getting a list of directoreis with a given relative
230 subdirectory in any of the configured base directories for a given
231 resource type.
232
233 Will check the user local directory first and then process the system
234 wide path list according to the inherent priority.
235
236 Similar to findResourceDir() but does not just find the first best match
237 but all matching resource directories. The resuling list will be sorted
238 according to the same proprity criteria.
239
240 @param resource a named resource type, e.g. "config"
241 @param relPath relative path of a subdirectory to look for,
242 e.g."akonadi/agents"
243
244 @returns a list of directory paths, or @c QString() if no such
245 relative path exists in any of the base directories or if
246 non of the matches is a directory
247
248 @see findResourceDir()
249 */
250 static QStringList findAllResourceDirs(const char *resource, const QString &relPath);
251
252 /**
253 @brief Finds or creates the "save to" directory for a given resource
254
255 Convenience method for creating subdirectores relative to a given
256 resource type's user directory, i.e. homePath() + relPath
257
258 If the target directory does not exists, it an all necessary parent
259 directories will be created, unless denied by the filesystem.
260
261 @param resource a named resource type, e.g. "config"
262 @param relPath relative path of a directory to be used for file writing
263
264 @return the directory path of the "save to" directory or @c QString()
265 if the directory or one of its parents could not be created
266
267 @see findResourceDir()
268 */
269 static QString saveDir(const char *resource, const QString &relPath);
270
271 /**
272 * @brief Open mode flags for resource files
273 *
274 * FileAccessMode is a typedef for QFlags<FileAccessFlag>. It stores
275 * a OR combination of FileAccessFlag values
276 */
277 enum FileAccessFlag {
278 ReadOnly = 0x1,
279 WriteOnly = 0x2,
280 ReadWrite = ReadOnly | WriteOnly
281 };
282
283 typedef QFlags<FileAccessFlag> FileAccessMode;
284
285 /**
286 * @brief Returns the path of the Akonadi server config file
287 *
288 * Convenience method for getting the server config file "akonadiserverrc"
289 * since this is an often needed procedure in several parts of the code.
290 *
291 * @param openMode how the application wants to use the config file
292 *
293 * @return the path of the server config file, suitable for \p openMode
294 */
295 static QString akonadiServerConfigFile(FileAccessMode openMode = ReadOnly);
296
297 /**
298 * @brief Returns the path of the Akonadi data connection config file
299 *
300 * Convenience method for getting the server config file "akonadiconnectionrc"
301 * since this is an often needed procedure in several parts of the code.
302 *
303 * @param openMode how the application wants to use the config file
304 *
305 * @return the path of the data connection config file, suitable for \p openMode
306 */
307 static QString akonadiConnectionConfigFile(FileAccessMode openMode = ReadOnly);
308
309private:
310 XdgBaseDirsPrivate *const d;
311
312private:
313 static QString akonadiConfigFile(const QString &file, FileAccessMode openMode);
314
315private:
316 XdgBaseDirs(const XdgBaseDirs &);
317 XdgBaseDirs &operator=(const XdgBaseDirs &);
318};
319
320}
321
322#endif
323