kde-playground/kdepim-runtime/resources/imap/imapidlemanager.cpp
2015-04-14 22:08:21 +00:00

185 lines
5.9 KiB
C++

/*
Copyright (c) 2007 Till Adam <adam@kde.org>
Copyright (C) 2008 Omat Holding B.V. <info@omat.nl>
Copyright (C) 2009 Kevin Ottens <ervin@kde.org>
Copyright (c) 2010 Klarälvdalens Datakonsult AB,
a KDAB Group company <info@kdab.com>
Author: Kevin Ottens <kevin@kdab.com>
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 "imapidlemanager.h"
#include <KDE/KDebug>
#include <kimap/idlejob.h>
#include <kimap/selectjob.h>
#include <kimap/session.h>
#include <QtCore/QTimer>
#include "imapresource.h"
#include "sessionpool.h"
ImapIdleManager::ImapIdleManager( ResourceStateInterface::Ptr state,
SessionPool *pool, ImapResourceBase *parent )
: QObject( parent ), m_sessionRequestId( 0 ), m_pool( pool ), m_session( 0 ),
m_idle( 0 ), m_resource( parent ), m_state( state ),
m_lastMessageCount( -1 ), m_lastRecentCount( -1 )
{
connect( pool, SIGNAL(sessionRequestDone(qint64,KIMAP::Session*,int,QString)),
this, SLOT(onSessionRequestDone(qint64,KIMAP::Session*,int,QString)) );
m_sessionRequestId = m_pool->requestSession();
}
ImapIdleManager::~ImapIdleManager()
{
stop();
if ( m_pool ) {
if ( m_sessionRequestId ) {
m_pool->cancelSessionRequest( m_sessionRequestId );
}
if ( m_session ) {
m_pool->releaseSession( m_session );
}
}
}
void ImapIdleManager::stop()
{
if ( m_idle ) {
m_idle->stop();
disconnect(m_idle, 0, this, 0);
m_idle = 0;
}
if ( m_pool ) {
disconnect(m_pool, 0, this, 0);
}
}
KIMAP::Session *ImapIdleManager::session() const
{
return m_session;
}
void ImapIdleManager::reconnect()
{
kDebug() << "attempting to reconnect IDLE session";
if ( m_session == 0 && m_pool->isConnected() && m_sessionRequestId == 0 )
m_sessionRequestId = m_pool->requestSession();
}
void ImapIdleManager::onSessionRequestDone( qint64 requestId, KIMAP::Session *session,
int errorCode, const QString &/*errorString*/ )
{
if ( requestId!=m_sessionRequestId || session==0 || errorCode!=SessionPool::NoError ) {
return;
}
m_session = session;
m_sessionRequestId = 0;
connect( m_pool, SIGNAL(connectionLost(KIMAP::Session*)),
this, SLOT(onConnectionLost(KIMAP::Session*)) );
connect( m_pool, SIGNAL(disconnectDone()),
this, SLOT(onPoolDisconnect()) );
KIMAP::SelectJob *select = new KIMAP::SelectJob( m_session );
select->setMailBox( m_state->mailBoxForCollection( m_state->collection() ) );
connect( select, SIGNAL(result(KJob*)),
this, SLOT(onSelectDone(KJob*)) );
select->start();
m_idle = new KIMAP::IdleJob( m_session );
connect( m_idle, SIGNAL(mailBoxStats(KIMAP::IdleJob*,QString,int,int)),
this, SLOT(onStatsReceived(KIMAP::IdleJob*,QString,int,int)) );
connect( m_idle, SIGNAL(mailBoxMessageFlagsChanged(KIMAP::IdleJob*,qint64)),
this, SLOT(onFlagsChanged(KIMAP::IdleJob*)) );
connect( m_idle, SIGNAL(result(KJob*)),
this, SLOT(onIdleStopped()) );
m_idle->start();
}
void ImapIdleManager::onConnectionLost( KIMAP::Session *session )
{
if ( session == m_session ) {
// Our session becomes invalid, so get ride of
// the pointer, we don't need to release it once the
// task is done
m_session = 0;
QMetaObject::invokeMethod( this, "reconnect", Qt::QueuedConnection );
}
}
void ImapIdleManager::onPoolDisconnect()
{
// All the sessions in the pool we used changed,
// so get ride of the pointer, we don't need to
// release our session anymore
m_pool = 0;
}
void ImapIdleManager::onSelectDone( KJob *job )
{
KIMAP::SelectJob *select = static_cast<KIMAP::SelectJob*>( job );
m_lastMessageCount = select->messageCount();
m_lastRecentCount = select->recentCount();
}
void ImapIdleManager::onIdleStopped()
{
kDebug( 5327 ) << "IDLE dropped maybe we should reconnect?";
m_idle = 0;
if ( m_session ) {
kDebug( 5327 ) << "Restarting the IDLE session!";
m_idle = new KIMAP::IdleJob( m_session );
connect( m_idle, SIGNAL(mailBoxStats(KIMAP::IdleJob*,QString,int,int)),
this, SLOT(onStatsReceived(KIMAP::IdleJob*,QString,int,int)) );
connect( m_idle, SIGNAL(result(KJob*)),
this, SLOT(onIdleStopped()) );
m_idle->start();
}
}
void ImapIdleManager::onStatsReceived(KIMAP::IdleJob *job, const QString &mailBox,
int messageCount, int recentCount)
{
kDebug( 5327 ) << "IDLE stats received:" << job << mailBox << messageCount << recentCount;
kDebug( 5327 ) << "Cached information:" << m_state->collection().remoteId() << m_state->collection().id()
<< m_lastMessageCount << m_lastRecentCount;
// It seems we're not in sync with the cache, resync is needed
if ( messageCount!=m_lastMessageCount || recentCount!=m_lastRecentCount ) {
m_lastMessageCount = messageCount;
m_lastRecentCount = recentCount;
kDebug( 5327 ) << "Resync needed for" << mailBox << m_state->collection().id();
m_resource->synchronizeCollection( m_state->collection().id() );
}
}
void ImapIdleManager::onFlagsChanged( KIMAP::IdleJob *job )
{
kDebug( 5327 ) << "IDLE flags changed in" << m_session->selectedMailBox();
m_resource->synchronizeCollection( m_state->collection().id() );
}