1/******************************************************************************
2* Copyright 2007 by Aaron Seigo <aseigo@kde.org> *
3* *
4* This library is free software; you can redistribute it and/or *
5* modify it under the terms of the GNU Library General Public *
6* License as published by the Free Software Foundation; either *
7* version 2 of the License, or (at your option) any later version. *
8* *
9* This library 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 GNU *
12* Library General Public License for more details. *
13* *
14* You should have received a copy of the GNU Library General Public License *
15* along with this library; see the file COPYING.LIB. If not, write to *
16* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17* Boston, MA 02110-1301, USA. *
18*******************************************************************************/
19
20#ifndef PLASMA_PACKAGESTRUCTURE_H
21#define PLASMA_PACKAGESTRUCTURE_H
22
23#include <QtCore/QStringList>
24#include <QtCore/QSharedData>
25
26#include <kgenericfactory.h>
27#include <klocale.h>
28#include <ksharedptr.h>
29
30#include <plasma/version.h>
31#include "packagemetadata.h"
32
33class KConfigBase;
34
35namespace Plasma
36{
37
38class PackageStructurePrivate;
39
40/**
41 * @class PackageStructure plasma/packagestructure.h <Plasma/PackageStructure>
42 *
43 * @short A description of the expected file structure of a given package type
44 *
45 * PackageStructure defines what is in a package. This information is used
46 * to create packages and provides a way to programatically refer to contents.
47 *
48 * An example usage of this class might be:
49 *
50 @code
51 PackageStructure structure;
52
53 structure.addDirectoryDefinition("images", "pics/", i18n("Images"));
54 QStringList mimetypes;
55 mimetypes << "image/svg" << "image/png" << "image/jpeg";
56 structure.setMimetypes("images", mimetypes);
57
58 structure.addDirectoryDefinition("scripts", "code/", i18n("Executable Scripts"));
59 mimetypes.clear();
60 mimetypes << "text/\*";
61 structure.setMimetypes("scripts", mimetypes);
62
63 structure.addFileDefinition("mainscript", "code/main.js", i18n("Main Script File"));
64 structure.setRequired("mainscript", true);
65 @endcode
66 * One may also choose to create a subclass of PackageStructure and include the setup
67 * in the constructor.
68 *
69 * Either way, PackageStructure creates a sort of "contract" between the packager and
70 * the application which is also self-documenting.
71 **/
72class PLASMA_EXPORT PackageStructure : public QObject, public QSharedData
73{
74 Q_OBJECT
75
76public:
77 typedef KSharedPtr<PackageStructure> Ptr;
78
79 /**
80 * Default constructor for a package structure definition
81 *
82 * @param type the type of package. This is often application specific.
83 **/
84 explicit PackageStructure(QObject *parent = 0,
85 const QString &type = i18nc("A non-functional package", "Invalid"));
86
87 /**
88 * Destructor
89 **/
90 virtual ~PackageStructure();
91
92 /**
93 * Assignment operator
94 **/
95 PackageStructure &operator=(const PackageStructure &rhs);
96
97 /**
98 * Loads a package format by name.
99 *
100 * @param format If not empty, attempts to locate the given format, either
101 * from built-ins or via plugins.
102 * @return a package that matches the format, if available. The caller
103 * is responsible for deleting the object.
104 */
105 static PackageStructure::Ptr load(const QString &packageFormat);
106
107 /**
108 * Type of package this structure describes
109 **/
110 QString type() const;
111
112 /**
113 * The directories defined for this package
114 **/
115 QList<const char*> directories() const;
116
117 /**
118 * The required directories defined for this package
119 **/
120 QList<const char*> requiredDirectories() const;
121
122 /**
123 * The individual files, by key, that are defined for this package
124 **/
125 QList<const char*> files() const;
126
127 /**
128 * The individual required files, by key, that are defined for this package
129 **/
130 QList<const char*> requiredFiles() const;
131
132 /**
133 * Adds a directory to the structure of the package. It is added as
134 * a not-required element with no associated mimetypes.
135 *
136 * Starting in 4.6, if an entry with the given key
137 * already exists, the path is added to it as a search alternative.
138 *
139 * @param key used as an internal label for this directory
140 * @param path the path within the package for this directory
141 * @param name the user visible (translated) name for the directory
142 **/
143 void addDirectoryDefinition(const char *key, const QString &path, const QString &name);
144
145 /**
146 * Adds a file to the structure of the package. It is added as
147 * a not-required element with no associated mimetypes.
148 *
149 * Starting in 4.6, if an entry with the given key
150 * already exists, the path is added to it as a search alternative.
151 *
152 * @param key used as an internal label for this file
153 * @param path the path within the package for this file
154 * @param name the user visible (translated) name for the file
155 **/
156 void addFileDefinition(const char *key, const QString &path, const QString &name);
157
158 /**
159 * Removes a definition from the structure of the package.
160 * @since 4.6
161 * @param key the internal label of the file or directory to remove
162 */
163 void removeDefinition(const char *key);
164
165 /**
166 * @return path relative to the package root for the given entry
167 * @deprecatd use searchPaths instead
168 **/
169 QString path(const char *key) const;
170
171 /**
172 * @return a list of paths relative to the package root for the given entry.
173 * They are orted by importance: when searching for a file the paths
174 * will be searched in order
175 * @since 4.6
176 **/
177 QStringList searchPath(const char *key) const;
178
179 /**
180 * Get the list of files of a given type.
181 *
182 * @param key the type of file to look for
183 * @return list of files by name
184 * @since 4.3
185 */
186 QStringList entryList(const char *key);
187
188 /**
189 * @return user visible name for the given entry
190 **/
191 QString name(const char *key) const;
192
193 /**
194 * Sets whether or not a given part of the structure is required or not.
195 * The path must already have been added using addDirectoryDefinition
196 * or addFileDefinition.
197 *
198 * @param key the entry within the package
199 * @param required true if this entry is required, false if not
200 */
201 void setRequired(const char *key, bool required);
202
203 /**
204 * @return true if the item at path exists and is required
205 **/
206 bool isRequired(const char *key) const;
207
208 /**
209 * Defines the default mimetypes for any definitions that do not have
210 * associated mimetypes. Handy for packages with only one or predominantly
211 * one file type.
212 *
213 * @param mimetypes a list of mimetypes
214 **/
215 void setDefaultMimetypes(QStringList mimetypes);
216
217 /**
218 * Define mimetypes for a given part of the structure
219 * The path must already have been added using addDirectoryDefinition
220 * or addFileDefinition.
221 *
222 * @param key the entry within the package
223 * @param mimetypes a list of mimetypes
224 **/
225 void setMimetypes(const char *key, QStringList mimetypes);
226
227 /**
228 * @return the mimetypes associated with the path, if any
229 **/
230 QStringList mimetypes(const char *key) const;
231
232 /**
233 * Sets the path to the package. Useful for package formats
234 * which do not have well defined contents prior to installation.
235 */
236 void setPath(const QString &path);
237
238 /**
239 * @return the path to the package, or QString() if none
240 */
241 QString path() const;
242
243 /**
244 * Read a package structure from a config file.
245 */
246 void read(const KConfigBase *config);
247
248 /**
249 * Write this package structure to a config file.
250 */
251 void write(KConfigBase *config) const;
252
253 /**
254 * Installs a package matching this package structure. By default installs a
255 * native Plasma::Package.
256 *
257 * @param archivePath path to the package archive file
258 * @param packageRoot path to the directory where the package should be
259 * installed to
260 * @return true on successful installation, false otherwise
261 **/
262 virtual bool installPackage(const QString &archivePath, const QString &packageRoot);
263
264 /**
265 * Uninstalls a package matching this package structure.
266 *
267 * @param packageName the name of the package to remove
268 * @param packageRoot path to the directory where the package should be installed to
269 * @return true on successful removal of the package, false otherwise
270 */
271 virtual bool uninstallPackage(const QString &packageName, const QString &packageRoot);
272
273 /**
274 * When called, the package plugin should display a window to the user
275 * that they can use to browser, select and then install widgets supported by
276 * this package plugin with.
277 *
278 * The user interface may be an in-process dialog or an out-of-process application.
279 *
280 * When the process is complete, the newWidgetBrowserFinished() signal must be
281 * emitted.
282 *
283 * @param parent the parent widget to use for the widget
284 */
285 virtual void createNewWidgetBrowser(QWidget *parent = 0);
286
287 /**
288 * @return the prefix inserted between the base path and content entries
289 * @deprecated use contentsPrefixPaths() instead.
290 */
291 KDE_DEPRECATED QString contentsPrefix() const;
292
293 /**
294 * @return the prefix paths inserted between the base path and content entries, in order of priority.
295 * When searching for a file, all paths will be tried in order.
296 * @since 4.6
297 */
298 QStringList contentsPrefixPaths() const;
299
300 /**
301 * @return preferred package root. This defaults to plasma/plasmoids/
302 */
303 QString defaultPackageRoot() const;
304
305 /**
306 * @return service prefix used in desktop files. This defaults to plasma-applet-
307 */
308 QString servicePrefix() const;
309
310 /**
311 * Sets service prefix.
312 */
313 void setServicePrefix(const QString &servicePrefix);
314
315 /**
316 * @return the package metadata object.
317 */
318 virtual PackageMetadata metadata();
319
320 /**
321 * @return true if paths/symlinks outside the package itself should be followed.
322 * By default this is set to false for security reasons.
323 */
324 bool allowExternalPaths() const;
325
326Q_SIGNALS:
327 /**
328 * Emitted when the new widget browser process completes.
329 */
330 void newWidgetBrowserFinished();
331
332protected:
333 /**
334 * Sets whether or not external paths/symlinks can be followed by a package
335 * @param allow true if paths/symlinks outside of the package should be followed,
336 * false if they should be rejected.
337 */
338 void setAllowExternalPaths(bool allow);
339
340 /**
341 * Sets the prefix that all the contents in this package should
342 * appear under. This defaults to "contents/" and is added automatically
343 * between the base path and the entries as defined by the package
344 * structure
345 *
346 * @param prefix the directory prefix to use
347 * @deprecated use setContentsPrefixPaths() instead.
348 */
349 KDE_DEPRECATED void setContentsPrefix(const QString &prefix);
350
351 /**
352 * Sets the prefixes that all the contents in this package should
353 * appear under. This defaults to "contents/" and is added automatically
354 * between the base path and the entries as defined by the package
355 * structure. Multiple entries can be added.
356 * In this case each file request will be searched in all prefixes in order,
357 * and the first found will be returned.
358 *
359 * @param prefix paths the directory prefix to use
360 * @since 4.6
361 */
362 void setContentsPrefixPaths(const QStringList &prefixPaths);
363
364 /**
365 * Sets preferred package root.
366 */
367 void setDefaultPackageRoot(const QString &packageRoot);
368
369 /**
370 * Called whenever the path changes so that subclasses may take
371 * package specific actions.
372 */
373 virtual void pathChanged();
374
375private:
376 PackageStructurePrivate * const d;
377};
378
379/**
380 * Register an applet when it is contained in a loadable module
381 */
382#define K_EXPORT_PLASMA_PACKAGESTRUCTURE(libname, classname) \
383K_PLUGIN_FACTORY(factory, registerPlugin<classname>();) \
384K_EXPORT_PLUGIN(factory("plasma_packagestructure_" #libname)) \
385K_EXPORT_PLUGIN_VERSION(PLASMA_VERSION)
386
387} // Plasma namespace
388#endif
389