Commit c03bf8cd authored by Volker Krause's avatar Volker Krause
Browse files

Start of the message (email/news) handling.

The message class for now contains just a pointer to the mime-tree,
meta-data handling is still missing.

There are also a query and a monitor job as well as a self-updating
(flat) message model.

This instroduces a dependency to libkmime, which is GPL. I assume that
linking LGPL code against a GPL-only library is a problem, right? How do
we solve this?

CCMAIL: kde-pim@kde.org

svn path=/trunk/KDE/kdepim/libakonadi/; revision=526069
parent 37f713a4
SUBDIRS = . tests
INCLUDES = -I$(top_srcdir)/ -I$(top_srcdir)/libakonadi $(all_includes)
INCLUDES = -I$(top_srcdir)/ -I$(top_srcdir)/libakonadi -I$(top_srcdir)/libkmime $(all_includes)
noinst_LTLIBRARIES = libakonadi.la
libakonadi_la_SOURCES = datarequest.cpp job.cpp query.cpp collection.cpp \
collectionlistjob.cpp collectionmodel.cpp collectionmonitorjob.cpp \
collectionfetchjob.cpp collectionview.cpp messagecollection.cpp \
messagecollectionmodel.cpp
messagecollectionmodel.cpp message.cpp messagemodel.cpp \
messagequery.cpp messagemonitor.cpp
libakonadi_la_LDFLAGS = $(all_libraries) -no-undefined
libakonadi_la_LIBADD = $(LIB_QT) $(LIB_KDECORE)
libakonadi_la_LIBADD = $(LIB_QT) $(LIB_KDECORE) $(top_builddir)/libkmime/libkmime.la
akonadiincludedir = $(includedir)/libakonadi
akonadiinclude_HEADERS = datarequest.h job.h query.h collection.h \
collectionlistjob.h collectionmodel.h collectionmonitorjob.h \
collectionfetchjob.h collectionview.h messagecollection.h \
messagecollectionmodel.h
messagecollectionmodel.h message.h messagemodel.h \
messagequery.h messagemonitor.h
METASOURCES = AUTO
......
/*
Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>
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 "message.h"
#include <kmime_message.h>
using namespace PIM;
class Message::Private
{
public:
DataReference ref;
KMime::Message *mime;
};
PIM::Message::Message( const DataReference & ref ) :
d( new Private() )
{
d->ref = ref;
}
PIM::Message::~Message( )
{
delete d->mime;
delete d;
}
DataReference PIM::Message::reference( ) const
{
return d->ref;
}
KMime::Message * PIM::Message::mime( ) const
{
return d->mime;
}
void PIM::Message::setMime( KMime::Message * mime )
{
d->mime = mime;
}
/*
Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>
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.
*/
#ifndef PIM_MESSAGE_H
#define PIM_MESSAGE_H
#include <libakonadi/job.h>
namespace KMime {
class Message;
}
namespace PIM {
/**
Representation of an email message or a news article.
*/
class Message
{
public:
typedef QList<Message*> List;
/**
Creates a new Message object.
@param ref The data reference of this message.
*/
Message( const DataReference &ref = DataReference() );
/**
Delete this message.
*/
~Message();
/**
Returns the DataReference of this object.
*/
DataReference reference() const;
/**
Returns the actual content of this message, including message headers
(as far as available).
*/
KMime::Message* mime() const;
/**
Sets the message content. The Message object takes the ownership of
@p mime, ie. it will take care of deleting it.
*/
void setMime( KMime::Message* mime );
private:
class Private;
Private* d;
};
}
#endif
/*
Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>
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 "message.h"
#include "messagemodel.h"
#include "messagemonitor.h"
#include "messagequery.h"
#include <kmime_message.h>
#include <kdebug.h>
#include <klocale.h>
using namespace PIM;
class MessageModel::Private
{
public:
QList<Message*> messages;
QString query;
MessageQuery *listingJob;
MessageMonitor *monitorJob;
QList<MessageQuery*> fetchJobs, updateJobs;
};
PIM::MessageModel::MessageModel( QObject *parent ) :
QAbstractTableModel( parent ),
d( new Private() )
{
d->listingJob = 0;
d->monitorJob = 0;
}
PIM::MessageModel::~MessageModel( )
{
delete d->listingJob;
delete d->monitorJob;
qDeleteAll( d->fetchJobs );
qDeleteAll( d->updateJobs );
delete d;
}
int PIM::MessageModel::columnCount( const QModelIndex & parent ) const
{
Q_UNUSED( parent );
return 5; // keep in sync with the column type enum
}
QVariant PIM::MessageModel::data( const QModelIndex & index, int role ) const
{
if ( !index.isValid() )
return QVariant();
if ( index.row() >= d->messages.count() )
return QVariant();
Message* msg = d->messages.at( index.row() );
Q_ASSERT( msg->mime() );
if ( role == Qt::DisplayRole ) {
switch ( index.column() ) {
case Subject:
return msg->mime()->subject()->asUnicodeString();
case Sender:
return msg->mime()->from()->asUnicodeString();
case Receiver:
return msg->mime()->to()->asUnicodeString();
case Date:
case Size:
// TODO
default:
return QVariant();
}
}
return QVariant();
}
int PIM::MessageModel::rowCount( const QModelIndex & parent ) const
{
Q_UNUSED( parent );
return d->messages.count();
}
QVariant PIM::MessageModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
switch ( section ) {
case Subject:
return i18n( "Subject" );
case Sender:
return i18n( "Sender" );
case Receiver:
return i18n( "Receiver" );
case Date:
return i18n( "Date" );
case Size:
return i18n( "Size" );
default:
return QString();
}
}
return QAbstractTableModel::headerData( section, orientation, role );
}
void PIM::MessageModel::setQuery( const QString & query )
{
if ( d->query == query )
return;
d->query = query;
// the query changed, thus everything we have already is invalid
d->messages.clear();
reset();
// stop all running jobs
delete d->monitorJob;
d->monitorJob = 0;
qDeleteAll( d->updateJobs );
d->updateJobs.clear();
qDeleteAll( d->fetchJobs );
d->updateJobs.clear();
delete d->listingJob;
// start listing job
d->listingJob = new MessageQuery( query, "ENVELOPE" );
connect( d->listingJob, SIGNAL( done( PIM::Job* ) ), SLOT( listingDone( PIM::Job* ) ) );
d->listingJob->start();
}
void PIM::MessageModel::listingDone( PIM::Job * job )
{
Q_ASSERT( job == d->listingJob );
if ( job->error() ) {
// TODO
kWarning() << k_funcinfo << "Message query failed!" << endl;
} else {
d->messages = d->listingJob->messages();
reset();
}
d->listingJob->deleteLater();
d->listingJob = 0;
// start monitor job
d->monitorJob = new MessageMonitor( d->query );
connect( d->monitorJob, SIGNAL( messagesChanged( const DataReference::List& ) ),
SLOT( messagesChanged( const DataReference::List& ) ) );
connect( d->monitorJob, SIGNAL( messagesRemoved( const DataReference::List& ) ),
SLOT( messagesRemoved( const DataReference::List& ) ) );
d->monitorJob->start();
}
void PIM::MessageModel::fetchingNewDone( PIM::Job * job )
{
Q_ASSERT( d->fetchJobs.contains( static_cast<MessageQuery*>( job ) ) );
if ( job->error() ) {
// TODO
kWarning() << k_funcinfo << "Fetching new messages failed!" << endl;
} else {
Message::List list = static_cast<MessageQuery*>( job )->messages();
beginInsertRows( QModelIndex(), d->messages.size(), d->messages.size() + list.size() );
d->messages += list;
endInsertRows();
}
d->fetchJobs.remove( static_cast<MessageQuery*>( job ) );
job->deleteLater();
}
void PIM::MessageModel::fetchingUpdatesDone( PIM::Job * job )
{
Q_ASSERT( d->updateJobs.contains( static_cast<MessageQuery*>( job ) ) );
if ( job->error() ) {
// TODO
kWarning() << k_funcinfo << "Updating changed messages failed!" << endl;
} else {
Message::List list = static_cast<MessageQuery*>( job )->messages();
foreach ( Message* msg, list ) {
// ### *slow*
for ( int i = 0; i < d->messages.size(); ++i ) {
if ( d->messages.at( i )->reference() == msg->reference() ) {
delete d->messages.at( i );
d->messages.replace( i, msg );
emit dataChanged( index( i, 0 ), index( i, columnCount() ) );
break;
}
}
}
}
d->updateJobs.remove( static_cast<MessageQuery*>( job ) );
job->deleteLater();
}
void PIM::MessageModel::messagesChanged( const DataReference::List & references )
{
// TODO: build query based on the reference list
QString query;
MessageQuery* job = new MessageQuery( query );
connect( job, SIGNAL( done( PIM::Job* ) ), SLOT( fetchingUpdatesDone( PIM::Job* job ) ) );
job->start();
d->updateJobs.append( job );
}
void PIM::MessageModel::messagesAdded( const DataReference::List & references )
{
// TODO: build query based on the reference list
QString query;
MessageQuery* job = new MessageQuery( query );
connect( job, SIGNAL( done( PIM::Job* ) ), SLOT( fetchingNewDone( PIM::Job* job ) ) );
job->start();
d->fetchJobs.append( job );
}
void PIM::MessageModel::messagesRemoved( const DataReference::List & references )
{
foreach ( DataReference ref, references ) {
// ### *slow*
int index = -1;
for ( int i = 0; i < d->messages.size(); ++i ) {
if ( d->messages.at( i )->reference() == ref ) {
index = i;
break;
}
}
if ( index < 0 )
continue;
beginRemoveRows( QModelIndex(), index, index );
Message* msg = d->messages.at( index );
d->messages.removeAt( index );
delete msg;
endRemoveRows();
}
}
#include "messagemodel.moc"
/*
Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>
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.
*/
#ifndef PIM_MESSAGEMODEL_H
#define PIM_MESSAGEMODEL_H
#include <libakonadi/job.h>
#include <QAbstractTableModel>
namespace PIM {
class Job;
/**
A flat self-updating message model.
*/
class MessageModel : public QAbstractTableModel
{
Q_OBJECT
public:
/**
Column types.
*/
enum Column {
Subject, /**< Subject column. */
Sender, /**< Sender column. */
Receiver, /**< Receiver column. */
Date, /**< Date column. */
Size /**< Size column. */
};
/**
Creates a new message model.
@param parent The parent object.
*/
MessageModel( QObject* parent = 0 );
/**
Deletes the message model.
*/
virtual ~MessageModel();
/**
Reimplemented from QAbstractItemModel.
*/
virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const;
/**
Reimplemented from QAbstractItemModel.
*/
virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const;
/**
Reimplemented from QAbstractItemModel.
*/
virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const;
/**
Reimplemented from QAbstractItemModel.
*/
virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
/**
Sets the query that represents the model content. If the query has
changed, the model is resetted and a new message listing is requested
from the storage backend.
*/
void setQuery( const QString &query );
private slots:
/**
Connected to the message query job which does a complete listing
*/
void listingDone( PIM::Job* job );
/**
Connected to message queries that handle newly added messages.
*/
void fetchingNewDone( PIM::Job* job );
/**
Connected to message queries that handle changed messages.
*/
void fetchingUpdatesDone( PIM::Job* job );
/**
Connected to the monitor job.
*/
void messagesChanged( const DataReference::List &references );
/**
Connected to the monitor job.
*/
void messagesAdded( const DataReference::List &references );
/**
Connected to the monitor job.
*/
void messagesRemoved( const DataReference::List &references );
private:
class Private;
Private* d;
};
}
#endif
/*
Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>
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 "messagemonitor.h"
using namespace PIM;
class MessageMonitor::Private
{
public:
QString query;
};
PIM::MessageMonitor::MessageMonitor( const QString & query ) :
Job(),
d( new Private() )
{
d->query = query;
}
PIM::MessageMonitor::~MessageMonitor( )
{
delete d;
}
void PIM::MessageMonitor::doStart( )
{
// TODO
}
#include "messagemonitor.moc"
/*
Copyright (c) 2006 Volker Krause <volker.krause@rwth-aachen.de>
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.
*/
#ifndef PIM_MESSAGEMONITOR_H
#define PIM_MESSAGEMONITOR_H
#include <libakonadi/job.h>
namespace PIM {
/**
Monitors a set of messages that match a given query and emits signals if
these messages are changed or removed or new messages that match the query
are added to the storage backend.
*/