mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-24 19:02:51 +00:00
283 lines
6.9 KiB
C++
283 lines
6.9 KiB
C++
/*
|
|
Copyright (c) 2009 Tobias Koenig <tokoe@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 as published by
|
|
the Free Software Foundation; either version 2 of the License, or (at your
|
|
option) any later version.
|
|
|
|
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 "itemsearchjob.h"
|
|
|
|
#include "imapparser_p.h"
|
|
#include "itemfetchscope.h"
|
|
#include "job_p.h"
|
|
#include "protocolhelper_p.h"
|
|
#include "searchquery.h"
|
|
|
|
#include <QtCore/QTimer>
|
|
#include <QThreadStorage>
|
|
|
|
using namespace Akonadi;
|
|
|
|
class Akonadi::ItemSearchJobPrivate : public JobPrivate
|
|
{
|
|
public:
|
|
ItemSearchJobPrivate(ItemSearchJob *parent, const SearchQuery &query)
|
|
: JobPrivate(parent)
|
|
, mQuery(query)
|
|
, mRecursive(false)
|
|
, mRemote(false)
|
|
, mEmitTimer(0)
|
|
{
|
|
}
|
|
|
|
void init()
|
|
{
|
|
Q_Q(ItemSearchJob);
|
|
mEmitTimer = new QTimer(q);
|
|
mEmitTimer->setSingleShot(true);
|
|
mEmitTimer->setInterval(100);
|
|
q->connect(mEmitTimer, SIGNAL(timeout()), q, SLOT(timeout()));
|
|
q->connect(q, SIGNAL(result(KJob*)), q, SLOT(timeout()));
|
|
}
|
|
|
|
void timeout()
|
|
{
|
|
Q_Q(Akonadi::ItemSearchJob);
|
|
|
|
mEmitTimer->stop(); // in case we are called by result()
|
|
if (!mPendingItems.isEmpty()) {
|
|
if (!q->error()) {
|
|
emit q->itemsReceived(mPendingItems);
|
|
}
|
|
mPendingItems.clear();
|
|
}
|
|
}
|
|
|
|
QString jobDebuggingString() const /*Q_DECL_OVERRIDE*/ {
|
|
QStringList flags;
|
|
if ( mRecursive ) {
|
|
flags.append( QLatin1String( "recursive" ) );
|
|
}
|
|
if ( mRemote ) {
|
|
flags.append( QLatin1String( "remote" ) );
|
|
}
|
|
if ( mCollections.isEmpty() ) {
|
|
flags.append( QLatin1String( "all collections" ) );
|
|
} else {
|
|
flags.append( QString::fromLatin1( "%1 collections" ).arg( mCollections.count() ) );
|
|
}
|
|
return QString::fromLatin1( "%1,json=%2" ).arg( flags.join(QLatin1String(","))).arg(QString::fromUtf8(mQuery.toJSON()));
|
|
}
|
|
|
|
Q_DECLARE_PUBLIC(ItemSearchJob)
|
|
|
|
SearchQuery mQuery;
|
|
Collection::List mCollections;
|
|
QStringList mMimeTypes;
|
|
bool mRecursive;
|
|
bool mRemote;
|
|
ItemFetchScope mFetchScope;
|
|
|
|
Item::List mItems;
|
|
Item::List mPendingItems; // items pending for emitting itemsReceived()
|
|
|
|
QTimer *mEmitTimer;
|
|
};
|
|
|
|
QThreadStorage<Session *> instances;
|
|
|
|
static Session *defaultSearchSession()
|
|
{
|
|
if (!instances.hasLocalData()) {
|
|
const QByteArray sessionName = Session::defaultSession()->sessionId() + "-SearchSession";
|
|
instances.setLocalData(new Session(sessionName));
|
|
}
|
|
return instances.localData();
|
|
}
|
|
|
|
static QObject *sessionForJob(QObject *parent)
|
|
{
|
|
if (qobject_cast<Job *>(parent) || qobject_cast<Session *>(parent)) {
|
|
return parent;
|
|
}
|
|
return defaultSearchSession();
|
|
}
|
|
|
|
ItemSearchJob::ItemSearchJob(const SearchQuery &query, QObject *parent)
|
|
: Job(new ItemSearchJobPrivate(this, query), sessionForJob(parent))
|
|
{
|
|
Q_D(ItemSearchJob);
|
|
|
|
d->init();
|
|
}
|
|
|
|
ItemSearchJob::ItemSearchJob(const QString &query, QObject *parent)
|
|
: Job(new ItemSearchJobPrivate(this, SearchQuery::fromJSON(query.toUtf8())), sessionForJob(parent))
|
|
{
|
|
Q_D(ItemSearchJob);
|
|
|
|
d->init();
|
|
}
|
|
|
|
ItemSearchJob::~ItemSearchJob()
|
|
{
|
|
}
|
|
|
|
void ItemSearchJob::setQuery(const QString &query)
|
|
{
|
|
Q_D(ItemSearchJob);
|
|
|
|
d->mQuery = SearchQuery::fromJSON(query.toUtf8());
|
|
}
|
|
|
|
void ItemSearchJob::setQuery(const SearchQuery &query)
|
|
{
|
|
Q_D(ItemSearchJob);
|
|
|
|
d->mQuery = query;
|
|
}
|
|
|
|
void ItemSearchJob::setFetchScope(const ItemFetchScope &fetchScope)
|
|
{
|
|
Q_D(ItemSearchJob);
|
|
|
|
d->mFetchScope = fetchScope;
|
|
}
|
|
|
|
ItemFetchScope &ItemSearchJob::fetchScope()
|
|
{
|
|
Q_D(ItemSearchJob);
|
|
|
|
return d->mFetchScope;
|
|
}
|
|
|
|
void ItemSearchJob::setSearchCollections(const Collection::List &collections)
|
|
{
|
|
Q_D(ItemSearchJob);
|
|
|
|
d->mCollections = collections;
|
|
}
|
|
|
|
Collection::List ItemSearchJob::searchCollections() const
|
|
{
|
|
return d_func()->mCollections;
|
|
}
|
|
|
|
void ItemSearchJob::setMimeTypes(const QStringList &mimeTypes)
|
|
{
|
|
Q_D(ItemSearchJob);
|
|
|
|
d->mMimeTypes = mimeTypes;
|
|
}
|
|
|
|
QStringList ItemSearchJob::mimeTypes() const
|
|
{
|
|
return d_func()->mMimeTypes;
|
|
}
|
|
|
|
void ItemSearchJob::setRecursive(bool recursive)
|
|
{
|
|
Q_D(ItemSearchJob);
|
|
|
|
d->mRecursive = recursive;
|
|
}
|
|
|
|
bool ItemSearchJob::isRecursive() const
|
|
{
|
|
return d_func()->mRecursive;
|
|
}
|
|
|
|
void ItemSearchJob::setRemoteSearchEnabled(bool enabled)
|
|
{
|
|
Q_D(ItemSearchJob);
|
|
|
|
d->mRemote = enabled;
|
|
}
|
|
|
|
bool ItemSearchJob::isRemoteSearchEnabled() const
|
|
{
|
|
return d_func()->mRemote;
|
|
}
|
|
|
|
void ItemSearchJob::doStart()
|
|
{
|
|
Q_D(ItemSearchJob);
|
|
|
|
QByteArray command = d->newTag() + " SEARCH ";
|
|
if (!d->mMimeTypes.isEmpty()) {
|
|
command += "MIMETYPE (" + d->mMimeTypes.join(QLatin1String(" ")).toLatin1() + ") ";
|
|
}
|
|
if (!d->mCollections.isEmpty()) {
|
|
command += "COLLECTIONS (";
|
|
Q_FOREACH (const Collection &collection, d->mCollections) {
|
|
command += QByteArray::number(collection.id()) + ' ';
|
|
}
|
|
command += ") ";
|
|
}
|
|
if (d->mRecursive) {
|
|
command += "RECURSIVE ";
|
|
}
|
|
if (d->mRemote) {
|
|
command += "REMOTE ";
|
|
}
|
|
|
|
command += "QUERY " + ImapParser::quote(d->mQuery.toJSON());
|
|
command += ' ' + ProtocolHelper::itemFetchScopeToByteArray(d->mFetchScope);
|
|
command += '\n';
|
|
d->writeData(command);
|
|
}
|
|
|
|
void ItemSearchJob::doHandleResponse(const QByteArray &tag, const QByteArray &data)
|
|
{
|
|
Q_D(ItemSearchJob);
|
|
|
|
if (tag == "*") {
|
|
int begin = data.indexOf("SEARCH");
|
|
if (begin >= 0) {
|
|
|
|
// split fetch response into key/value pairs
|
|
QList<QByteArray> fetchResponse;
|
|
ImapParser::parseParenthesizedList(data, fetchResponse, begin + 7);
|
|
|
|
Item item;
|
|
ProtocolHelper::parseItemFetchResult(fetchResponse, item);
|
|
if (!item.isValid()) {
|
|
return;
|
|
}
|
|
|
|
d->mItems.append(item);
|
|
d->mPendingItems.append(item);
|
|
if (!d->mEmitTimer->isActive()) {
|
|
d->mEmitTimer->start();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
kDebug() << "Unhandled response: " << tag << data;
|
|
}
|
|
|
|
Item::List ItemSearchJob::items() const
|
|
{
|
|
Q_D(const ItemSearchJob);
|
|
|
|
return d->mItems;
|
|
}
|
|
|
|
QUrl ItemSearchJob::akonadiItemIdUri()
|
|
{
|
|
return QUrl(QLatin1String("http://akonadi-project.org/ontologies/aneo#akonadiItemId"));
|
|
}
|
|
|
|
#include "moc_itemsearchjob.cpp"
|