7#include "quickengine.h"
10#include "imageloader_p.h"
11#include "installation_p.h"
12#include "knewstuffquick_debug.h"
13#include "quicksettings.h"
15#include <KLocalizedString>
19#include "categoriesmodel.h"
20#include "quickquestionlistener.h"
21#include "searchpresetmodel.h"
23#include "../core/enginebase_p.h"
24#include "../core/providerbase_p.h"
25#include "../core/providercore.h"
26#include "../core/providercore_p.h"
49 int numPictureJobs = 0;
50 int numInstallJobs = 0;
54 : KNSCore::EngineBase(parent)
55 , d(new EnginePrivate)
56 , dd(KNSCore::EngineBase::d.
get())
58 connect(
this, &KNSCore::EngineBase::providerAdded,
this, [
this](
auto core) {
59 connect(core->d->base, &KNSCore::ProviderBase::entriesLoaded,
this, [
this](
const auto &request,
const auto &entries) {
60 d->currentPage = qMax<int>(request.page(), d->currentPage);
61 qCDebug(KNEWSTUFFQUICK) <<
"loaded page " << request.page() <<
"current page" << d->currentPage <<
"count:" << entries.count();
63 if (request.filter() != KNSCore::Filter::Updates) {
64 dd->cache->insertRequest(request, entries);
66 Q_EMIT signalEntriesLoaded(entries);
71 connect(core->d->base, &KNSCore::ProviderBase::entryDetailsLoaded,
this, [
this](
const auto &entry) {
74 Q_EMIT signalEntryEvent(entry, KNSCore::Entry::DetailsLoadedEvent);
82 setBusy(BusyOperation::Initializing,
i18n(
"Loading data"));
84 KNewStuffQuick::QuickQuestionListener::instance();
90 d->searchTimer.setSingleShot(
true);
91 d->searchTimer.setInterval(1000);
93 connect(installation(), &KNSCore::Installation::signalInstallationFinished,
this, [
this]() {
97 connect(installation(), &KNSCore::Installation::signalInstallationFailed,
this, [
this](
const QString &message) {
99 Q_EMIT signalErrorCode(KNSCore::ErrorCode::InstallationError, message,
QVariant());
101 connect(
this, &EngineBase::signalProvidersLoaded,
this, &Engine::updateStatus);
102 connect(
this, &EngineBase::signalProvidersLoaded,
this, [
this]() {
104 d->currentRequest.filter(),
105 d->currentRequest.searchTerm(),
106 EngineBase::categories(),
107 d->currentRequest.page(),
108 d->currentRequest.pageSize());
114 [setBusy,
this](
const KNSCore::ErrorCode::ErrorCode &error,
const QString &message,
const QVariant &metadata) {
115 Q_EMIT errorCode(error, message, metadata);
116 if (error == KNSCore::ErrorCode::ProviderError || error == KNSCore::ErrorCode::ConfigFileError) {
124 if (error == KNSCore::ErrorCode::ConfigFileError) {
126 Q_EMIT errorCode(error, message, metadata);
133 Q_EMIT entryEvent(entry, event);
138 connect(
this, &Engine::signalResetView,
this, &Engine::categoriesFilterChanged);
139 connect(
this, &Engine::signalResetView,
this, &Engine::filterChanged);
140 connect(
this, &Engine::signalResetView,
this, &Engine::sortOrderChanged);
141 connect(
this, &Engine::signalResetView,
this, &Engine::searchTermChanged);
144bool Engine::init(
const QString &configfile)
146 const bool valid = EngineBase::init(configfile);
149 if (event == KNSCore::Entry::StatusChangedEvent) {
150 dd->cache->registerChangedEntry(entry);
153 const auto slotEntryChanged = [
this](
const KNSCore::Entry &entry) {
158 connect(dd->cache.get(), &KNSCore::Cache2::entryChanged,
this, slotEntryChanged);
162void Engine::updateStatus()
166 if (d->numPictureJobs > 0) {
168 busyMessage =
i18n(
"Loading data");
169 state |= BusyOperation::LoadingPreview;
171 if (d->numInstallJobs > 0) {
172 busyMessage =
i18n(
"Installing");
173 state |= BusyOperation::InstallingEntry;
175 if (d->numDataJobs > 0) {
176 busyMessage =
i18n(
"Loading data");
177 state |= BusyOperation::LoadingData;
179 d->busyMessage = busyMessage;
183bool Engine::needsLazyLoadSpinner()
185 return d->numDataJobs > 0 || d->numPictureJobs;
188Engine::~Engine() =
default;
190void Engine::setBusyState(BusyState state)
192 d->busyState = state;
199QString Engine::busyMessage()
const
201 return d->busyMessage;
204QString Engine::configFile()
const
206 return d->configFile;
209void Engine::setConfigFile(
const QString &newFile)
211 if (d->configFile != newFile) {
212 d->configFile = newFile;
213 Q_EMIT configFileChanged();
215 if (KNewStuffQuick::Settings::instance()->allowedByKiosk()) {
216 d->isValid = init(newFile);
217 Q_EMIT categoriesFilterChanged();
219 Q_EMIT sortOrderChanged();
220 Q_EMIT searchTermChanged();
225 KNSCore::ErrorCode::ConfigFileError,
226 i18nc(
"An informational message which is shown to inform the user they are not authorized to use GetHotNewStuff functionality",
227 "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."),
235 return d->categoriesModel;
240 return d->currentRequest.categories();
243void Engine::setCategoriesFilter(
const QStringList &newCategoriesFilter)
245 if (d->currentRequest.categories() != newCategoriesFilter) {
247 d->currentRequest.filter(),
248 d->currentRequest.searchTerm(),
250 d->currentRequest.page(),
251 d->currentRequest.pageSize());
253 Q_EMIT categoriesFilterChanged();
257#if KNEWSTUFFCORE_BUILD_DEPRECATED_SINCE(6, 9)
258KNSCore::Provider::Filter Engine::filter()
const
260 return [filter = filter2()] {
262 case KNSCore::Filter::None:
263 return KNSCore::Provider::None;
264 case KNSCore::Filter::Installed:
265 return KNSCore::Provider::Installed;
266 case KNSCore::Filter::Updates:
267 return KNSCore::Provider::Updates;
268 case KNSCore::Filter::ExactEntryId:
269 return KNSCore::Provider::ExactEntryId;
271 return KNSCore::Provider::None;
276#if KNEWSTUFFCORE_BUILD_DEPRECATED_SINCE(6, 9)
279 setFilter2([newFilter_] {
280 switch (newFilter_) {
281 case KNSCore::Provider::None:
282 return KNSCore::Filter::None;
283 case KNSCore::Provider::Installed:
284 return KNSCore::Filter::Installed;
285 case KNSCore::Provider::Updates:
286 return KNSCore::Filter::Updates;
287 case KNSCore::Provider::ExactEntryId:
288 return KNSCore::Filter::ExactEntryId;
290 return KNSCore::Filter::None;
295KNSCore::Filter Engine::filter2()
const
297 return d->currentRequest.filter();
300void Engine::setFilter2(KNSCore::Filter newFilter)
302 if (d->currentRequest.filter() != newFilter) {
305 d->currentRequest.searchTerm(),
306 d->currentRequest.categories(),
307 d->currentRequest.page(),
308 d->currentRequest.pageSize());
314#if KNEWSTUFFCORE_BUILD_DEPRECATED_SINCE(6, 9)
315KNSCore::Provider::SortMode Engine::sortOrder()
const
317 return [mode = sortOrder2()] {
319 case KNSCore::SortMode::Newest:
320 return KNSCore::Provider::Newest;
321 case KNSCore::SortMode::Alphabetical:
322 return KNSCore::Provider::Alphabetical;
323 case KNSCore::SortMode::Rating:
324 return KNSCore::Provider::Rating;
325 case KNSCore::SortMode::Downloads:
326 return KNSCore::Provider::Downloads;
328 return KNSCore::Provider::Rating;
333#if KNEWSTUFFCORE_BUILD_DEPRECATED_SINCE(6, 9)
336 setSortOrder2([mode_] {
338 case KNSCore::Provider::Newest:
339 return KNSCore::SortMode::Newest;
340 case KNSCore::Provider::Alphabetical:
341 return KNSCore::SortMode::Alphabetical;
342 case KNSCore::Provider::Rating:
343 return KNSCore::SortMode::Rating;
344 case KNSCore::Provider::Downloads:
345 return KNSCore::SortMode::Downloads;
347 return KNSCore::SortMode::Rating;
352KNSCore::SortMode Engine::sortOrder2()
const
354 return d->currentRequest.sortMode();
357void Engine::setSortOrder2(KNSCore::SortMode mode)
359 if (d->currentRequest.sortMode() != mode) {
361 d->currentRequest.filter(),
362 d->currentRequest.searchTerm(),
363 d->currentRequest.categories(),
364 d->currentRequest.page(),
365 d->currentRequest.pageSize());
367 Q_EMIT sortOrderChanged();
371QString Engine::searchTerm()
const
373 return d->currentRequest.searchTerm();
376void Engine::setSearchTerm(
const QString &searchTerm)
378 if (d->isValid && d->currentRequest.searchTerm() != searchTerm) {
380 d->currentRequest.filter(),
382 d->currentRequest.categories(),
383 d->currentRequest.page(),
384 d->currentRequest.pageSize());
385 Q_EMIT searchTermChanged();
391 d->searchTimer.start();
397 return d->searchPresetModel;
400bool Engine::isValid()
407 const auto core = dd->providerCores.value(entry.providerId());
409 qCWarning(KNEWSTUFFQUICK) <<
"Provider was not found" << entry.providerId();
413 const auto base = core->d->base;
414 if (!base->isInitialized()) {
415 qCWarning(KNEWSTUFFQUICK) <<
"Provider was not initialized" << base << entry.providerId();
419 base->loadEntryDetails(entry);
422void Engine::reloadEntries()
427 d->currentRequest.filter(),
428 d->currentRequest.searchTerm(),
429 d->currentRequest.categories(),
431 d->currentRequest.pageSize());
434 const auto providersList = dd->providerCores;
435 for (
const auto &core : providersList) {
436 const auto &base = core->d->base;
437 if (base->isInitialized()) {
438 if (d->currentRequest.filter() == KNSCore::Filter::Installed || d->currentRequest.filter() == KNSCore::Filter::Updates) {
440 base->loadEntries(d->currentRequest);
446 qCDebug(KNEWSTUFFQUICK) <<
"From cache";
447 cacheEntries << lastCache;
449 d->currentPage = d->currentRequest.page();
450 d->currentRequest = d->currentRequest.nextPage();
451 lastCache = dd->cache->requestFromCache(d->currentRequest);
455 if (d->currentPage >= 0) {
457 d->currentRequest.filter(),
458 d->currentRequest.searchTerm(),
459 d->currentRequest.categories(),
461 d->currentRequest.pageSize());
465 Q_EMIT signalEntriesLoaded(cacheEntries);
467 qCDebug(KNEWSTUFFQUICK) <<
"From provider";
468 base->loadEntries(d->currentRequest);
478void Engine::loadPreview(
const KNSCore::Entry &entry, KNSCore::Entry::PreviewType type)
480 qCDebug(KNEWSTUFFQUICK) <<
"START preview: " << entry.name() <<
type;
481 auto l =
new KNSCore::ImageLoader(entry, type,
this);
482 connect(l, &KNSCore::ImageLoader::signalPreviewLoaded,
this, [
this](
const KNSCore::Entry &entry, KNSCore::Entry::PreviewType type) {
483 qCDebug(KNEWSTUFFQUICK) <<
"FINISH preview: " << entry.name() <<
type;
484 Q_EMIT signalEntryPreviewLoaded(entry, type);
488 connect(l, &KNSCore::ImageLoader::signalError,
this, [
this](
const KNSCore::Entry &entry, KNSCore::Entry::PreviewType type,
const QString &errorText) {
489 Q_EMIT signalErrorCode(KNSCore::ErrorCode::ImageError, errorText, QVariantList() << entry.name() << type);
490 qCDebug(KNEWSTUFFQUICK) <<
"ERROR preview: " << errorText << entry.name() <<
type;
504#if KNEWSTUFFCORE_BUILD_DEPRECATED_SINCE(6, 9)
507 qmlWarning(
this) <<
"org.kde.newstuff.core.Engine.install is deprecated. Use installLinkId or installLatest";
509 registerTransaction(transaction);
510 if (!transaction->isFinished()) {
519 registerTransaction(transaction);
520 if (!transaction->isFinished()) {
528 registerTransaction(transaction);
529 if (!transaction->isFinished()) {
545void Engine::requestMoreData()
547 qCDebug(KNEWSTUFFQUICK) <<
"Get more data! current page: " << d->currentPage <<
" requested: " << d->currentRequest.page();
549 if (d->currentPage < d->currentRequest.page()) {
553 d->currentRequest = d->currentRequest.nextPage();
557void Engine::doRequest()
559 const auto cores = dd->providerCores;
560 for (
const auto &core : cores) {
561 const auto &base = core->d->base;
562 if (base->isInitialized()) {
563 base->loadEntries(d->currentRequest);
570void Engine::revalidateCacheEntries()
575 const auto cores = dd->providerCores;
576 for (
const auto &core : cores) {
577 const auto &base = core->d->base;
578 if (base && base->isInitialized()) {
580 dd->cache->removeDeletedEntries();
583 for (
const auto &oldCachedEntry : cacheBefore) {
584 if (!cacheAfter.
contains(oldCachedEntry)) {
595void Engine::restoreSearch()
597 d->searchTimer.stop();
598 d->currentRequest = d->storedRequest;
604 d->searchTimer.start();
607 qCWarning(KNEWSTUFFQUICK) <<
"Attempted to call restoreSearch() without a correctly initialized engine. You will likely get unexpected behaviour.";
611void Engine::storeSearch()
613 d->storedRequest = d->currentRequest;
A model which shows the categories found in an Engine.
void signalEntryEvent(const KNSCore::Entry &entry, KNSCore::Entry::EntryEvent event)
void errorCode(KNSCore::ErrorCode::ErrorCode errorCode, const QString &message, const QVariant &metadata)
Fires in the case of any critical or serious errors, such as network or API problems.
void setSortOrder(KNSCore::Provider::SortMode newSortOrder)
Q_INVOKABLE void installLinkId(const KNSCore::Entry &entry, quint8 linkId)
Performs an install on the given entry.
Q_INVOKABLE void install(const KNSCore::Entry &entry, int linkId=1)
Installs an entry's payload file.
Q_INVOKABLE void adoptEntry(const KNSCore::Entry &entry)
Adopt an entry using the adoption command.
void setFilter(KNSCore::Provider::Filter filter)
Q_SIGNAL void busyStateChanged()
Signal gets emitted when the busy state changes.
Q_INVOKABLE void installLatest(const KNSCore::Entry &entry)
Performs an install of the latest version on the given entry.
BusyState busyState
Current state of the engine, the state con contain multiple operations an empty BusyState represents ...
Q_INVOKABLE void uninstall(const KNSCore::Entry &entry)
Uninstalls an entry.
void signalErrorCode(KNSCore::ErrorCode::ErrorCode errorCode, const QString &message, const QVariant &metadata)
Fires in the case of any critical or serious errors, such as network or API problems.
KNewStuff data entry container.
@ StatusChangedEvent
Used when an event's status is set (use Entry::status() to get the new status)
static Transaction * install(EngineBase *engine, const Entry &entry, int linkId=1)
Performs an install on the given entry from the engine.
void signalEntryEvent(const KNSCore::Entry &entry, KNSCore::Entry::EntryEvent event)
Informs about how the entry has changed.
void signalMessage(const QString &message)
Provides the message to update our users about how the Transaction progressed.
void signalErrorCode(KNSCore::ErrorCode::ErrorCode errorCode, const QString &message, const QVariant &metadata)
Fires in the case of any critical or serious errors, such as network or API problems.
static Transaction * installLatest(EngineBase *engine, const Entry &entry)
Performs an install of the latest version on the given entry from the engine.
static Transaction * installLinkId(EngineBase *engine, const Entry &entry, quint8 linkId)
Performs an install on the given entry from the engine.
static Transaction * adopt(EngineBase *engine, const Entry &entry)
Adopt the entry from engine using the adoption command.
static Transaction * uninstall(EngineBase *engine, const Entry &entry)
Uninstalls the given entry from the engine.
The SearchPresetModel class.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
Type type(const QSqlDatabase &db)
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
bool contains(const AT &value) const const
bool isEmpty() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool event(QEvent *e)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)