akonadi
job.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "job.h"
00023 #include "job_p.h"
00024 #include "imapparser_p.h"
00025 #include "session.h"
00026 #include "session_p.h"
00027
00028 #include <kdebug.h>
00029 #include <klocale.h>
00030
00031 #include <QtCore/QEventLoop>
00032 #include <QtCore/QTimer>
00033 #include <QtCore/QTextStream>
00034 #include <QtNetwork/QHostAddress>
00035 #include <QtNetwork/QTcpSocket>
00036
00037 using namespace Akonadi;
00038
00039
00040 void JobPrivate::handleResponse( const QByteArray & tag, const QByteArray & data )
00041 {
00042 Q_Q( Job );
00043
00044 if ( mCurrentSubJob ) {
00045 mCurrentSubJob->d_ptr->handleResponse( tag, data );
00046 return;
00047 }
00048
00049 if ( tag == mTag ) {
00050 if ( data.startsWith( "NO " ) || data.startsWith( "BAD " ) ) {
00051 QString msg = QString::fromUtf8( data );
00052
00053 msg.remove( 0, msg.startsWith( QLatin1String( "NO " ) ) ? 3 : 4 );
00054
00055 if ( msg.endsWith( QLatin1String( "\r\n" ) ) )
00056 msg.chop( 2 );
00057
00058 q->setError( Job::Unknown );
00059 q->setErrorText( msg );
00060 q->emitResult();
00061 return;
00062 } else if ( data.startsWith( "OK" ) ) {
00063 q->emitResult();
00064 return;
00065 }
00066 }
00067
00068 q->doHandleResponse( tag, data );
00069 }
00070
00071 void JobPrivate::init( QObject *parent )
00072 {
00073 Q_Q( Job );
00074
00075 mParentJob = dynamic_cast<Job*>( parent );
00076 mSession = dynamic_cast<Session*>( parent );
00077
00078 if ( !mSession ) {
00079 if ( !mParentJob )
00080 mSession = Session::defaultSession();
00081 else
00082 mSession = mParentJob->d_ptr->mSession;
00083 }
00084
00085 if ( !mParentJob )
00086 mSession->d->addJob( q );
00087 else
00088 mParentJob->addSubjob( q );
00089 }
00090
00091 void JobPrivate::startQueued()
00092 {
00093 Q_Q( Job );
00094 mStarted = true;
00095
00096 emit q->aboutToStart( q );
00097 q->doStart();
00098 QTimer::singleShot( 0, q, SLOT(startNext()) );
00099 }
00100
00101 void JobPrivate::lostConnection()
00102 {
00103 Q_Q( Job );
00104
00105 if ( mCurrentSubJob ) {
00106 mCurrentSubJob->d_ptr->lostConnection();
00107 } else {
00108 q->setError( Job::ConnectionFailed );
00109 q->kill( KJob::EmitResult );
00110 }
00111 }
00112
00113 void JobPrivate::slotSubJobAboutToStart( Job * job )
00114 {
00115 Q_ASSERT( mCurrentSubJob == 0 );
00116 mCurrentSubJob = job;
00117 }
00118
00119 void JobPrivate::startNext()
00120 {
00121 Q_Q( Job );
00122
00123 if ( mStarted && !mCurrentSubJob && q->hasSubjobs() ) {
00124 Job *job = dynamic_cast<Akonadi::Job*>( q->subjobs().first() );
00125 Q_ASSERT( job );
00126 job->d_ptr->startQueued();
00127 }
00128 }
00129
00130 QByteArray JobPrivate::newTag( )
00131 {
00132 if ( mParentJob )
00133 mTag = mParentJob->d_ptr->newTag();
00134 else
00135 mTag = QByteArray::number( mSession->d->nextTag() );
00136 return mTag;
00137 }
00138
00139 QByteArray JobPrivate::tag() const
00140 {
00141 return mTag;
00142 }
00143
00144 void JobPrivate::writeData( const QByteArray & data )
00145 {
00146 Q_ASSERT_X( !mWriteFinished, "Job::writeData()", "Calling writeData() after emitting writeFinished()" );
00147 mSession->d->writeData( data );
00148 }
00149
00150
00151
00152 Job::Job( QObject *parent )
00153 : KCompositeJob( parent ),
00154 d_ptr( new JobPrivate( this ) )
00155 {
00156 d_ptr->init( parent );
00157 }
00158
00159 Job::Job( JobPrivate *dd, QObject *parent )
00160 : KCompositeJob( parent ),
00161 d_ptr( dd )
00162 {
00163 d_ptr->init( parent );
00164 }
00165
00166 Job::~Job()
00167 {
00168 delete d_ptr;
00169 }
00170
00171 void Job::start()
00172 {
00173 }
00174
00175 bool Job::doKill()
00176 {
00177 return true;
00178 }
00179
00180 QString Job::errorString() const
00181 {
00182 QString str;
00183 switch ( error() ) {
00184 case NoError:
00185 break;
00186 case ConnectionFailed:
00187 str = i18n( "Cannot connect to the Akonadi service." );
00188 break;
00189 case ProtocolVersionMismatch:
00190 str = i18n( "The protocol version of the Akonadi server is incompatible. Make sure you have a compatible version installed." );
00191 break;
00192 case UserCanceled:
00193 str = i18n( "User canceled operation." );
00194 break;
00195 case Unknown:
00196 default:
00197 str = i18n( "Unknown error." );
00198 break;
00199 }
00200 if ( !errorText().isEmpty() ) {
00201 str += QString::fromLatin1( " (%1)" ).arg( errorText() );
00202 }
00203 return str;
00204 }
00205
00206 bool Job::addSubjob( KJob * job )
00207 {
00208 bool rv = KCompositeJob::addSubjob( job );
00209 if ( rv ) {
00210 connect( job, SIGNAL(aboutToStart(Akonadi::Job*)), SLOT(slotSubJobAboutToStart(Akonadi::Job*)) );
00211 QTimer::singleShot( 0, this, SLOT(startNext()) );
00212 }
00213 return rv;
00214 }
00215
00216 bool Job::removeSubjob(KJob * job)
00217 {
00218 bool rv = KCompositeJob::removeSubjob( job );
00219 if ( job == d_ptr->mCurrentSubJob ) {
00220 d_ptr->mCurrentSubJob = 0;
00221 QTimer::singleShot( 0, this, SLOT(startNext()) );
00222 }
00223 return rv;
00224 }
00225
00226 void Job::doHandleResponse(const QByteArray & tag, const QByteArray & data)
00227 {
00228 kDebug( 5250 ) << "Unhandled response: " << tag << data;
00229 }
00230
00231 void Job::slotResult(KJob * job)
00232 {
00233 Q_ASSERT( job == d_ptr->mCurrentSubJob );
00234 d_ptr->mCurrentSubJob = 0;
00235 KCompositeJob::slotResult( job );
00236 if ( !job->error() )
00237 QTimer::singleShot( 0, this, SLOT(startNext()) );
00238 }
00239
00240 void Job::emitWriteFinished()
00241 {
00242 d_ptr->mWriteFinished = true;
00243 emit writeFinished( this );
00244 }
00245
00246 #include "job.moc"