KNewStuff

kpackagejob.cpp
1 /*
2  Copyright (C) 2020 Dan Leinir Turthra Jensen <[email protected]>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License as published by the Free Software Foundation; either
7  version 2.1 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  Lesser General Public License for more details.
13 
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 #include "kpackagejob.h"
19 
20 #include <knewstuffcore_debug.h>
21 
22 #include <KLocalizedString>
23 
24 #include <KPackage/PackageStructure>
25 #include <KPackage/Package>
26 #include <KPackage/PackageLoader>
27 
28 #include <QCoreApplication>
29 #include <QRunnable>
30 #include <QStandardPaths>
31 #include <QThreadPool>
32 #include <QTimer>
33 
34 using namespace KNSCore;
35 
36 enum Operation {
37  UnknownOperation,
38  InstallOperation,
39  UpdateOperation,
40  UninstallOperation
41 };
42 class KPackageTask;
43 class KPackageJob::Private {
44 public:
45  Private() {}
46 
47  QString package;
48  QString packageRoot;
49  QString serviceType;
50  Operation operation{UnknownOperation};
51 
52  KPackageTask* runnable{nullptr};
53 };
54 
55 class KPackageTask : public QObject, public QRunnable
56 {
57  Q_OBJECT
58 public:
59  QString package;
60  QString packageRoot;
61  QString serviceType;
62  Operation operation{UnknownOperation};
63  void run() override
64  {
65  qCDebug(KNEWSTUFFCORE) << "Attempting to perform an installation operation of type" << operation << "on the package" << package << "of type" << serviceType << "in the package root" << packageRoot;
67  if (structure) {
68  qCDebug(KNEWSTUFFCORE) << "Service type understood";
69  KPackage::Package installer = KPackage::Package(structure);
70  if (installer.hasValidStructure()) {
71  qCDebug(KNEWSTUFFCORE) << "Installer successfully created and has a valid structure";
72  KJob *job{nullptr};
73  switch(operation)
74  {
75  case InstallOperation:
76  job = installer.install(package, packageRoot);
77  break;
78  case UpdateOperation:
79  job = installer.update(package, packageRoot);
80  break;
81  case UninstallOperation:
82  job = installer.uninstall(package, packageRoot);
83  break;
84  case UnknownOperation:
85  default:
86  // This should really not be happening, can't create one of these without going through one
87  // of the functions below, so how'd you get it in this state?
88  break;
89  };
90  if (job) {
91  qCDebug(KNEWSTUFFCORE) << "Created job, now let's wait for it to do its thing...";
92  QEventLoop loop;
93  connect(job, &KJob::result, this, [this,job,&loop](){
94  emit result(job);
95  loop.exit(0);
96  });
97  loop.exec();
98  } else {
99  qCWarning(KNEWSTUFFCORE) << "Failed to create a job to perform our task";
100  emit error(3, i18n("Failed to create a job for the package management task. This is usually because the package is invalid. We attempted to operate on the package %1", package));
101  }
102  } else {
103  qCWarning(KNEWSTUFFCORE) << "Failed to create package installer";
104  emit error(2, i18n("Could not create a package installer for the service type %1: The installer does not have a valid structure", serviceType));
105  }
106  } else {
107  qCWarning(KNEWSTUFFCORE) << "Service type was not understood";
108  emit error(1, i18n("The service type %1 was not understood by the KPackage installer", serviceType));
109  }
110  }
111  Q_SIGNAL void result(KJob* job);
112  Q_SIGNAL void error(int errorCode, const QString& errorText);
113 };
114 
115 KPackageJob::KPackageJob(QObject* parent)
116  : KJob(parent)
117  , d(new Private)
118 {
119 }
120 
121 KPackageJob::~KPackageJob()
122 {
123  delete d;
124 }
125 
126 void KPackageJob::start()
127 {
128  if (d->runnable) {
129  // refuse to start the task more than once
130  return;
131  }
132  d->runnable = new KPackageTask();
133  d->runnable->package = d->package;
134  d->runnable->packageRoot = d->packageRoot;
135  d->runnable->serviceType = d->serviceType;
136  d->runnable->operation = d->operation;
137  connect(d->runnable, &KPackageTask::error, this, [this](int errorCode, const QString& errorText){
138  setError(errorCode);
139  setErrorText(errorText);
141  connect(d->runnable, &KPackageTask::result, this, [this](KJob* job){
142  setError(job->error());
143  setErrorText(job->errorText());
144  emitResult();
146  QThreadPool::globalInstance()->start(d->runnable);
147 }
148 
149 KNSCore::KPackageJob * KNSCore::KPackageJob::install(const QString &sourcePackage, const QString &packageRoot, const QString &serviceType)
150 {
151  KPackageJob* job = new KPackageJob();
152  job->d->package = sourcePackage;
153  job->d->packageRoot = packageRoot;
154  job->d->serviceType = serviceType;
155  job->d->operation = InstallOperation;
156  QTimer::singleShot(0, job, &KPackageJob::start);
157  return job;
158 }
159 
160 KPackageJob * KPackageJob::update(const QString &sourcePackage, const QString &packageRoot, const QString &serviceType)
161 {
162  KPackageJob* job = new KPackageJob();
163  job->d->package = sourcePackage;
164  job->d->packageRoot = packageRoot;
165  job->d->serviceType = serviceType;
166  job->d->operation = UpdateOperation;
167  QTimer::singleShot(0, job, &KPackageJob::start);
168  return job;
169 }
170 
171 KPackageJob * KPackageJob::uninstall(const QString &packageName, const QString &packageRoot, const QString &serviceType)
172 {
173  KPackageJob* job = new KPackageJob();
174  job->d->package = packageName;
175  job->d->packageRoot = packageRoot;
176  job->d->serviceType = serviceType;
177  job->d->operation = UninstallOperation;
178  QTimer::singleShot(0, job, &KPackageJob::start);
179  return job;
180 }
181 
182 #include "kpackagejob.moc"
KJob * uninstall(const QString &packageName, const QString &packageRoot)
QThreadPool * globalInstance()
Contains the core functionality for handling interaction with NewStuff providers. ...
bool hasValidStructure() const
static PackageLoader * self()
A job for performing basic actions on KPackage packages asynchronously.
Definition: kpackagejob.h:34
int exec(QEventLoop::ProcessEventsFlags flags)
Q_OBJECTQ_OBJECT
void exit(int returnCode)
KPackage::PackageStructure * loadPackageStructure(const QString &packageFormat)
QString i18n(const char *text, const TYPE &arg...)
Q_SIGNALQ_SIGNAL
static KPackageJob * install(const QString &sourcePackage, const QString &packageRoot, const QString &serviceType)
Create a job for installing the given package into the package root, and treat it as the given servic...
KIOWIDGETS_EXPORT bool run(const QUrl &_url, bool _is_local)
KJob * install(const QString &sourcePackage, const QString &packageRoot=QString())
void result(KJob *job)
void start(QRunnable *runnable, int priority)
QueuedConnection
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
KJob * update(const QString &sourcePackage, const QString &packageRoot=QString())
QString errorText() const
int error() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sun Aug 9 2020 22:43:40 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.