[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: [kdelibs/frameworks] /: Merge remote-tracking branch 'origin/KDE/4.10' into frameworks
From: David Faure <faure+bluesystems () kde ! org>
Date: 2012-12-01 9:36:44
Message-ID: 20121201093644.D9B77A6091 () git ! kde ! org
[Download RAW message or body]
Git commit 14890a3e8ee2284fe14a23186ffb57ac54eebccd by David Faure.
Committed on 01/12/2012 at 10:36.
Pushed by dfaure into branch 'frameworks'.
Merge remote-tracking branch 'origin/KDE/4.10' into frameworks
Conflicts:
CMakeLists.txt [version]
kdecore/services/kmimetype.cpp [gone, kio/global.cpp has the change]
kio/kio/kdirlister.cpp [watchedWhileInCache]
kio/kio/kprotocolmanager.cpp [KMimeType->QMimeType]
kio/misc/kpac/kpactest.pac [,kded -> .kded5]
kio/misc/kpac/kpactest2.pac [,kded -> .kded5]
kio/tests/krununittest.cpp [kstddirs/qstandardpaths]
M +12 -6 kio/kio/kdirlister.cpp
M +4 -0 kio/kio/kdirlister_p.h
M +19 -1 kio/kio/kprotocolmanager.cpp
M +72 -3 kio/tests/kdirlistertest.cpp
M +1 -0 kio/tests/kdirlistertest.h
M +6 -1 kio/tests/krununittest.cpp
A +1 -1 staging/kservice/src/sycoca/ksycoca.cpp [License: LGPL (v2)]
http://commits.kde.org/kdelibs/14890a3e8ee2284fe14a23186ffb57ac54eebccd
diff --cc kio/kio/kdirlister.cpp
index a7153dc,d7de137..6c88a31
--- a/kio/kio/kdirlister.cpp
+++ b/kio/kio/kdirlister.cpp
@@@ -746,26 -744,31 +751,27 @@@ void KDirListerCache::updateDirectory(
}
}
-bool KDirListerCache::checkUpdate( const QString& _dir )
+bool KDirListerCache::checkUpdate(const QUrl& _dir)
{
- if ( !itemsInUse.contains(_dir) )
- {
- DirItem *item = itemsCached[_dir];
- if ( item && item->complete )
- {
- // Stop watching items once they are only in the cache and not used anymore.
- // We'll trigger an update when listing that dir again later.
- item->complete = false;
- item->watchedWhileInCache = false;
- item->decAutoUpdate();
- // Hmm, this debug output might include login/password from the _dir URL.
- //kDebug(7004) << "directory " << _dir << " not in use, marked dirty.";
+ QString dir = _dir.toString();
+ if (!itemsInUse.contains(dir)) {
+ DirItem *item = itemsCached[dir];
+ if (item && item->complete) {
+ item->complete = false;
++ item->watchedWhileInCache = false;
+ item->decAutoUpdate();
+ // Hmm, this debug output might include login/password from the _dir \
URL. + //kDebug(7004) << "directory " << _dir << " not in use, marked \
dirty."; + }
+ //else
+ //kDebug(7004) << "aborted, directory " << _dir << " not in cache.";
+ return false;
+ } else {
+ return true;
}
- //else
- //kDebug(7004) << "aborted, directory " << _dir << " not in cache.";
-
- return false;
- }
- else
- return true;
}
-KFileItem KDirListerCache::itemForUrl( const KUrl& url ) const
+KFileItem KDirListerCache::itemForUrl( const QUrl& url ) const
{
KFileItem *item = findByUrl( 0, url );
if (item) {
diff --cc kio/kio/kdirlister_p.h
index 48d8e39,a78cc3c..5b1e037
--- a/kio/kio/kdirlister_p.h
+++ b/kio/kio/kdirlister_p.h
@@@ -394,8 -393,11 +395,11 @@@ private
// this directory is up-to-date
bool complete;
+ // the directory is watched while being in the cache (useful for proper \
incAutoUpdate/decAutoUpdate count) + bool watchedWhileInCache;
+
// the complete url of this directory
- KUrl url;
+ QUrl url;
// the local path, with symlinks resolved, so that KDirWatch works
QString m_canonicalPath;
diff --cc kio/kio/kprotocolmanager.cpp
index 657fab8,f8ed48a..79c3000
--- a/kio/kio/kprotocolmanager.cpp
+++ b/kio/kio/kprotocolmanager.cpp
@@@ -59,7 -54,6 +59,8 @@@
#include <kio/slaveconfig.h>
#include <kio/ioslave_defaults.h>
#include <kio/http_slave_defaults.h>
+#include <qstandardpaths.h>
++#include <qmimedatabase.h>
#define QL1S(x) QLatin1String(x)
#define QL1C(x) QLatin1Char(x)
@@@ -1215,10 -1190,26 +1216,27 @@@ QString KProtocolManager::protocolForAr
}
}
}
- return d->protocolForArchiveMimetypes.value(mimeType);
+ const QString prot = d->protocolForArchiveMimetypes.value(mimeType);
+ if (!prot.isEmpty())
+ return prot;
+
+ // Check parent mimetypes
- KMimeType::Ptr mime = KMimeType::mimeType(mimeType);
- if (mime) {
- const QStringList parentMimeTypes = mime->allParentMimeTypes();
++ QMimeDatabase db;
++ QMimeType mime = db.mimeTypeForName(mimeType);
++ if (mime.isValid()) {
++ const QStringList parentMimeTypes = mime.allAncestors();
+ Q_FOREACH(const QString& parentMimeType, parentMimeTypes) {
+ const QString res = \
d->protocolForArchiveMimetypes.value(parentMimeType); + if \
(!res.isEmpty()) { + return res;
+ }
+ }
+ }
+
+ return QString();
}
-QString KProtocolManager::charsetFor(const KUrl& url)
+QString KProtocolManager::charsetFor(const QUrl& url)
{
return KIO::SlaveConfig::self()->configData(url.scheme(), url.host(), \
QLatin1String("Charset")); }
diff --cc kio/tests/kdirlistertest.cpp
index 25ca4da,b574816..77bb379
--- a/kio/tests/kdirlistertest.cpp
+++ b/kio/tests/kdirlistertest.cpp
@@@ -29,9 -29,8 +29,10 @@@ QTEST_MAIN(KDirListerTest
#include "kiotesthelper.h"
#include <kio/deletejob.h>
#include <kdirwatch.h>
+#include <kprotocolinfo.h>
#include <kio/job.h>
#include <kio/copyjob.h>
++#include <qurlpathinfo.h>
#define WORKAROUND_BROKEN_INOTIFY 0
@@@ -872,6 -871,68 +873,68 @@@ void KDirListerTest::testOpenAndStop(
disconnect(&m_dirLister, 0, this, 0);
}
+ // A bug in the decAutoUpdate/incAutoUpdate logic made KDirLister stop watching a \
directory for changes, + // and never watch it again when opening it from the cache.
+ void KDirListerTest::testBug211472()
+ {
+ m_items.clear();
+
- KTempDir newDir;
- const QString path = newDir.name() + "newsubdir/";
++ QTemporaryDir newDir;
++ const QString path = newDir.path() + "/newsubdir/";
+ QDir().mkdir(path);
+ MyDirLister dirLister;
+ connect(&dirLister, SIGNAL(newItems(KFileItemList)), this, \
SLOT(slotNewItems(KFileItemList))); +
- dirLister.openUrl(KUrl(path));
++ dirLister.openUrl(QUrl::fromLocalFile(path));
+ QVERIFY(QTest::kWaitForSignal(&dirLister, SIGNAL(completed()), 1000));
+ QVERIFY(dirLister.isFinished());
+ QVERIFY(m_items.isEmpty());
+
+ if (true) {
+ // This block is required to trigger bug 211472.
+
+ // Go 'up' to the parent of 'newsubdir'.
- dirLister.openUrl(KUrl(newDir.name()));
++ dirLister.openUrl(QUrl::fromLocalFile(newDir.path()));
+ QVERIFY(QTest::kWaitForSignal(&dirLister, SIGNAL(completed()), 1000));
+ QVERIFY(dirLister.isFinished());
+ QVERIFY(!m_items.isEmpty());
+ m_items.clear();
+
+ // Create a file in 'newsubdir' while we are listing its parent dir.
+ createTestFile(path + "newFile-1");
+ // At this point, newsubdir is not used, so it's moved to the cache.
+ // This happens in checkUpdate, called when receiving a notification for \
the cached dir, + // this is why this unittest needs to create a test file in \
the subdir. + QTest::qWait(1000);
+ QVERIFY(m_items.isEmpty());
+
+ // Return to 'newsubdir'. It will be emitted from the cache, then an update \
will happen.
- dirLister.openUrl(KUrl(path));
++ dirLister.openUrl(QUrl::fromLocalFile(path));
+ QVERIFY(QTest::kWaitForSignal(&dirLister, SIGNAL(completed()), 1000));
+ QVERIFY(QTest::kWaitForSignal(&dirLister, SIGNAL(completed()), 1000));
+ QVERIFY(dirLister.isFinished());
+ QCOMPARE(m_items.count(), 1);
+ m_items.clear();
+ }
+
+ // Now try to create a second file in 'newsubdir' and verify that the
+ // dir lister notices it.
+ QTest::qWait(1000); // We need a 1s timestamp difference on the dir, otherwise \
FAM won't notice anything. +
+ createTestFile(path + "newFile-2");
+
+ int numTries = 0;
+ // Give time for KDirWatch to notify us
+ while (m_items.isEmpty()) {
+ QVERIFY(++numTries < 10);
+ QTest::qWait(200);
+ }
+ QCOMPARE(m_items.count(), 1);
+
- newDir.unlink();
++ newDir.remove();
+ QVERIFY(QTest::kWaitForSignal(&dirLister, SIGNAL(clear()), 1000));
+ }
+
void KDirListerTest::testRedirection()
{
m_items.clear();
@@@ -955,7 -1013,7 +1018,7 @@@ void KDirListerTest::slotRefreshItems2(
void KDirListerTest::testDeleteCurrentDir()
{
// ensure m_dirLister holds the items.
-- m_dirLister.openUrl(KUrl(path()), KDirLister::NoFlags);
++ m_dirLister.openUrl(QUrl::fromLocalFile(path()), KDirLister::NoFlags);
connect(&m_dirLister, SIGNAL(completed()), this, SLOT(exitLoop()));
enterLoop();
disconnect(&m_dirLister, SIGNAL(completed()), this, SLOT(exitLoop()));
@@@ -968,8 -1026,14 +1031,14 @@@
enterLoop();
QCOMPARE(m_dirLister.spyClear.count(), 1);
QCOMPARE(m_dirLister.spyClearKUrl.count(), 0);
- QCOMPARE(m_dirLister.spyItemsDeleted.count(), 1);
- QCOMPARE(m_dirLister.spyItemsDeleted[0][0].value<KFileItemList>().count(), 1);
- KUrl::List deletedUrls;
++ QList<QUrl> deletedUrls;
+ for (int i = 0; i < m_dirLister.spyItemsDeleted.count(); ++i)
+ deletedUrls += \
m_dirLister.spyItemsDeleted[i][0].value<KFileItemList>().urlList(); + //kDebug() \
<< deletedUrls;
- KUrl currentDirUrl = QUrl::fromLocalFile(path());
- currentDirUrl.adjustPath(KUrl::RemoveTrailingSlash);
++ QUrl currentDirUrl = QUrl::fromLocalFile(path());
++ QUrlPathInfo::adjustPath(currentDirUrl, QUrlPathInfo::StripTrailingSlash);
+ // Sometimes I get ("current/subdir", "current") here, but that seems ok.
+ QVERIFY(deletedUrls.contains(currentDirUrl));
}
int KDirListerTest::fileCount() const
diff --cc kio/tests/krununittest.cpp
index 314da79,b58033f..334a4be
--- a/kio/tests/krununittest.cpp
+++ b/kio/tests/krununittest.cpp
@@@ -129,14 -122,19 +129,19 @@@ void KRunUnitTest::testProcessDesktopEx
process.setShellCommand("");
const QString shellPath = process.program().at(0);
+ // Arch moved /bin/date to /usr/bin/date...
- const QString datePath = KStandardDirs::findExe("date");
++ const QString datePath = QStandardPaths::findExecutable("date");
+
for (int su = 0; su < 2; su++)
for (int te = 0; te < 2; te++)
for (int ex = 0; ex < 2; ex++) {
int pt = ex+te*2+su*4;
QString exe;
if (pt == 4 || pt == 5)
- exe = KStandardDirs::findExe("kdesu");
+ exe = QStandardPaths::findExecutable("kdesu");
- const QString result = \
QString::fromLatin1(rslts[pt]).replace("/bin/sh", shellPath); + const \
QString result = QString::fromLatin1(rslts[pt]) + \
.replace("/bin/sh", shellPath) + .replace("/bin/date", datePath);
checkPDE( execs[ex], terms[te], sus[su], l0, false, exe + result);
}
}
diff --cc staging/kservice/src/sycoca/ksycoca.cpp
index b75e2ce,0000000..3754cad
mode 100644,000000..100644
--- a/staging/kservice/src/sycoca/ksycoca.cpp
+++ b/staging/kservice/src/sycoca/ksycoca.cpp
@@@ -1,626 -1,0 +1,626 @@@
+/* This file is part of the KDE libraries
+ * Copyright (C) 1999-2000 Waldo Bastian <bastian@kde.org>
+ * Copyright (C) 2005-2009 David Faure <faure@kde.org>
+ * Copyright (C) 2008 Hamish Rodda <rodda@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ **/
+
+#include "ksycoca.h"
+#include "ksycoca_p.h"
+#include "ksycocatype.h"
+#include "ksycocafactory.h"
+#include "kmemfile_p.h"
+#include "kconfiggroup.h"
+#include "ksharedconfig.h"
+
+#include <qstandardpaths.h>
+#include <QtCore/QDataStream>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QFile>
+#include <QtCore/QBuffer>
+#include <QProcess>
+#include <QtDBus/QtDBus>
+
+#include <stdlib.h>
+#include <fcntl.h>
+
+#include "ksycocadevices_p.h"
+
+// TODO: remove mmap() from kdewin32 and use QFile::mmap() when needed
+#ifdef Q_OS_WIN
+#undef HAVE_MMAP
+#endif
+/**
+ * Sycoca file version number.
+ * If the existing file is outdated, it will not get read
+ * but instead we'll ask kded to regenerate a new one...
+ */
- #define KSYCOCA_VERSION 210
++#define KSYCOCA_VERSION 212
+
+/**
+ * Sycoca file name, used internally (by kbuildsycoca)
+ */
+#define KSYCOCA_FILENAME "ksycoca5"
+
+#if HAVE_MADVISE || HAVE_MMAP
+#include <sys/mman.h> // This #include was checked when looking for posix_madvise
+#endif
+
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *) -1)
+#endif
+
+static bool s_autoRebuild = true;
+
+// The following limitations are in place:
+// Maximum length of a single string: 8192 bytes
+// Maximum length of a string list: 1024 strings
+// Maximum number of entries: 8192
+//
+// The purpose of these limitations is to limit the impact
+// of database corruption.
+
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(KSycocaPrivate::BehaviorsIfNotFound)
+
+KSycocaPrivate::KSycocaPrivate()
+ : databaseStatus( DatabaseNotOpen ),
+ readError( false ),
+ timeStamp( 0 ),
+ m_databasePath(),
+ updateSig( 0 ),
+ sycoca_size(0),
+ sycoca_mmap(0),
+ m_mmapFile(0),
+ m_device(0)
+{
+#ifdef Q_OS_WIN
+ /*
+ on windows we use KMemFile (QSharedMemory) to avoid problems
+ with mmap (can't delete a mmap'd file)
+ */
+ m_sycocaStrategy = StrategyMemFile;
+#else
+ m_sycocaStrategy = StrategyMmap;
+#endif
+ KConfigGroup config(KSharedConfig::openConfig(), "KSycoca");
+ setStrategyFromString(config.readEntry("strategy"));
+}
+
+void KSycocaPrivate::setStrategyFromString(const QString& strategy) {
+ if (strategy == QLatin1String("mmap"))
+ m_sycocaStrategy = StrategyMmap;
+ else if (strategy == QLatin1String("file"))
+ m_sycocaStrategy = StrategyFile;
+ else if (strategy == QLatin1String("sharedmem"))
+ m_sycocaStrategy = StrategyMemFile;
+ else if (!strategy.isEmpty())
+ qWarning() << "Unknown sycoca strategy:" << strategy;
+}
+
+bool KSycocaPrivate::tryMmap()
+{
+#if HAVE_MMAP
+ Q_ASSERT(!m_databasePath.isEmpty());
+ m_mmapFile = new QFile(m_databasePath);
+ const bool canRead = m_mmapFile->open(QIODevice::ReadOnly);
+ Q_ASSERT(canRead);
+ if (!canRead)
+ return false;
+ fcntl(m_mmapFile->handle(), F_SETFD, FD_CLOEXEC);
+ sycoca_size = m_mmapFile->size();
+ sycoca_mmap = (const char *) mmap(0, sycoca_size,
+ PROT_READ, MAP_SHARED,
+ m_mmapFile->handle(), 0);
+ /* POSIX mandates only MAP_FAILED, but we are paranoid so check for
+ null pointer too. */
+ if (sycoca_mmap == (const char*) MAP_FAILED || sycoca_mmap == 0) {
+ qDebug().nospace() << "mmap failed. (length = " << sycoca_size << ")";
+ sycoca_mmap = 0;
+ return false;
+ } else {
+#if HAVE_MADVISE
+ (void) posix_madvise((void*)sycoca_mmap, sycoca_size, POSIX_MADV_WILLNEED);
+#endif // HAVE_MADVISE
+ return true;
+ }
+#endif // HAVE_MMAP
+ return false;
+}
+
+int KSycoca::version()
+{
+ return KSYCOCA_VERSION;
+}
+
+class KSycocaSingleton
+{
+public:
+ KSycocaSingleton() { }
+ ~KSycocaSingleton() { }
+
+ bool hasSycoca() const {
+ return m_threadSycocas.hasLocalData();
+ }
+ KSycoca* sycoca() {
+ if (!m_threadSycocas.hasLocalData())
+ m_threadSycocas.setLocalData(new KSycoca);
+ return m_threadSycocas.localData();
+ }
+ void setSycoca(KSycoca* s) {
+ m_threadSycocas.setLocalData(s);
+ }
+
+private:
+ QThreadStorage<KSycoca*> m_threadSycocas;
+};
+
+Q_GLOBAL_STATIC(KSycocaSingleton, ksycocaInstance)
+
+// Read-only constructor
+KSycoca::KSycoca()
+ : d(new KSycocaPrivate)
+{
+ QDBusConnection::sessionBus().connect(QString(), QString(),
+ QString::fromLatin1("org.kde.KSycoca"),
+ \
QString::fromLatin1("notifyDatabaseChanged"), + \
this, SLOT(notifyDatabaseChanged(QStringList))); +}
+
+bool KSycocaPrivate::openDatabase(bool openDummyIfNotFound)
+{
+ Q_ASSERT(databaseStatus == DatabaseNotOpen);
+
+ delete m_device; m_device = 0;
+ QString path = KSycoca::absoluteFilePath();
+
+ bool canRead = QFileInfo(path).isReadable();
+ qDebug() << "Trying to open ksycoca from" << path;
+ if (!canRead) {
+ path = KSycoca::absoluteFilePath(KSycoca::GlobalDatabase);
+ if (!path.isEmpty()) {
+ qDebug() << "Trying to open global ksycoca from " << path;
+ canRead = QFileInfo(path).isReadable();
+ }
+ }
+
+ bool result = true;
+ if (canRead) {
+ m_databasePath = path;
+ checkVersion();
+ } else { // No database file
+ //qDebug() << "Could not open ksycoca";
+ m_databasePath.clear();
+ databaseStatus = NoDatabase;
+ if (openDummyIfNotFound) {
+ // We open a dummy database instead.
+ //qDebug() << "No database, opening a dummy one.";
+
+ m_sycocaStrategy = StrategyDummyBuffer;
+ QDataStream* str = stream();
+ *str << qint32(KSYCOCA_VERSION);
+ *str << qint32(0);
+ } else {
+ result = false;
+ }
+ }
+ return result;
+}
+
+KSycocaAbstractDevice* KSycocaPrivate::device()
+{
+ if (m_device)
+ return m_device;
+
+ Q_ASSERT(!m_databasePath.isEmpty());
+
+ KSycocaAbstractDevice* device = m_device;
+ if (m_sycocaStrategy == StrategyDummyBuffer) {
+ device = new KSycocaBufferDevice;
+ device->device()->open(QIODevice::ReadOnly); // can't fail
+ } else {
+#if HAVE_MMAP
+ if (m_sycocaStrategy == StrategyMmap && tryMmap()) {
+ device = new KSycocaMmapDevice(sycoca_mmap,
+ sycoca_size);
+ if (!device->device()->open(QIODevice::ReadOnly)) {
+ delete device; device = 0;
+ }
+ }
+#endif
+#ifndef QT_NO_SHAREDMEMORY
+ if (!device && m_sycocaStrategy == StrategyMemFile) {
+ device = new KSycocaMemFileDevice(m_databasePath);
+ if (!device->device()->open(QIODevice::ReadOnly)) {
+ delete device; device = 0;
+ }
+ }
+#endif
+ if (!device) {
+ device = new KSycocaFileDevice(m_databasePath);
+ if (!device->device()->open(QIODevice::ReadOnly)) {
+ qWarning() << "Couldn't open" << m_databasePath << "even though it \
is readable? Impossible."; + //delete device; device = 0; // this \
would crash in the return statement... + }
+ }
+ }
+ if (device) {
+ m_device = device;
+ }
+ return m_device;
+}
+
+QDataStream*& KSycocaPrivate::stream()
+{
+ if (!m_device) {
+ if (databaseStatus == DatabaseNotOpen) {
+ checkDatabase(KSycocaPrivate::IfNotFoundRecreate | \
KSycocaPrivate::IfNotFoundOpenDummy); + }
+
+ device(); // create m_device
+ }
+
+ return m_device->stream();
+}
+
+// Read-write constructor - only for KBuildSycoca
+KSycoca::KSycoca( bool /* dummy */ )
+ : d(new KSycocaPrivate)
+{
+ // This instance was not created by the singleton, but by a direct call to new!
+ ksycocaInstance()->setSycoca(this);
+}
+
+KSycoca * KSycoca::self()
+{
+ KSycoca* s = ksycocaInstance()->sycoca();
+ Q_ASSERT(s);
+ return s;
+}
+
+KSycoca::~KSycoca()
+{
+ d->closeDatabase();
+ delete d;
+ //if (ksycocaInstance.exists()
+ // && ksycocaInstance->self == this)
+ // ksycocaInstance->self = 0;
+}
+
+bool KSycoca::isAvailable()
+{
+ return self()->d->checkDatabase(KSycocaPrivate::IfNotFoundDoNothing/* don't \
open dummy db if not found */); +}
+
+void KSycocaPrivate::closeDatabase()
+{
+ delete m_device;
+ m_device = 0;
+
+ // It is very important to delete all factories here
+ // since they cache information about the database file
+ // But other threads might be using them, so this class is
+ // refcounted, and deleted when the last thread is done with them
+ qDeleteAll(m_factories);
+ m_factories.clear();
+#if HAVE_MMAP
+ if (sycoca_mmap) {
+ //QBuffer *buf = static_cast<QBuffer*>(device);
+ //buf->buffer().clear();
+ // Solaris has munmap(char*, size_t) and everything else should
+ // be happy with a char* for munmap(void*, size_t)
+ munmap(const_cast<char*>(sycoca_mmap), sycoca_size);
+ sycoca_mmap = 0;
+ }
+ delete m_mmapFile; m_mmapFile = 0;
+#endif
+
+ databaseStatus = DatabaseNotOpen;
+ timeStamp = 0;
+}
+
+void KSycoca::addFactory( KSycocaFactory *factory )
+{
+ d->addFactory(factory);
+}
+
+#ifndef KDE_NO_DEPRECATED
+bool KSycoca::isChanged(const char *type)
+{
+ return self()->d->changeList.contains(QString::fromLatin1(type));
+}
+#endif
+
+void KSycoca::notifyDatabaseChanged(const QStringList &changeList)
+{
+ d->changeList = changeList;
+ //qDebug() << QThread::currentThread() << "got a notifyDatabaseChanged signal" \
<< changeList; + // kbuildsycoca tells us the database file changed
+ // Close the database and forget all about what we knew
+ // The next call to any public method will recreate
+ // everything that's needed.
+ d->closeDatabase();
+
+ // Now notify applications
+#ifndef KDE_NO_DEPRECATED
+ emit databaseChanged();
+#endif
+ emit databaseChanged(changeList);
+}
+
+QDataStream * KSycoca::findEntry(int offset, KSycocaType &type)
+{
+ QDataStream* str = stream();
+ Q_ASSERT(str);
+ //qDebug() << QString("KSycoca::_findEntry(offset=%1)").arg(offset,8,16);
+ str->device()->seek(offset);
+ qint32 aType;
+ *str >> aType;
+ type = KSycocaType(aType);
+ //qDebug() << QString("KSycoca::found type %1").arg(aType);
+ return str;
+}
+
+KSycocaFactoryList* KSycoca::factories()
+{
+ return d->factories();
+}
+
+// Warning, checkVersion rewinds to the beginning of stream().
+bool KSycocaPrivate::checkVersion()
+{
+ QDataStream *m_str = device()->stream();
+ Q_ASSERT(m_str);
+ m_str->device()->seek(0);
+ qint32 aVersion;
+ *m_str >> aVersion;
+ if ( aVersion < KSYCOCA_VERSION ) {
+ qDebug() << "Found version" << aVersion << ", expecting version" << \
KSYCOCA_VERSION << "or higher."; + databaseStatus = BadVersion;
+ return false;
+ } else {
+ databaseStatus = DatabaseOK;
+ return true;
+ }
+}
+
+// If it returns true, we have a valid database and the stream has rewinded to the \
beginning +// and past the version number.
+bool KSycocaPrivate::checkDatabase(BehaviorsIfNotFound ifNotFound)
+{
+ if (databaseStatus == DatabaseOK) {
+ if (checkVersion()) // we know the version is ok, but we must rewind the \
stream anyway + return true;
+ }
+
+ closeDatabase(); // close the dummy one
+
+ // We can only use the installed ksycoca file if kded is running,
+ // since kded is what keeps the file uptodate.
+ QDBusConnectionInterface* bus = QDBusConnection::sessionBus().interface();
+ const bool kdedRunning = \
bus->isServiceRegistered(QString::fromLatin1("org.kde.kded5")) || + \
qAppName() == "kbuildsycoca5"; +
+ // Check if new database already available
+ if (kdedRunning && openDatabase(ifNotFound & IfNotFoundOpenDummy)) {
+ if (checkVersion()) {
+ // Database exists, and version is ok.
+ return true;
+ }
+ }
+
+ if (ifNotFound & IfNotFoundRecreate) {
+ // Ask kded to rebuild ksycoca
+ // (so that it's not only built, but also kept up-to-date...)
+ bool justStarted = false;
+ if (!bus->isServiceRegistered(QLatin1String("org.kde.kded5"))) {
+ // kded isn't even running: start it
+ QDBusReply<void> reply = \
bus->startService(QLatin1String("org.kde.kded5")); + if \
(!reply.isValid()) { + qWarning() << "Couldn't start kded5 from \
org.kde.kded5.service:" << reply.error(); + }
+ //qDebug() << "kded5 registered";
+ justStarted = true;
+ } else {
+ //qDebug() << "kded5 found";
+ }
+
+ QDBusInterface sycoca(QLatin1String("org.kde.kded5"), \
QLatin1String("/kbuildsycoca")); +#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
+ if (QStandardPaths::isTestModeEnabled()) {
+ if (!justStarted) {
+ const QDBusReply<bool> testMode = \
sycoca.call(QLatin1String("isTestModeEnabled")); + if \
(!testMode.value()) { + qWarning() << "This unit test uses \
ksycoca, it needs to be run in a separate DBus session, so that kded can be started \
in 'test mode'."; + qWarning() << "KSycoca updates will very \
likely fail unless you do that."; + qWarning() << "`eval \
dbus-launch` ; make test"; + // Idea for the future: move \
kbuildsycoca stuff to its own kded module, and use + // the same \
module with a different name, for test mode. + // On the other \
hand, the use of other kded modules (cookies, timezone, etc.) + \
// is also better separated from the user's kded anyway. + }
+ }
+ sycoca.call(QLatin1String("enableTestMode"));
+ Q_ASSERT(QDBusReply<bool>(sycoca.call(QLatin1String("isTestModeEnabled"))).value());
+ }
+#else
+ Q_UNUSED(justStarted);
+#endif
+
+ //qDebug() << "We have no database.... asking kded to create it";
+ sycoca.call(QLatin1String("recreate"));
+
+ closeDatabase(); // close the dummy one
+
+ // Ok, the new database should be here now, open it.
+ if (!openDatabase(ifNotFound & IfNotFoundOpenDummy)) {
+ qDebug() << "Still no database...";
+ return false; // Still no database - uh oh
+ }
+ if (!checkVersion()) {
+ qDebug() << "Still outdated...";
+ return false; // Still outdated - uh oh
+ }
+ return true;
+ }
+
+ return false;
+}
+
+QDataStream * KSycoca::findFactory(KSycocaFactoryId id)
+{
+ // Ensure we have a valid database (right version, and rewinded to beginning)
+ if (!d->checkDatabase(KSycocaPrivate::IfNotFoundRecreate)) {
+ return 0;
+ }
+
+ QDataStream* str = stream();
+ Q_ASSERT(str);
+
+ qint32 aId;
+ qint32 aOffset;
+ while(true) {
+ *str >> aId;
+ if (aId == 0) {
+ qWarning() << "Error, KSycocaFactory (id =" << int(id) << ") not \
found!"; + break;
+ }
+ *str >> aOffset;
+ if (aId == id) {
+ //qDebug() << "KSycoca::findFactory(" << id << ") offset " << aOffset;
+ str->device()->seek(aOffset);
+ return str;
+ }
+ }
+ return 0;
+}
+
+QString KSycoca::kfsstnd_prefixes()
+{
+ // do not try to launch kbuildsycoca from here; this code is also called by \
kbuildsycoca. + if (!d->checkDatabase(KSycocaPrivate::IfNotFoundDoNothing))
+ return QString();
+ QDataStream* str = stream();
+ Q_ASSERT(str);
+ qint32 aId;
+ qint32 aOffset;
+ // skip factories offsets
+ while(true)
+ {
+ *str >> aId;
+ if ( aId )
+ *str >> aOffset;
+ else
+ break; // just read 0
+ }
+ // We now point to the header
+ QString prefixes;
+ KSycocaEntry::read(*str, prefixes);
+ *str >> d->timeStamp;
+ KSycocaEntry::read(*str, d->language);
+ *str >> d->updateSig;
+ KSycocaEntry::read(*str, d->allResourceDirs);
+ return prefixes;
+}
+
+quint32 KSycoca::timeStamp()
+{
+ if (!d->timeStamp)
+ (void) kfsstnd_prefixes();
+ return d->timeStamp;
+}
+
+quint32 KSycoca::updateSignature()
+{
+ if (!d->timeStamp)
+ (void) kfsstnd_prefixes();
+ return d->updateSig;
+}
+
+QString KSycoca::absoluteFilePath(DatabaseType type)
+{
+ if (type == GlobalDatabase) {
+ QString path = QStandardPaths::locate(QStandardPaths::GenericDataLocation, \
QString::fromLatin1("kde5/services/" KSYCOCA_FILENAME)); + if \
(path.isEmpty()) + return \
QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + \
QString::fromLatin1("/kde5/services/" KSYCOCA_FILENAME); + return path;
+ }
+
+ const QByteArray ksycoca_env = qgetenv("KDESYCOCA");
+ if (ksycoca_env.isEmpty()) {
+ return QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation) \
+ QLatin1Char('/') + QString::fromLatin1(KSYCOCA_FILENAME); + } else {
+ return QFile::decodeName(ksycoca_env);
+ }
+}
+
+QString KSycoca::language()
+{
+ if (d->language.isEmpty())
+ (void) kfsstnd_prefixes();
+ return d->language;
+}
+
+QStringList KSycoca::allResourceDirs()
+{
+ if (!d->timeStamp)
+ (void) kfsstnd_prefixes();
+ return d->allResourceDirs;
+}
+
+void KSycoca::flagError()
+{
+ qWarning() << "ERROR: KSycoca database corruption!";
+ KSycocaPrivate* d = ksycocaInstance()->sycoca()->d;
+ if (d->readError)
+ return;
+ d->readError = true;
+ if (s_autoRebuild) {
+ // Rebuild the damned thing.
+ if (QProcess::execute(QStandardPaths::findExecutable(QString::fromLatin1(KBUILDSYCOCA_EXENAME))) \
!= 0) + qWarning("ERROR: Running %s failed", KBUILDSYCOCA_EXENAME);
+ // Old comment, maybe not true anymore:
+ // Do not wait until the DBUS signal from kbuildsycoca here.
+ // It deletes m_str which is a problem when flagError is called during the \
KSycocaFactory ctor... + }
+}
+
+bool KSycoca::isBuilding()
+{
+ return false;
+}
+
+void KSycoca::disableAutoRebuild()
+{
+ s_autoRebuild = false;
+}
+
+QDataStream*& KSycoca::stream()
+{
+ return d->stream();
+}
+
+void KSycoca::clearCaches()
+{
+#if QT_VERSION >= QT_VERSION_CHECK(5,1,0)
+ if (ksycocaInstance.exists() && ksycocaInstance()->hasSycoca())
+#else
+ if (ksycocaInstance() && ksycocaInstance()->hasSycoca())
+#endif
+ ksycocaInstance()->sycoca()->d->closeDatabase();
+}
+
+#include "ksycoca.moc"
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic