KNewStuff
cache.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (c) 2009 Frederik Gladhorn <gladhorn@kde.org> 00003 00004 This library is free software; you can redistribute it and/or 00005 modify it under the terms of the GNU Lesser General Public 00006 License as published by the Free Software Foundation; either 00007 version 2.1 of the License, or (at your option) any later version. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public 00015 License along with this library. If not, see <http://www.gnu.org/licenses/>. 00016 */ 00017 00018 #include "cache.h" 00019 00020 #include <QtCore/QFile> 00021 #include <QtCore/QDir> 00022 #include <QtCore/QFileInfo> 00023 #include <QtCore/QXmlStreamReader> 00024 #include <kstandarddirs.h> 00025 #include <kdebug.h> 00026 00027 using namespace KNS3; 00028 00029 Cache::Cache(QObject* parent): QObject(parent) 00030 { 00031 } 00032 00033 void Cache::setRegistryFileName(const QString& file) 00034 { 00035 m_kns2ComponentName = file; 00036 00037 registryFile = KStandardDirs::locateLocal("data", "knewstuff3/" + file + ".knsregistry"); 00038 kDebug() << "Using registry file: " << registryFile; 00039 } 00040 00041 void Cache::readRegistry() 00042 { 00043 // read KNS2 registry first to migrate it 00044 readKns2MetaFiles(); 00045 00046 QFile f(registryFile); 00047 if (!f.open(QIODevice::ReadOnly)) { 00048 kWarning() << "The file " << registryFile << " could not be opened."; 00049 return; 00050 } 00051 00052 QDomDocument doc; 00053 if (!doc.setContent(&f)) { 00054 kWarning() << "The file could not be parsed."; 00055 return; 00056 } 00057 00058 QDomElement root = doc.documentElement(); 00059 if (root.tagName() != "hotnewstuffregistry") { 00060 kWarning() << "The file doesn't seem to be of interest."; 00061 return; 00062 } 00063 00064 QDomElement stuff = root.firstChildElement("stuff"); 00065 while (!stuff.isNull()) { 00066 EntryInternal e; 00067 e.setEntryXML(stuff); 00068 e.setSource(EntryInternal::Cache); 00069 cache.insert(e); 00070 stuff = stuff.nextSiblingElement("stuff"); 00071 } 00072 00073 kDebug() << "Cache read... entries: " << cache.size(); 00074 } 00075 00076 void Cache::readKns2MetaFiles() 00077 { 00078 KStandardDirs d; 00079 kDebug() << "Loading KNS2 registry of files for the component: " << m_kns2ComponentName; 00080 00081 QString realAppName = m_kns2ComponentName.split(':')[0]; 00082 00083 const QStringList dirs = d.findDirs("data", "knewstuff2-entries.registry"); 00084 for (QStringList::ConstIterator it = dirs.begin(); it != dirs.end(); ++it) { 00085 //kDebug() << " + Load from directory '" + (*it) + "'."; 00086 QDir dir((*it)); 00087 const QStringList files = dir.entryList(QDir::Files | QDir::Readable); 00088 for (QStringList::const_iterator fit = files.begin(); fit != files.end(); ++fit) { 00089 QString filepath = (*it) + '/' + (*fit); 00090 00091 kDebug() << " Load from file '" + filepath + "'."; 00092 00093 QFileInfo info(filepath); 00094 QFile f(filepath); 00095 00096 // first see if this file is even for this app 00097 // because the registry contains entries for all apps 00098 // FIXMEE: should be able to do this with a filter on the entryList above probably 00099 QString thisAppName = QString::fromUtf8(QByteArray::fromBase64(info.baseName().toUtf8())); 00100 00101 // NOTE: the ":" needs to always coincide with the separator character used in 00102 // the id(Entry*) method 00103 thisAppName = thisAppName.split(':')[0]; 00104 00105 if (thisAppName != realAppName) { 00106 continue; 00107 } 00108 00109 if (!f.open(QIODevice::ReadOnly)) { 00110 kWarning() << "The file: " << filepath << " could not be opened."; 00111 continue; 00112 } 00113 00114 QDomDocument doc; 00115 if (!doc.setContent(&f)) { 00116 kWarning() << "The file could not be parsed."; 00117 return; 00118 } 00119 kDebug() << "found entry: " << doc.toString(); 00120 00121 QDomElement root = doc.documentElement(); 00122 if (root.tagName() != "ghnsinstall") { 00123 kWarning() << "The file doesn't seem to be of interest."; 00124 return; 00125 } 00126 00127 // The .meta files only contain one entry 00128 QDomElement stuff = root.firstChildElement("stuff"); 00129 EntryInternal e; 00130 e.setEntryXML(stuff); 00131 e.setSource(EntryInternal::Cache); 00132 00133 if (e.payload().startsWith(QLatin1String("http://download.kde.org/khotnewstuff"))) { 00134 // This is 99% sure a opendesktop file, make it a real one. 00135 e.setProviderId(QLatin1String("https://api.opendesktop.org/v1/")); 00136 e.setHomepage(QString(QLatin1String("http://opendesktop.org/content/show.php?content=") + e.uniqueId())); 00137 00138 } else if (e.payload().startsWith(QLatin1String("http://edu.kde.org/contrib/kvtml/"))) { 00139 // kvmtl-1 00140 e.setProviderId("http://edu.kde.org/contrib/kvtml/kvtml.xml"); 00141 } else if (e.payload().startsWith(QLatin1String("http://edu.kde.org/contrib/kvtml2/"))) { 00142 // kvmtl-2 00143 e.setProviderId("http://edu.kde.org/contrib/kvtml2/provider41.xml"); 00144 } else { 00145 // we failed, skip 00146 kWarning() << "Could not load entry: " << filepath; 00147 continue; 00148 } 00149 00150 e.setStatus(Entry::Installed); 00151 00152 cache.insert(e); 00153 QDomDocument tmp("yay"); 00154 tmp.appendChild(e.entryXML()); 00155 kDebug() << "new entry: " << tmp.toString(); 00156 00157 f.close(); 00158 00159 QDir dir; 00160 if (!dir.remove(filepath)) { 00161 kWarning() << "could not delete old kns2 .meta file: " << filepath; 00162 } else { 00163 kDebug() << "Migrated KNS2 entry to KNS3."; 00164 } 00165 00166 } 00167 } 00168 } 00169 00170 EntryInternal::List Cache::registryForProvider(const QString& providerId) 00171 { 00172 EntryInternal::List entries; 00173 foreach (const EntryInternal& e, cache) { 00174 if (e.providerId() == providerId) { 00175 entries.append(e); 00176 } 00177 } 00178 return entries; 00179 } 00180 00181 00182 void Cache::writeRegistry() 00183 { 00184 kDebug() << "Write registry"; 00185 00186 QFile f(registryFile); 00187 if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) { 00188 kWarning() << "Cannot write meta information to '" << registryFile << "'." << endl; 00189 return; 00190 } 00191 00192 QDomDocument doc("khotnewstuff3"); 00193 doc.appendChild(doc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" )); 00194 QDomElement root = doc.createElement("hotnewstuffregistry"); 00195 doc.appendChild(root); 00196 00197 foreach (const EntryInternal& entry, cache) { 00198 // Write the entry, unless the policy is CacheNever and the entry is not installed. 00199 if (entry.status() == Entry::Installed || entry.status() == Entry::Updateable) { 00200 QDomElement exml = entry.entryXML(); 00201 root.appendChild(exml); 00202 } 00203 } 00204 00205 QTextStream metastream(&f); 00206 metastream << doc.toByteArray(); 00207 00208 f.close(); 00209 } 00210 00211 void Cache::registerChangedEntry(const KNS3::EntryInternal& entry) 00212 { 00213 cache.insert(entry); 00214 } 00215 00216 void Cache::insertRequest(const KNS3::Provider::SearchRequest& request, const KNS3::EntryInternal::List& entries) 00217 { 00218 // append new entries 00219 requestCache[request.hashForRequest()].append(entries); 00220 kDebug() << request.hashForRequest() << " add: " << entries.size() << " keys: " << requestCache.keys(); 00221 } 00222 00223 EntryInternal::List Cache::requestFromCache(const KNS3::Provider::SearchRequest& request) 00224 { 00225 kDebug() << request.hashForRequest(); 00226 return requestCache.value(request.hashForRequest()); 00227 } 00228 00229 #include "cache.moc"
KDE 4.6 API Reference