KNewStuff

quickengine.cpp
1 /*
2  SPDX-FileCopyrightText: 2016 Dan Leinir Turthra Jensen <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 
7 #include "quickengine.h"
8 #include "quicksettings.h"
9 
10 #if KNEWSTUFFQUICK_BUILD_DEPRECATED_SINCE(5, 81)
11 #include <KAuthorized>
12 #endif
13 #include <KLocalizedString>
14 
15 #include "categoriesmodel.h"
16 #include "quickquestionlistener.h"
17 #include "searchpresetmodel.h"
18 
19 #include "engine.h"
20 
21 class EnginePrivate
22 {
23 public:
24  EnginePrivate()
25  : engine(nullptr)
26  , categoriesModel(nullptr)
27  , searchPresetModel(nullptr)
28  {
29  }
30  KNSCore::Engine *engine;
31  bool isLoading{false};
32  bool isValid{false};
33  CategoriesModel *categoriesModel;
34  SearchPresetModel *searchPresetModel;
35  QString configFile;
36 
37 #if KNEWSTUFF_BUILD_DEPRECATED_SINCE(5, 82)
38  KNSCore::EntryInternal::List changedEntries;
39  static KNSCore::EntryWrapper *getChangedEntry(QQmlListProperty<KNSCore::EntryWrapper> *property, int i)
40  {
41  KNSCore::EntryWrapper *entry{nullptr};
42  if (property) {
43  auto d = static_cast<EnginePrivate *>(property->data);
44  if (d) {
45  if (i >= 0 && i < d->changedEntries.count()) {
46  // Lifetime management for these objects should be done by the consumer,
47  // but are also parented for auto-delete on application shutdown
48  entry = new KNSCore::EntryWrapper(d->changedEntries[i], property->object);
49  }
50  }
51  }
52  return entry;
53  }
54  static int getChangedEntriesCount(QQmlListProperty<KNSCore::EntryWrapper> *property)
55  {
56  int count{0};
57  if (property) {
58  auto d = static_cast<EnginePrivate *>(property->data);
59  if (d) {
60  count = d->changedEntries.count();
61  }
62  }
63  return count;
64  }
65 #endif
66 };
67 
68 Engine::Engine(QObject *parent)
69  : QObject(parent)
70  , d(new EnginePrivate)
71 {
72 }
73 
74 Engine::~Engine() = default;
75 
76 #if KNEWSTUFFQUICK_BUILD_DEPRECATED_SINCE(5, 81)
77 bool Engine::allowedByKiosk() const
78 {
79  return KAuthorized::authorize(KAuthorized::GHNS);
80 }
81 #endif
82 
83 QString Engine::configFile() const
84 {
85  return d->configFile;
86 }
87 
88 void Engine::setConfigFile(const QString &newFile)
89 {
90  if (d->configFile != newFile) {
91  d->isLoading = true;
92  Q_EMIT isLoadingChanged();
93  d->configFile = newFile;
94  Q_EMIT configFileChanged();
95 
96  if (KNewStuffQuick::Settings::instance()->allowedByKiosk()) {
97  if (!d->engine) {
98  d->engine = new KNSCore::Engine(this);
99  connect(d->engine, &KNSCore::Engine::signalProvidersLoaded, this, [=]() {
100  d->isLoading = false;
101  Q_EMIT isLoadingChanged();
102  });
103  connect(d->engine, &KNSCore::Engine::signalMessage, this, &Engine::message);
104  connect(d->engine, &KNSCore::Engine::busyStateChanged, this, [this]() {
105  if (!d->engine->busyState()) {
106  idleMessage(QString());
107  } else {
108  busyMessage(d->engine->busyMessage());
109  }
110  });
111  connect(d->engine,
113  this,
114  [=](const KNSCore::ErrorCode &theErrorCode, const QString &message, const QVariant &metadata) {
115  Q_EMIT errorCode(static_cast<ErrorCode>(theErrorCode), message, metadata);
116  if (theErrorCode == KNSCore::ProviderError) {
117  // This means loading the providers file failed entirely and we cannot complete the
118  // initialisation. It also means the engine is done loading, but that nothing will
119  // work, and we need to inform the user of this.
120  d->isLoading = false;
121  Q_EMIT isLoadingChanged();
122  }
124  });
125  connect(d->engine,
127  this,
129  KNSCore::EntryWrapper *wrappedEntry = new KNSCore::EntryWrapper(entry, this);
130  // Just forward the event but not do anything more
131  if (event != KNSCore::EntryInternal::StatusChangedEvent) {
132  Q_EMIT entryEvent(wrappedEntry, (EntryEvent)event);
133  return;
134  }
135 
136  // We do not want to emit the entries changed signal for intermediate changed
137  // this would cause the KCMs to reload their view unnecessarily, BUG: 431568
138  if (entry.status() == KNS3::Entry::Installing || entry.status() == KNS3::Entry::Updating) {
139  return;
140  }
141  Q_EMIT entryEvent(wrappedEntry, (EntryEvent)event);
142 #if KNEWSTUFF_BUILD_DEPRECATED_SINCE(5, 82)
143  if (d->changedEntries.contains(entry)) {
144  d->changedEntries.removeAll(entry);
145  }
146  d->changedEntries << entry;
147  Q_EMIT changedEntriesChanged();
148 #endif
149  });
150  Q_EMIT engineChanged();
151  KNewStuffQuick::QuickQuestionListener::instance();
152  d->categoriesModel = new CategoriesModel(this);
153  Q_EMIT categoriesChanged();
154  d->searchPresetModel = new SearchPresetModel(this);
155  Q_EMIT searchPresetModelChanged();
156  // And finally, let's just make sure we don't miss out the various things here getting changed
157  // In other words, when we're asked to reset the view, actually do that
158  connect(d->engine, &KNSCore::Engine::signalResetView, this, &Engine::categoriesFilterChanged);
159  connect(d->engine, &KNSCore::Engine::signalResetView, this, &Engine::filterChanged);
160  connect(d->engine, &KNSCore::Engine::signalResetView, this, &Engine::sortOrderChanged);
161  connect(d->engine, &KNSCore::Engine::signalResetView, this, &Engine::searchTermChanged);
162  Q_EMIT categoriesFilterChanged();
163  Q_EMIT filterChanged();
164  Q_EMIT sortOrderChanged();
165  Q_EMIT searchTermChanged();
166  }
167  d->isValid = d->engine->init(d->configFile);
168  Q_EMIT engineInitialized();
169  } else {
170  // This is not an error message in the proper sense, and the message is not intended to look like an error (as there is really
171  // nothing the user can do to fix it, and we just tell them so they're not wondering what's wrong)
172  Q_EMIT message(
173  i18nc("An informational message which is shown to inform the user they are not authorized to use GetHotNewStuff functionality",
174  "You are not authorized to Get Hot New Stuff. If you think this is in error, please contact the person in charge of your permissions."));
175  }
176  }
177 }
178 
179 QObject *Engine::engine() const
180 {
181  return d->engine;
182 }
183 
184 bool Engine::isLoading() const
185 {
186  return d->isLoading;
187 }
188 
189 bool Engine::hasAdoptionCommand() const
190 {
191  if (d->engine) {
192  return d->engine->hasAdoptionCommand();
193  }
194  return false;
195 }
196 
197 QString Engine::name() const
198 {
199  if (d->engine) {
200  return d->engine->name();
201  }
202  return QString{};
203 }
204 
206 {
207  return d->categoriesModel;
208 }
209 
211 {
212  if (d->engine) {
213  return d->engine->categoriesFilter();
214  }
215  return QStringList{};
216 }
217 
218 void Engine::setCategoriesFilter(const QStringList &newCategoriesFilter)
219 {
220  if (d->engine) {
221  // This ensures that if we somehow end up with any empty entries (such as the default
222  // option in the categories dropdowns), our list will remain empty.
223  QStringList filter{newCategoriesFilter};
224  filter.removeAll({});
225  if (d->engine->categoriesFilter() != filter) {
226  d->engine->setCategoriesFilter(filter);
227  Q_EMIT categoriesFilterChanged();
228  }
229  }
230 }
231 
232 void Engine::resetCategoriesFilter()
233 {
234  if (d->engine) {
235  d->engine->setCategoriesFilter(d->engine->categories());
236  }
237 }
238 
239 int Engine::filter() const
240 {
241  if (d->engine) {
242  return d->engine->filter();
243  }
244  return 0;
245 }
246 
247 void Engine::setFilter(int newFilter)
248 {
249  if (d->engine && d->engine->filter() != newFilter) {
250  d->engine->setFilter(static_cast<KNSCore::Provider::Filter>(newFilter));
251  Q_EMIT filterChanged();
252  }
253 }
254 
255 int Engine::sortOrder() const
256 {
257  if (d->engine) {
258  return d->engine->sortMode();
259  }
260  return 0;
261 }
262 
263 void Engine::setSortOrder(int newSortOrder)
264 {
265  if (d->engine && d->engine->sortMode() != newSortOrder) {
266  d->engine->setSortMode(static_cast<KNSCore::Provider::SortMode>(newSortOrder));
267  Q_EMIT sortOrderChanged();
268  }
269 }
270 
272 {
273  if (d->engine) {
274  return d->engine->searchTerm();
275  }
276  return QString{};
277 }
278 
279 void Engine::setSearchTerm(const QString &newSearchTerm)
280 {
281  if (d->engine && d->isValid && d->engine->searchTerm() != newSearchTerm) {
282  d->engine->setSearchTerm(newSearchTerm);
283  Q_EMIT searchTermChanged();
284  }
285 }
286 
287 QObject *Engine::searchPresetModel() const
288 {
289  return d->searchPresetModel;
290 }
291 
292 void Engine::resetSearchTerm()
293 {
295 }
296 
297 #if KNEWSTUFF_BUILD_DEPRECATED_SINCE(5, 82)
298 QQmlListProperty<KNSCore::EntryWrapper> Engine::changedEntries()
299 {
300  return QQmlListProperty<KNSCore::EntryWrapper>(this, d.get(), &EnginePrivate::getChangedEntriesCount, &EnginePrivate::getChangedEntry);
301 }
302 
303 int Engine::changedEntriesCount() const
304 {
305  return d->changedEntries.count();
306 }
307 
308 void Engine::resetChangedEntries()
309 {
310  if (!d->changedEntries.isEmpty()) {
311  d->changedEntries.clear();
312  Q_EMIT changedEntriesChanged();
313  }
314 }
315 #endif
316 
317 bool Engine::isValid()
318 {
319  return d->isValid;
320 }
A model which shows the categories found in an Engine.
bool hasAdoptionCommand() const
Whether or not an adoption command exists for this engine.
Definition: engine.cpp:1052
~Engine() override
Destructor.
Definition: engine.cpp:189
void signalEntryEvent(const EntryInternal &entry, EntryInternal::EntryEvent event)
This is fired for any event related directly to a single EntryInternal instance.
KNewStuff data entry container.
Definition: entryinternal.h:52
KNewStuff engine.
Definition: engine.h:60
Q_EMITQ_EMIT
int count(const T &value) const const
QString searchTerm() const
The search term for the current search (empty if none is set)
Definition: engine.cpp:660
The SearchPresetModel class.
QString name() const
The name as defined by the knsrc file.
Definition: engine.cpp:322
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
bool isLoading
Whether or not the engine is performing its initial loading operations.
Definition: quickengine.h:40
ErrorCode
An enumeration of specific error conditions which might occur and which users of KNewStuff would want...
Definition: errorcode.h:24
void setSearchTerm(const QString &searchString)
Sets a string search term.
Definition: engine.cpp:648
KCALUTILS_EXPORT QString errorMessage(const KCalendarCore::Exception &exception)
Wraps a KNSCore::EntryInternal in a QObject for passing through Qt Quick.
Definition: entrywrapper.h:38
virtual bool event(QEvent *e)
void setCategoriesFilter(const QStringList &categories)
Set the categories that will be included in searches.
Definition: engine.cpp:579
Q_SIGNAL void busyStateChanged()
Signal gets emitted when the busy state changes.
KCONFIGCORE_EXPORT bool authorize(const QString &action)
void setFilter(Provider::Filter filter)
Set a filter for results (defaults to none), which will allow you to show only installed entries,...
Definition: engine.cpp:599
Provider::Filter filter() const
The result filter set on the current request.
Definition: engine.cpp:608
void signalMessage(const QString &message)
Indicates a message to be added to the ui's log, or sent to a messagebox.
bool isValid(QStringView ifopt)
void signalErrorCode(const KNSCore::ErrorCode &errorCode, const QString &message, const QVariant &metadata)
Fires in the case of any critical or serious errors, such as network or API problems.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QStringList categories() const
The list of the server-side names of the categories handled by this engine instance.
Definition: engine.cpp:327
QStringList categoriesFilter() const
The list of categories searches will actually show results from.
Definition: engine.cpp:332
QString message
KNS3::Entry::Status status() const
Retrieves the entry's status.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 6 2023 04:18:17 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.