2
Copyright (c) 2007 Till Adam <adam@kde.org>
4
This library is free software; you can redistribute it and/or modify it
5
under the terms of the GNU Library General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or (at your
7
option) any later version.
9
This library is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12
License for more details.
14
You should have received a copy of the GNU Library General Public License
15
along with this library; see the file COPYING.LIB. If not, write to the
16
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
#include "maildirresource.h"
22
#include "settingsadaptor.h"
23
#include "configdialog.h"
25
#include <QtCore/QDir>
26
#include <QtDBus/QDBusConnection>
28
#include <akonadi/kmime/messageparts.h>
29
#include <akonadi/changerecorder.h>
30
#include <akonadi/itemfetchscope.h>
33
#include <kfiledialog.h>
36
#include <KWindowSystem>
38
#include "libmaildir/maildir.h"
40
#include <kmime/kmime_message.h>
42
#include <boost/shared_ptr.hpp>
43
typedef boost::shared_ptr<KMime::Message> MessagePtr;
45
using namespace Akonadi;
48
static QString maildirPath( const QString &remoteId )
50
const int pos = remoteId.lastIndexOf( QDir::separator() );
52
return remoteId.left( pos );
56
static QString maildirId( const QString &remoteId )
58
const int pos = remoteId.lastIndexOf( QDir::separator() );
60
return remoteId.mid( pos + 1 );
64
static QString maildirSubdirPath( const QString &parentPath, const QString &subName )
66
QString basePath = maildirPath( parentPath );
67
if ( !basePath.endsWith( QDir::separator() ) )
68
basePath += QDir::separator();
69
const QString name = maildirId( parentPath );
70
return basePath + '.' + name + ".directory" + QDir::separator() + subName;
73
MaildirResource::MaildirResource( const QString &id )
76
new SettingsAdaptor( Settings::self() );
77
QDBusConnection::sessionBus().registerObject( QLatin1String( "/Settings" ),
78
Settings::self(), QDBusConnection::ExportAdaptors );
79
connect( this, SIGNAL(reloadConfiguration()), SLOT(ensureDirExists()) );
81
// We need to enable this here, otherwise we neither get the remote ID of the
82
// parent collection when a collection changes, nor the full item when an item
84
changeRecorder()->fetchCollection( true );
85
changeRecorder()->itemFetchScope().fetchFullPayload( true );
88
MaildirResource::~ MaildirResource()
92
bool MaildirResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArray> &parts )
96
const QString dir = maildirPath( item.remoteId() );
97
const QString entry = maildirId( item.remoteId() );
100
if ( !md.isValid() ) {
101
cancelTask( i18n( "Unable to fetch item: The maildir folder \"%1\" is not valid.",
106
const QByteArray data = md.readEntry( entry );
107
KMime::Message *mail = new KMime::Message();
108
mail->setContent( KMime::CRLFtoLF( data ) );
112
i.setPayload( MessagePtr( mail ) );
117
void MaildirResource::aboutToQuit()
119
// The settings may not have been saved if e.g. they have been modified via
120
// DBus instead of the config dialog.
121
Settings::self()->writeConfig();
122
kDebug( 5254 ) << "Implement me!" ;
125
void MaildirResource::configure( WId windowId )
129
KWindowSystem::setMainWindow( &dlg, windowId );
133
synchronizeCollectionTree();
136
void MaildirResource::itemAdded( const Akonadi::Item & item, const Akonadi::Collection& collection )
138
Maildir dir( collection.remoteId() );
140
if ( Settings::readOnly() || !dir.isValid( errMsg ) ) {
141
cancelTask( errMsg );
144
// we can only deal with mail
145
if ( item.mimeType() != "message/rfc822" ) {
146
cancelTask( i18n("Only email messages can be added to the Maildir resource.") );
149
const MessagePtr mail = item.payload<MessagePtr>();
150
const QString rid = collection.remoteId() + QDir::separator() + dir.addEntry( mail->encodedContent() );
152
i.setRemoteId( rid );
153
changeCommitted( i );
156
void MaildirResource::itemChanged( const Akonadi::Item& item, const QSet<QByteArray>& parts )
158
if ( Settings::self()->readOnly() || !parts.contains( MessagePart::Body ) ) {
163
const QString path = maildirPath( item.remoteId() );
164
const QString entry = maildirId( item.remoteId() );
168
if ( !dir.isValid( errMsg ) ) {
169
cancelTask( errMsg );
172
// we can only deal with mail
173
if ( item.mimeType() != "message/rfc822" ) {
174
cancelTask( i18n("Only email messages can be added to the Maildir resource.") );
177
const MessagePtr mail = item.payload<MessagePtr>();
178
dir.writeEntry( entry, mail->encodedContent() );
179
changeCommitted( item );
182
void MaildirResource::itemRemoved(const Akonadi::Item & item)
184
if ( !Settings::self()->readOnly() ) {
185
const QString path = maildirPath( item.remoteId() );
186
const QString entry = maildirId( item.remoteId() );
190
if ( !dir.isValid( errMsg ) ) {
191
cancelTask( errMsg );
194
if ( !dir.removeEntry( entry ) ) {
195
emit error( i18n("Failed to delete item: %1", item.remoteId()) );
201
Collection::List listRecursive( const Collection &root, const Maildir &dir )
203
Collection::List list;
204
const QStringList mimeTypes = QStringList() << "message/rfc822" << Collection::mimeType();
205
foreach ( const QString &sub, dir.subFolderList() ) {
206
const QString path = maildirSubdirPath( root.remoteId(), sub );
212
c.setRemoteId( path );
214
c.setContentMimeTypes( mimeTypes );
216
list += listRecursive( c, md );
221
void MaildirResource::retrieveCollections()
223
Maildir dir( Settings::self()->path() );
225
if ( !dir.isValid( errMsg ) ) {
226
emit error( errMsg );
227
collectionsRetrieved( Collection::List() );
231
root.setParent( Collection::root() );
232
root.setRemoteId( Settings::self()->path() );
233
root.setName( name() );
234
QStringList mimeTypes;
235
mimeTypes << "message/rfc822" << Collection::mimeType();
236
root.setContentMimeTypes( mimeTypes );
238
Collection::List list;
240
list += listRecursive( root, dir );
241
collectionsRetrieved( list );
244
void MaildirResource::retrieveItems( const Akonadi::Collection & col )
246
Maildir md( col.remoteId() );
247
if ( !md.isValid() ) {
248
emit error( i18n("Invalid maildir: %1", col.remoteId() ) );
249
itemsRetrieved( Item::List() );
252
QStringList entryList = md.entryList();
255
foreach ( const QString &entry, entryList ) {
256
const QString rid = col.remoteId() + QDir::separator() + entry;
258
item.setRemoteId( rid );
259
item.setMimeType( "message/rfc822" );
260
item.setSize( md.size( entry ) );
261
KMime::Message *msg = new KMime::Message;
262
msg->setHead( KMime::CRLFtoLF( md.readEntryHeaders( entry ) ) );
264
item.setPayload( MessagePtr( msg ) );
267
itemsRetrieved( items );
270
void MaildirResource::collectionAdded(const Collection & collection, const Collection &parent)
272
Maildir md( parent.remoteId() );
273
kDebug( 5254 ) << md.subFolderList() << md.entryList();
274
if ( Settings::self()->readOnly() || !md.isValid() ) {
280
QString newFolderPath = md.addSubFolder( collection.name() );
281
if ( newFolderPath.isEmpty() ) {
286
kDebug( 5254 ) << md.subFolderList() << md.entryList();
288
Collection col = collection;
289
col.setRemoteId( newFolderPath );
290
changeCommitted( col );
295
void MaildirResource::collectionChanged(const Collection & collection)
297
kDebug( 5254 ) << "Implement me!";
298
AgentBase::Observer::collectionChanged( collection );
301
void MaildirResource::collectionRemoved( const Akonadi::Collection &collection )
303
kDebug( 5254 ) << "Implement me!";
304
AgentBase::Observer::collectionRemoved( collection );
307
void MaildirResource::ensureDirExists()
309
Maildir root( Settings::self()->path() );
310
if ( !root.isValid() ) {
311
if ( !root.create() )
312
emit status( Broken, i18n( "Unable to create maildir '%1'." ).arg( Settings::self()->path() ) );
317
AKONADI_RESOURCE_MAIN( MaildirResource )
319
#include "maildirresource.moc"