14#include <QFileSystemWatcher>
17#include <QXmlStreamReader>
18#include <knewstuffcore_debug.h>
19#include <qstandardpaths.h>
21#include "searchrequest.h"
22#include "searchrequest_p.h"
24class KNSCore::Cache2Private
27 Cache2Private(Cache2 *qq)
36 QHash<QString, Entry::List> requestCache;
38 QPointer<QTimer> throttleTimer;
46 bool writingRegistry =
false;
47 bool reloadingRegistry =
false;
52 throttleTimer =
new QTimer(q);
56 throttleTimer->setSingleShot(
true);
57 throttleTimer->setInterval(1000);
59 throttleTimer->start();
63using namespace KNSCore;
66Q_GLOBAL_STATIC(CacheHash, s_caches)
69Cache2::Cache2(
const QString &appName)
71 , d(new Cache2Private(this))
75 d->registryFile =
path +
appName + QStringLiteral(
".knsregistry");
76 qCDebug(KNEWSTUFFCORE) <<
"Using registry file: " << d->registryFile;
78 s_watcher->addPath(d->registryFile);
80 std::function<void()> changeChecker = [
this, &changeChecker]() {
81 if (d->writingRegistry) {
84 d->reloadingRegistry =
true;
90 for (
const Entry &entry : oldCache) {
91 if (!d->cache.contains(entry) && entry.status() != KNSCore::Entry::Deleted) {
92 Entry removedEntry(entry);
93 removedEntry.setEntryDeleted();
94 Q_EMIT entryChanged(removedEntry);
100 for (
const Entry &entry : std::as_const(d->cache)) {
101 auto iterator = oldCache.constFind(entry);
102 if (iterator == oldCache.constEnd()) {
103 Q_EMIT entryChanged(entry);
104 }
else if ((*iterator).status() != entry.status()) {
110 Q_EMIT entryChanged(entry);
113 d->reloadingRegistry =
false;
117 if (file == d->registryFile) {
125 CacheHash::const_iterator it = s_caches()->constFind(appName);
126 if ((it != s_caches()->constEnd()) && !(*it).isNull()) {
133 if (auto cache = s_caches()) {
134 cache->remove(appName);
143 s_watcher->removePath(d->registryFile);
146void Cache2::readRegistry()
148 QFile f(d->registryFile);
151 qWarning() <<
"The file " << d->registryFile <<
" could not be opened.";
157 if (reader.hasError() || !reader.readNextStartElement()) {
158 qCWarning(KNEWSTUFFCORE) <<
"The file could not be parsed.";
163 qCWarning(KNEWSTUFFCORE) <<
"The file doesn't seem to be of interest.";
167 for (
auto token = reader.readNext(); !reader.atEnd(); token = reader.readNext()) {
178 qCDebug(KNEWSTUFFCORE) <<
"Cache read... entries: " << d->cache.size();
181Entry::List Cache2::registryForProvider(
const QString &providerId)
184 for (
const Entry &e : std::as_const(d->cache)) {
185 if (e.providerId() == providerId) {
192Entry::List Cache2::registry()
const
195 for (
const Entry &e : std::as_const(d->cache)) {
201void Cache2::writeRegistry()
207 qCDebug(KNEWSTUFFCORE) <<
"Write registry";
209 d->writingRegistry =
true;
210 QFile f(d->registryFile);
212 qWarning() <<
"Cannot write meta information to" << d->registryFile;
217 doc.appendChild(doc.createProcessingInstruction(QStringLiteral(
"xml"), QStringLiteral(
"version=\"1.0\" encoding=\"UTF-8\"")));
218 QDomElement root = doc.createElement(QStringLiteral(
"hotnewstuffregistry"));
221 for (
const Entry &entry : std::as_const(d->cache)) {
223 if (entry.status() == KNSCore::Entry::Installed || entry.status() == KNSCore::Entry::Updateable) {
230 metastream << doc.toByteArray();
233 d->writingRegistry =
false;
239 if (entry.status() == KNSCore::Entry::Updating || entry.status() == KNSCore::Entry::Installing) {
242 if (!d->reloadingRegistry) {
244 d->cache.remove(entry);
245 d->cache.insert(entry);
253 auto &cacheList = d->requestCache[request.d->hashForRequest()];
254 for (
const auto &entry : entries) {
255 if (!cacheList.contains(entry)) {
256 cacheList.append(entry);
259 qCDebug(KNEWSTUFFCORE) << request.d->hashForRequest() <<
" add to cache: " << entries.size() <<
" keys: " << d->requestCache.keys();
264 qCDebug(KNEWSTUFFCORE) <<
"from cache" << request.d->hashForRequest();
265 return d->requestCache.value(request.d->hashForRequest());
268void KNSCore::Cache2::removeDeletedEntries()
271 while (i.hasNext()) {
273 bool installedFileExists{
false};
275 for (
const auto &installedFile : installedFiles) {
278 if (
QDir(installedFile.left(installedFile.size() - 2)).
exists()) {
279 installedFileExists =
true;
283 installedFileExists =
true;
287 if (!installedFileExists) {
297 for (
const Entry &entry : std::as_const(d->cache)) {
KNewStuff data entry container.
bool setEntryXML(QXmlStreamReader &reader)
set the xml for the entry parses the xml and sets the private members accordingly used to deserialize...
QStringList installedFiles() const
Retrieve the locally installed files.
void setSource(Source source)
The source of this entry can be Cache, Registry or Online -.
QString path(const QString &relativePath)
QCA_EXPORT QString appName()
bool exists() const const
bool mkpath(const QString &dirPath) const const
QDomNode appendChild(const QDomNode &newChild)
bool exists(const QString &fileName)
bool exists(const QString &path)
void fileChanged(const QString &path)
void append(QList< T > &&value)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void destroyed(QObject *obj)
QString writableLocation(StandardLocation type)
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)