23 #include "agentbase.h"
24 #include "agentbase_p.h"
26 #include "agentmanager.h"
27 #include "changerecorder.h"
28 #include "controladaptor.h"
29 #include "dbusconnectionpool.h"
30 #include "itemfetchjob.h"
31 #include "kdepimlibs-version.h"
32 #include "monitor_p.h"
33 #include "servermanager_p.h"
35 #include "session_p.h"
36 #include "statusadaptor.h"
37 #include "xdgbasedirs_p.h"
39 #include <kaboutdata.h>
40 #include <kcmdlineargs.h>
43 #include <kstandarddirs.h>
45 #include <Solid/PowerManagement>
47 #include <QtCore/QDir>
48 #include <QtCore/QSettings>
49 #include <QtCore/QTimer>
50 #include <QtDBus/QtDBus>
51 #include <QtGui/QApplication>
59 using namespace Akonadi;
74 Q_UNUSED( collection );
75 if ( sAgentBase != 0 )
82 Q_UNUSED( partIdentifiers );
83 if ( sAgentBase != 0 )
90 if ( sAgentBase != 0 )
96 Q_UNUSED( collection );
98 if ( sAgentBase != 0 )
104 Q_UNUSED( collection );
105 if ( sAgentBase != 0 )
111 Q_UNUSED( collection );
112 if ( sAgentBase != 0 )
121 if ( sAgentBase != 0 )
128 Q_UNUSED( collection );
129 if ( sAgentBase != 0 ) {
131 QObject::disconnect( sAgentBase->
changeRecorder(), SIGNAL(itemLinked(Akonadi::Item,Akonadi::Collection)),
132 sAgentBase->d_ptr, SLOT(itemLinked(Akonadi::Item,Akonadi::Collection)) );
140 Q_UNUSED( collection );
141 if ( sAgentBase != 0 ) {
143 QObject::disconnect( sAgentBase->
changeRecorder(), SIGNAL(itemUnlinked(Akonadi::Item,Akonadi::Collection)),
144 sAgentBase->d_ptr, SLOT(itemUnlinked(Akonadi::Item,Akonadi::Collection)) );
151 Q_UNUSED( collection );
154 if ( sAgentBase != 0 )
160 Q_UNUSED( changedAttributes );
161 collectionChanged( collection );
166 AgentBasePrivate::AgentBasePrivate(
AgentBase *parent )
168 mDBusConnection( QString() ),
171 mNeedsNetwork( false ),
177 QThread::currentThread()->setPriority(QThread::LowPriority);
179 Internal::setClientType( Internal::Agent );
182 AgentBasePrivate::~AgentBasePrivate()
184 mChangeRecorder->setConfig( 0 );
195 SessionPrivate::createDefaultSession( mId.toLatin1() );
197 if ( QThread::currentThread() != QCoreApplication::instance()->thread() ) {
198 mDBusConnection = QDBusConnection::connectToBus( QDBusConnection::SessionBus, q->identifier() );
199 Q_ASSERT( mDBusConnection.isConnected() );
202 mTracer =
new org::freedesktop::Akonadi::Tracer( QLatin1String(
"org.freedesktop.Akonadi" ),
203 QLatin1String(
"/tracing" ),
204 DBusConnectionPool::threadConnection(), q );
206 new Akonadi__ControlAdaptor( q );
207 new Akonadi__StatusAdaptor( q );
208 if ( !DBusConnectionPool::threadConnection().registerObject( QLatin1String(
"/" ), q, QDBusConnection::ExportAdaptors ) )
209 q->error( QString::fromLatin1(
"Unable to register object at dbus: %1" ).arg( DBusConnectionPool::threadConnection().lastError().message() ) );
211 mSettings =
new QSettings( QString::fromLatin1(
"%1/agent_config_%2" ).arg( XdgBaseDirs::saveDir(
"config", QLatin1String(
"akonadi" ) ), mId ), QSettings::IniFormat );
214 mChangeRecorder->ignoreSession( Session::defaultSession() );
215 mChangeRecorder->itemFetchScope().setCacheOnly(
true );
216 mChangeRecorder->setConfig( mSettings );
218 mOnline = mSettings->value( QLatin1String(
"Agent/Online" ),
true ).toBool();
221 mStatusMessage = defaultReadyMessage();
223 mName = mSettings->value( QLatin1String(
"Agent/Name" ) ).toString();
224 if ( mName.isEmpty() ) {
225 mName = mSettings->value( QLatin1String(
"Resource/Name" ) ).toString();
226 if ( !mName.isEmpty() ) {
227 mSettings->remove( QLatin1String(
"Resource/Name" ) );
228 mSettings->setValue( QLatin1String(
"Agent/Name" ), mName );
232 connect( mChangeRecorder, SIGNAL(itemAdded(Akonadi::Item,Akonadi::Collection)),
233 SLOT(itemAdded(Akonadi::Item,Akonadi::Collection)) );
234 connect( mChangeRecorder, SIGNAL(itemChanged(Akonadi::Item,QSet<QByteArray>)),
235 SLOT(itemChanged(Akonadi::Item,QSet<QByteArray>)) );
236 connect( mChangeRecorder, SIGNAL(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)),
237 SLOT(itemMoved(Akonadi::Item,Akonadi::Collection,Akonadi::Collection)) );
238 connect( mChangeRecorder, SIGNAL(itemRemoved(Akonadi::Item)),
239 SLOT(itemRemoved(Akonadi::Item)) );
240 connect( mChangeRecorder, SIGNAL(collectionAdded(Akonadi::Collection,Akonadi::Collection)),
241 SLOT(collectionAdded(Akonadi::Collection,Akonadi::Collection)) );
242 connect( mChangeRecorder, SIGNAL(itemLinked(Akonadi::Item,Akonadi::Collection)),
243 SLOT(itemLinked(Akonadi::Item,Akonadi::Collection)) );
244 connect( mChangeRecorder, SIGNAL(itemUnlinked(Akonadi::Item,Akonadi::Collection)),
245 SLOT(itemUnlinked(Akonadi::Item,Akonadi::Collection)) );
246 connect( mChangeRecorder, SIGNAL(collectionChanged(Akonadi::Collection)),
247 SLOT(collectionChanged(Akonadi::Collection)) );
248 connect( mChangeRecorder, SIGNAL(collectionChanged(Akonadi::Collection,QSet<QByteArray>)),
249 SLOT(collectionChanged(Akonadi::Collection,QSet<QByteArray>)) );
250 connect( mChangeRecorder, SIGNAL(collectionMoved(Akonadi::Collection,Akonadi::Collection,Akonadi::Collection)),
251 SLOT(collectionMoved(Akonadi::Collection,Akonadi::Collection,Akonadi::Collection)) );
252 connect( mChangeRecorder, SIGNAL(collectionRemoved(Akonadi::Collection)),
253 SLOT(collectionRemoved(Akonadi::Collection)) );
254 connect( mChangeRecorder, SIGNAL(collectionSubscribed(Akonadi::Collection,Akonadi::Collection)),
255 SLOT(collectionSubscribed(Akonadi::Collection,Akonadi::Collection)) );
256 connect( mChangeRecorder, SIGNAL(collectionUnsubscribed(Akonadi::Collection)),
257 SLOT(collectionUnsubscribed(Akonadi::Collection)) );
259 connect( q, SIGNAL(
status(
int,QString)), q, SLOT(slotStatus(
int,QString)) );
260 connect( q, SIGNAL(
percent(
int)), q, SLOT(slotPercent(
int)) );
261 connect( q, SIGNAL(
warning(QString)), q, SLOT(slotWarning(QString)) );
262 connect( q, SIGNAL(
error(QString)), q, SLOT(slotError(QString)) );
264 connect( Solid::PowerManagement::notifier(), SIGNAL(resumingFromSuspend()), q, SLOT(slotResumedFromSuspend()) );
269 if ( QThread::currentThread() == QCoreApplication::instance()->thread() )
270 KGlobal::setAllowQuit(
true );
274 if ( KApplication::kApplication() )
275 KApplication::kApplication()->disableSessionManagement();
281 QTimer::singleShot( 0, q, SLOT(delayedInit()) );
284 void AgentBasePrivate::delayedInit()
287 const QString serviceId = QLatin1String(
"org.freedesktop.Akonadi.Agent." ) + mId;
288 if ( !DBusConnectionPool::threadConnection().registerService( serviceId ) )
289 kFatal() <<
"Unable to register service" << serviceId <<
"at dbus:" << DBusConnectionPool::threadConnection().lastError().message();
290 q->setOnline( mOnline );
293 void AgentBasePrivate::setProgramName()
296 QString programName = mResourceTypeName;
297 if ( !mName.isEmpty() ) {
298 programName = i18nc(
"Name and type of Akonadi resource",
"%1 of type %2", mName, mResourceTypeName ) ;
300 const_cast<KAboutData*
>( KGlobal::mainComponent().aboutData() )->setProgramName( ki18n( programName.toUtf8() ) );
303 void AgentBasePrivate::itemAdded(
const Akonadi::Item &item,
const Akonadi::Collection &collection )
305 if ( mObserver != 0 )
306 mObserver->itemAdded( item, collection );
309 void AgentBasePrivate::itemChanged(
const Akonadi::Item &item,
const QSet<QByteArray> &partIdentifiers )
311 if ( mObserver != 0 )
312 mObserver->itemChanged( item, partIdentifiers );
315 void AgentBasePrivate::itemMoved(
const Akonadi::Item &item,
const Akonadi::Collection &source,
const Akonadi::Collection &dest )
320 if ( !source.resource().isEmpty() && !dest.resource().isEmpty() ) {
321 if ( source.resource() != dest.resource() ) {
322 if ( source.resource() == q_ptr->identifier() ) {
323 Akonadi::Item i( item );
324 i.setParentCollection( source );
325 mObserver->itemRemoved( i );
327 else if ( dest.resource() == q_ptr->identifier() )
328 mObserver->itemAdded( item, dest );
329 else if ( observer2 )
330 observer2->
itemMoved( item, source, dest );
339 observer2->
itemMoved( item, source, dest );
344 mObserver->itemAdded( item, dest );
350 void AgentBasePrivate::itemRemoved(
const Akonadi::Item &item )
352 if ( mObserver != 0 )
353 mObserver->itemRemoved( item );
356 void AgentBasePrivate::itemLinked(
const Akonadi::Item &item,
const Akonadi::Collection &collection )
365 void AgentBasePrivate::itemUnlinked(
const Akonadi::Item &item,
const Akonadi::Collection &collection )
374 void AgentBasePrivate::collectionAdded(
const Akonadi::Collection &collection,
const Akonadi::Collection &parent )
376 if ( mObserver != 0 )
377 mObserver->collectionAdded( collection, parent );
380 void AgentBasePrivate::collectionChanged(
const Akonadi::Collection &collection )
383 if ( mObserver != 0 && observer2 == 0 )
387 void AgentBasePrivate::collectionChanged(
const Akonadi::Collection &collection,
const QSet<QByteArray> &changedAttributes )
390 if ( observer2 != 0 )
394 void AgentBasePrivate::collectionMoved(
const Akonadi::Collection &collection,
const Akonadi::Collection &source,
const Akonadi::Collection &dest )
399 }
else if ( mObserver ) {
403 mObserver->collectionAdded( collection, dest );
409 void AgentBasePrivate::collectionRemoved(
const Akonadi::Collection &collection )
411 if ( mObserver != 0 )
412 mObserver->collectionRemoved( collection );
415 void AgentBasePrivate::collectionSubscribed(
const Akonadi::Collection &collection,
const Akonadi::Collection &parent )
417 Q_UNUSED( collection );
422 void AgentBasePrivate::collectionUnsubscribed(
const Akonadi::Collection &collection )
424 Q_UNUSED( collection );
430 mChangeRecorder->changeProcessed();
431 QTimer::singleShot( 0, mChangeRecorder, SLOT(replayNext()) );
434 void AgentBasePrivate::slotStatus(
int status,
const QString &message )
436 mStatusMessage = message;
441 if ( mStatusMessage.isEmpty() )
442 mStatusMessage = defaultReadyMessage();
447 if ( mStatusMessage.isEmpty() )
448 mStatusMessage = defaultSyncingMessage();
453 if ( mStatusMessage.isEmpty() )
454 mStatusMessage = defaultErrorMessage();
459 Q_ASSERT( !
"Unknown status passed" );
464 void AgentBasePrivate::slotPercent(
int progress )
469 void AgentBasePrivate::slotWarning(
const QString& message )
471 mTracer->warning( QString::fromLatin1(
"AgentBase(%1)" ).arg( mId ), message );
474 void AgentBasePrivate::slotError(
const QString& message )
476 mTracer->error( QString::fromLatin1(
"AgentBase(%1)" ).arg( mId ), message );
479 void AgentBasePrivate::slotNetworkStatusChange( Solid::Networking::Status stat )
482 q->setOnline( stat == Solid::Networking::Unknown || stat == Solid::Networking::Connected );
485 void AgentBasePrivate::slotResumedFromSuspend()
488 slotNetworkStatusChange( Solid::Networking::status() );
512 QString AgentBase::parseArguments(
int argc,
char **argv )
516 kDebug() <<
"Not enough arguments passed...";
520 for (
int i = 1; i < argc - 1; ++i ) {
521 if ( QLatin1String( argv[ i ] ) == QLatin1String(
"--identifier" ) )
522 identifier = QLatin1String( argv[ i + 1 ] );
525 if ( identifier.isEmpty() ) {
526 kDebug() <<
"Identifier argument missing";
530 const QFileInfo fi( QString::fromLocal8Bit( argv[0] ) );
532 const QByteArray catalog = fi.baseName().toLatin1();
534 KCmdLineArgs::init( argc, argv, identifier.toLatin1(), catalog, ki18n(
"Akonadi Agent" ), KDEPIMLIBS_VERSION,
535 ki18n(
"Akonadi Agent" ) );
537 KCmdLineOptions options;
538 options.add(
"identifier <argument>", ki18n(
"Agent identifier" ) );
539 KCmdLineArgs::addCmdLineOptions( options );
548 QApplication::setQuitOnLastWindowClosed(
false );
549 KGlobal::locale()->insertCatalog( QLatin1String(
"libakonadi" ) );
550 int rv = kapp->exec();
559 return d->mStatusCode;
566 return d->mStatusMessage;
580 return d->mProgressMessage;
593 d->mNeedsNetwork = needsNetwork;
595 if ( d->mNeedsNetwork ) {
596 connect( Solid::Networking::notifier()
597 , SIGNAL(statusChanged(Solid::Networking::Status))
598 ,
this, SLOT(slotNetworkStatusChange(Solid::Networking::Status))
599 , Qt::UniqueConnection );
602 disconnect( Solid::Networking::notifier(), 0, 0, 0 );
612 const QString newMessage = d->defaultReadyMessage();
614 emit
status( d->mStatusCode, newMessage );
616 d->mSettings->setValue( QLatin1String(
"Agent/Online" ), state );
628 Q_UNUSED( windowId );
632 #ifdef Q_OS_WIN //krazy:exclude=cpp
635 configure( reinterpret_cast<WId>( windowId ) );
641 const bool registered = DBusConnectionPool::threadConnection().interface()->isServiceRegistered( QLatin1String(
"org.freedesktop.akonaditray" ) );
645 QDBusInterface dbus( QLatin1String(
"org.freedesktop.akonaditray" ), QLatin1String(
"/Actions" ),
646 QLatin1String(
"org.freedesktop.Akonadi.Tray" ) );
647 const QDBusMessage reply = dbus.call( QLatin1String(
"getWinId" ) );
649 if ( reply.type() == QDBusMessage::ErrorMessage )
652 const WId winid = (WId)reply.arguments().at( 0 ).toLongLong();
657 void AgentBase::quit()
662 if ( d->mSettings ) {
664 d->mSettings->sync();
679 d->mChangeRecorder->blockSignals(
true );
683 const QString fileName = d->mSettings->fileName();
695 QFile::remove( fileName );
700 QFile::remove( fileName + QLatin1String(
"_changes.dat" ) );
705 QString configFile = KStandardDirs::locateLocal(
"config",
config()->name() );
706 QFile::remove( configFile );
714 d_ptr->mObserver = observer;
725 if ( name == d->mName )
731 if ( d->mName.isEmpty() || d->mName == d->mId ) {
732 d->mSettings->remove( QLatin1String(
"Resource/Name" ) );
733 d->mSettings->remove( QLatin1String(
"Agent/Name" ) );
735 d->mSettings->setValue( QLatin1String(
"Agent/Name" ), d->mName );
737 d->mSettings->sync();
747 if ( d->mName.isEmpty() )
756 d->changeProcessed();
761 return d_ptr->mChangeRecorder;
766 if ( QCoreApplication::instance()->thread() == QThread::currentThread() )
772 void AgentBase::abort()
777 void AgentBase::reconfigure()
782 extern QThreadStorage<KComponentData*> s_agentComponentDatas;
786 if ( QThread::currentThread() == QCoreApplication::instance()->thread() ) {
787 if ( s_agentComponentDatas.hasLocalData() )
788 return *(s_agentComponentDatas.localData());
790 return KGlobal::mainComponent();
793 Q_ASSERT( s_agentComponentDatas.hasLocalData() );
794 return *(s_agentComponentDatas.localData());
797 #include "agentbase.moc"
798 #include "agentbase_p.moc"