libplasma
package.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "package.h"
00022
00023 #include <QDir>
00024 #include <QFile>
00025
00026 #include <KArchiveDirectory>
00027 #include <KArchiveEntry>
00028 #include <KComponentData>
00029 #include <KDesktopFile>
00030 #include <KIO/CopyJob>
00031 #include <KIO/FileCopyJob>
00032 #include <KIO/Job>
00033 #include <KPluginInfo>
00034 #include <KStandardDirs>
00035 #include <KTempDir>
00036 #include <KTemporaryFile>
00037 #include <KZip>
00038 #include <KDebug>
00039
00040 #include "packagemetadata.h"
00041
00042 namespace Plasma
00043 {
00044
00045 class PackagePrivate
00046 {
00047 public:
00048 PackagePrivate(const PackageStructure::Ptr st, const QString& p)
00049 : structure(st),
00050 basePath(p),
00051 valid(QFile::exists(basePath)),
00052 metadata(0)
00053 {
00054 if (valid && basePath[basePath.length() - 1] != '/') {
00055 basePath.append('/');
00056 }
00057 }
00058
00059 ~PackagePrivate()
00060 {
00061 delete metadata;
00062 }
00063
00064 PackageStructure::Ptr structure;
00065 QString basePath;
00066 bool valid;
00067 PackageMetadata *metadata;
00068 };
00069
00070 Package::Package(const QString& packageRoot, const QString& package, PackageStructure::Ptr structure)
00071 : d(new PackagePrivate(structure, packageRoot + '/' + package))
00072 {
00073 structure->setPath(d->basePath);
00074 }
00075
00076 Package::Package(const QString &packagePath, PackageStructure::Ptr structure)
00077 : d(new PackagePrivate(structure, packagePath))
00078 {
00079 structure->setPath(d->basePath);
00080 }
00081
00082 Package::~Package()
00083 {
00084 delete d;
00085 }
00086
00087 bool Package::isValid() const
00088 {
00089 if (!d->valid) {
00090 return false;
00091 }
00092
00093 foreach (const char *dir, d->structure->requiredDirectories()) {
00094 if (!QFile::exists(d->basePath + d->structure->contentsPrefix() + d->structure->path(dir))) {
00095 kWarning(505) << "Could not find required directory" << dir;
00096 d->valid = false;
00097 return false;
00098 }
00099 }
00100
00101 foreach (const char *file, d->structure->requiredFiles()) {
00102 if (!QFile::exists(d->basePath + d->structure->contentsPrefix() + d->structure->path(file))) {
00103 kWarning(505) << "Could not find required file" << file << ", look in"
00104 << d->basePath + d->structure->contentsPrefix() + d->structure->path(file) << endl;
00105 d->valid = false;
00106 return false;
00107 }
00108 }
00109
00110 return true;
00111 }
00112
00113 QString Package::filePath(const char* fileType, const QString& filename) const
00114 {
00115 if (!d->valid) {
00116 kDebug() << "package is not valid";
00117 return QString();
00118 }
00119
00120 QString path = d->structure->path(fileType);
00121
00122 if (path.isEmpty()) {
00123 kDebug() << "no matching path came of it";
00124 return QString();
00125 }
00126
00127 path.prepend(d->basePath + d->structure->contentsPrefix());
00128
00129 if (!filename.isEmpty()) {
00130 path.append("/").append(filename);
00131 }
00132
00133 if (QFile::exists(path)) {
00134 return path;
00135 }
00136
00137 kDebug() << path << "does not exist";
00138 return QString();
00139 }
00140
00141 QString Package::filePath(const char* fileType) const
00142 {
00143 return filePath(fileType, QString());
00144 }
00145
00146 QStringList Package::entryList(const char* fileType) const
00147 {
00148 if (!d->valid) {
00149 return QStringList();
00150 }
00151
00152 QString path = d->structure->path(fileType);
00153 if (path.isEmpty()) {
00154 return QStringList();
00155 }
00156
00157 QDir dir(d->basePath + d->structure->contentsPrefix() + path);
00158
00159 if (!dir.exists()) {
00160 return QStringList();
00161 }
00162
00163 return dir.entryList(QDir::Files | QDir::Readable);
00164 }
00165
00166 const PackageMetadata* Package::metadata() const
00167 {
00168
00169 if (!d->metadata) {
00170 d->metadata = new PackageMetadata(d->basePath + "metadata.desktop");
00171 }
00172 return d->metadata;
00173 }
00174
00175 const QString Package::path() const
00176 {
00177 return d->basePath;
00178 }
00179
00180 const PackageStructure::Ptr Package::structure() const
00181 {
00182 return d->structure;
00183 }
00184
00185
00186
00187 QStringList Package::listInstalled(const QString& packageRoot)
00188 {
00189 QDir dir(packageRoot);
00190
00191 if (!dir.exists()) {
00192 return QStringList();
00193 }
00194
00195 QStringList packages;
00196
00197 foreach (const QString& sdir, dir.entryList(QDir::AllDirs | QDir::Readable)) {
00198 QString metadata = packageRoot + '/' + sdir + "/metadata.desktop";
00199 if (QFile::exists(metadata)) {
00200 PackageMetadata m(metadata);
00201 packages << m.pluginName();
00202 }
00203 }
00204
00205 return packages;
00206 }
00207
00208 bool Package::installPackage(const QString& package,
00209 const QString& packageRoot)
00210 {
00211
00212 QDir root(packageRoot);
00213
00214 if (!root.exists()) {
00215 KStandardDirs::makeDir(packageRoot);
00216 if (!root.exists()) {
00217 kWarning() << "Could not create package root directory:" << packageRoot;
00218 return false;
00219 }
00220 }
00221
00222 QFileInfo fileInfo(package);
00223 if (!fileInfo.exists()) {
00224 kWarning() << "No such file:" << package;
00225 return false;
00226 }
00227
00228 QString path;
00229 KTempDir tempdir;
00230 bool archivedPackage = false;
00231
00232 if (fileInfo.isDir()) {
00233
00234 path = package;
00235
00236
00237 if (path[path.size() - 1] != '/') {
00238 path.append('/');
00239 }
00240 } else {
00241 KZip archive(package);
00242 if (!archive.open(QIODevice::ReadOnly)) {
00243 kWarning() << "Could not open package file:" << package;
00244 return false;
00245 }
00246
00247 archivedPackage = true;
00248 const KArchiveDirectory* source = archive.directory();
00249 const KArchiveEntry* metadata = source->entry("metadata.desktop");
00250
00251 if (!metadata) {
00252 kWarning() << "No metadata file in package" << package;
00253 return false;
00254 }
00255
00256 path = tempdir.name();
00257 source->copyTo(path);
00258 }
00259
00260 QString metadataPath = path + "metadata.desktop";
00261 if (!QFile::exists(metadataPath)) {
00262 kWarning() << "No metadata file in package" << package;
00263 return false;
00264 }
00265
00266 PackageMetadata meta(metadataPath);
00267 QString targetName = meta.pluginName();
00268
00269 if (targetName.isEmpty()) {
00270 kWarning() << "Package plugin name not specified";
00271 return false;
00272 }
00273
00274 targetName = packageRoot + '/' + targetName;
00275 if (QFile::exists(targetName)) {
00276 kWarning() << targetName << "already exists";
00277 return false;
00278 }
00279
00280 if (archivedPackage) {
00281
00282 KIO::CopyJob *job = KIO::move(KUrl(path), KUrl(targetName), KIO::HideProgressInfo);
00283 if (!job->exec()) {
00284 kWarning() << "Could not move package to destination:" << targetName << " : " << job->errorString();
00285 return false;
00286 }
00287 } else {
00288
00289
00290 KIO::CopyJob *job = KIO::copy(KUrl(path), KUrl(targetName), KIO::HideProgressInfo);
00291 if (!job->exec()) {
00292 kWarning() << "Could not copy package to destination:" << targetName << " : " << job->errorString();
00293 return false;
00294 }
00295 }
00296
00297 if (archivedPackage) {
00298
00299 tempdir.setAutoRemove(false);
00300 }
00301
00302
00303 QString metaPath = targetName + "/metadata.desktop";
00304 KDesktopFile df(metaPath);
00305 KConfigGroup cg = df.desktopGroup();
00306
00307
00308
00309
00310
00311
00312
00313
00314 QString serviceName;
00315 if (KGlobal::hasMainComponent()) {
00316 serviceName = KGlobal::mainComponent().componentName();
00317 }
00318 serviceName.append("_plasma_applet_" + meta.pluginName());
00319
00320 QString service = KStandardDirs::locateLocal("services", serviceName + ".desktop");
00321 KIO::FileCopyJob *job = KIO::file_copy(metaPath, service, -1, KIO::HideProgressInfo);
00322 if (job->exec()) {
00323
00324
00325 QString iconPath = targetName + '/' + cg.readEntry("Icon");
00326 QFile icon(iconPath);
00327 if (icon.exists()) {
00328 cg.writeEntry("Icon", iconPath);
00329 }
00330 }
00331
00332 return true;
00333 }
00334
00335 bool Package::registerPackage(const PackageMetadata &data, const QString &iconPath)
00336 {
00337 QString serviceName("plasma-applet-" + data.pluginName());
00338 QString service = KStandardDirs::locateLocal("services", serviceName + ".desktop");
00339
00340 if (data.pluginName().isEmpty()) {
00341 return false;
00342 }
00343
00344 data.write(service);
00345
00346 KDesktopFile config(service);
00347 KConfigGroup cg = config.desktopGroup();
00348 const QString type = data.type().isEmpty() ? "Service" : data.type();
00349 cg.writeEntry("Type", type);
00350 const QString serviceTypes = data.serviceType().isNull() ? "Plasma/Applet,Plasma/Containment" : data.serviceType();
00351 cg.writeEntry("X-KDE-ServiceTypes", serviceTypes);
00352 cg.writeEntry("X-KDE-PluginInfo-EnabledByDefault", true);
00353
00354 QFile icon(iconPath);
00355 if (icon.exists()) {
00356
00357 QString installedIcon("plasma_applet_" + data.pluginName() +
00358 iconPath.right(iconPath.length() - iconPath.lastIndexOf("/")));
00359 cg.writeEntry("Icon", installedIcon);
00360 installedIcon = KStandardDirs::locateLocal("icon", installedIcon);
00361 KIO::FileCopyJob *job = KIO::file_copy(iconPath, installedIcon, -1, KIO::HideProgressInfo);
00362 job->exec();
00363 }
00364
00365 return true;
00366 }
00367
00368 bool Package::createPackage(const PackageMetadata &metadata,
00369 const QString &source,
00370 const QString &destination,
00371 const QString &icon)
00372 {
00373 if (!metadata.isValid()) {
00374 kWarning(550) << "Metadata file is not complete";
00375 return false;
00376 }
00377
00378
00379 KTemporaryFile metadataFile;
00380 if (!metadataFile.open()) {
00381 return false;
00382 }
00383 metadata.write(metadataFile.fileName());
00384
00385
00386 KZip creation(destination);
00387 creation.setCompression(KZip::NoCompression);
00388 if (!creation.open(QIODevice::WriteOnly)) {
00389 return false;
00390 }
00391
00392 creation.addLocalFile(metadataFile.fileName(), "metadata.desktop");
00393 creation.addLocalDirectory(source, "contents");
00394 creation.close();
00395 return true;
00396 }
00397
00398
00399 }