mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-24 02:42:51 +00:00
322 lines
12 KiB
C++
322 lines
12 KiB
C++
/*
|
|
Copyright (c) 2008 Volker Krause <vkrause@kde.org>
|
|
|
|
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 KRESMIGRATOR_H
|
|
#define KRESMIGRATOR_H
|
|
|
|
#include "kresmigratorbase.h"
|
|
|
|
#include <akonadi/agentmanager.h>
|
|
#include <kresources/manager.h>
|
|
#include <kresources/resource.h>
|
|
#include <QFile>
|
|
|
|
#include <KConfigGroup>
|
|
#include <KDebug>
|
|
#include <KGlobal>
|
|
#include <KStandardDirs>
|
|
|
|
using namespace Akonadi;
|
|
|
|
template <typename T> class KResMigrator : public KResMigratorBase
|
|
{
|
|
public:
|
|
KResMigrator( const QString &type, const QString &bridgeType ) :
|
|
KResMigratorBase( type, bridgeType ),
|
|
mConfig( 0 ),
|
|
mManager( 0 ),
|
|
mBridgeManager( 0 ),
|
|
mClientBridgeFound( false )
|
|
{
|
|
}
|
|
|
|
virtual ~KResMigrator()
|
|
{
|
|
delete mBridgeManager;
|
|
mBridgeManager = 0;
|
|
delete mManager;
|
|
mManager = 0;
|
|
delete mConfig;
|
|
mConfig = 0;
|
|
}
|
|
|
|
void migrate()
|
|
{
|
|
const QString kresCfgFile = KStandardDirs::locateLocal( "config", QString::fromLatin1( "kresources/%1/stdrc" ).arg( mType ) );
|
|
mConfig = new KConfig( kresCfgFile );
|
|
const KConfigGroup generalGroup( mConfig, QLatin1String( "General" ) );
|
|
mUnknownTypeResources = QSet<QString>::fromList( generalGroup.readEntry( QLatin1String( "ResourceKeys" ), QStringList() ) );
|
|
|
|
mManager = new KRES::Manager<T>( mType );
|
|
mManager->readConfig();
|
|
{
|
|
ResourceIterator it = mManager->begin();
|
|
while ( it != mManager->end() ) {
|
|
mResourcesToMigrate.append( *it );
|
|
++it;
|
|
}
|
|
mIt = mResourcesToMigrate.constBegin();
|
|
}
|
|
migrateNext();
|
|
}
|
|
|
|
void migrateNext()
|
|
{
|
|
while ( mIt != mResourcesToMigrate.constEnd() ) {
|
|
mUnknownTypeResources.remove( ( *mIt )->identifier() );
|
|
if ( ( *mIt )->type() == QLatin1String("akonadi") ) {
|
|
mClientBridgeIdentifier = ( *mIt )->identifier();
|
|
mClientBridgeFound = true;
|
|
emit message( Skip, i18n( "Client-side bridge already set up." ) );
|
|
++mIt;
|
|
continue;
|
|
}
|
|
//KConfigGroup cfg( KGlobal::config(), QLatin1String("Resource ") + ( *mIt )->identifier() );
|
|
kDebug() << "migrateNext:" << ( *mIt )->identifier();
|
|
if ( migrationState( ( *mIt )->identifier() ) == None ) {
|
|
emit message( Info, i18n( "Trying to migrate '%1'...", ( *mIt )->resourceName() ) );
|
|
mPendingBridgedResources.removeAll( ( *mIt )->identifier() );
|
|
T* res = *mIt;
|
|
mCurrentKResource = res;
|
|
++mIt;
|
|
|
|
if ( res->type() == QLatin1String("imap") ) {
|
|
createKolabResource( res->identifier(), res->resourceName() );
|
|
} else {
|
|
bool nativeAvailable = mBridgeOnly ? false : migrateResource( res );
|
|
if ( !nativeAvailable ) {
|
|
emit message( Info, i18n( "No native backend for '%1' available.", res->resourceName() ) );
|
|
migrateToBridge( res, mBridgeType );
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
if ( migrationState( ( *mIt )->identifier() ) == Bridged &&
|
|
!mPendingBridgedResources.contains( ( *mIt )->identifier() ) )
|
|
mPendingBridgedResources << ( *mIt )->identifier();
|
|
if ( migrationState( ( *mIt )->identifier() ) == Complete )
|
|
emit message( Skip, i18n( "'%1' has already been migrated.", ( *mIt )->resourceName() ) );
|
|
++mIt;
|
|
}
|
|
if ( !mBridgeType.isEmpty() ) {
|
|
if ( mIt == mResourcesToMigrate.constEnd() ) {
|
|
migrateBridged();
|
|
if ( mPendingBridgedResources.isEmpty() ) {
|
|
migrateUnknown();
|
|
if ( mUnknownTypeResources.isEmpty() ) {
|
|
deleteLater();
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
migrateUnknown();
|
|
if ( mUnknownTypeResources.isEmpty() ) {
|
|
deleteLater();
|
|
}
|
|
}
|
|
}
|
|
|
|
void migrateBridged()
|
|
{
|
|
delete mBridgeManager;
|
|
mBridgeManager = 0;
|
|
|
|
if ( mPendingBridgedResources.isEmpty() ) {
|
|
setupClientBridge();
|
|
return;
|
|
}
|
|
const QString resId = mPendingBridgedResources.takeFirst();
|
|
KConfigGroup resMigrationCfg( KGlobal::config(), QLatin1String("Resource ") + resId );
|
|
const QString akoResId = resMigrationCfg.readEntry( "ResourceIdentifier", "" );
|
|
if ( akoResId.isEmpty() ) {
|
|
mUnknownTypeResources.remove( resId );
|
|
emit message( Error, i18n( "No Akonadi agent identifier specified for previously bridged resource '%1'", resId ) );
|
|
migrateNext();
|
|
return;
|
|
}
|
|
|
|
const QString bridgedCfgFile = KStandardDirs::locateLocal( "config", QString::fromLatin1( "%1rc" ).arg( akoResId ) );
|
|
kDebug() << bridgedCfgFile;
|
|
if ( !QFile::exists( bridgedCfgFile ) ) {
|
|
emit message( Info, i18n( "Bridged resource %1 does not exist anymore, trying a direct migration", akoResId ) );
|
|
setMigrationState( resId /*old id*/, None,
|
|
QString() /*akonadi id*/, mType );
|
|
|
|
ResourceIterator it = mManager->begin();
|
|
while ( it != mManager->end() ) {
|
|
if ( ( *it )->identifier() == resId ) {
|
|
mResourcesToMigrate.append( *it );
|
|
break;
|
|
}
|
|
++it;
|
|
}
|
|
migrateNext();
|
|
return;
|
|
}
|
|
mUnknownTypeResources.remove( resId );
|
|
delete mConfig;
|
|
mConfig = new KConfig( bridgedCfgFile );
|
|
|
|
mBridgeManager = new KRES::Manager<T>( mType );
|
|
mBridgeManager->readConfig( mConfig );
|
|
if ( !mBridgeManager->standardResource() ) {
|
|
// the plugin for this type might no longer be available
|
|
const KConfigGroup kresCfgGroup( mConfig, QString::fromLatin1( "Resource_%1" ).arg( resId ) );
|
|
const QString resourceType = kresCfgGroup.readEntry( QLatin1String( "ResourceType" ), QString() );
|
|
if ( !resourceType.isEmpty() ) {
|
|
if ( resourceType == QLatin1String( "imap" ) ) {
|
|
createKolabResource( resId, kresCfgGroup.readEntry( QLatin1String( "ResourceName" ), QString() ) );
|
|
return;
|
|
}
|
|
|
|
if ( migrateUnknownResource( resId, resourceType, kresCfgGroup ) ) {
|
|
migrateNext();
|
|
return;
|
|
}
|
|
}
|
|
emit message( Error, i18n( "Bridged resource '%1' has no standard resource.", resId ) );
|
|
migrateNext();
|
|
return;
|
|
}
|
|
|
|
T *res = mBridgeManager->standardResource();
|
|
emit message( Info, i18n( "Trying to migrate '%1' from compatibility bridge to native backend...", res->resourceName() ) );
|
|
mCurrentKResource = res;
|
|
bool nativeAvailable = migrateResource( res );
|
|
if ( !nativeAvailable ) {
|
|
emit message( Skip, i18n( "No native backend available, keeping compatibility bridge for '%1'.", res->resourceName() ) );
|
|
migrateNext();
|
|
}
|
|
}
|
|
|
|
virtual bool migrateResource( T *res ) = 0;
|
|
|
|
virtual bool migrateUnknownResource( const QString &kresId, const QString &kresType, const KConfigGroup &kresConfig )
|
|
{
|
|
Q_UNUSED( kresId );
|
|
Q_UNUSED( kresType );
|
|
Q_UNUSED( kresConfig );
|
|
|
|
migrateNext();
|
|
return false;
|
|
}
|
|
|
|
KConfigGroup kresConfig( KRES::Resource* res ) const
|
|
{
|
|
return KConfigGroup( mConfig, QLatin1String("Resource_") + res->identifier() );
|
|
}
|
|
|
|
T* currentResource()
|
|
{
|
|
T* res = dynamic_cast<T*>( mCurrentKResource );
|
|
Q_ASSERT( res );
|
|
return res;
|
|
}
|
|
|
|
void migrationCompleted( const Akonadi::AgentInstance &instance )
|
|
{
|
|
KResMigratorBase::migrationCompleted( instance, mCurrentKResource->identifier(), mCurrentKResource->resourceName() );
|
|
migrationCompletedHelper( instance );
|
|
}
|
|
|
|
void migratedToBridge(const Akonadi::AgentInstance & instance)
|
|
{
|
|
mBridgingInProgress = false;
|
|
setMigrationState( mCurrentKResource->identifier(), Bridged, instance.identifier(), mType );
|
|
emit message( Success, i18n( "Migration of '%1' to compatibility bridge succeeded.", mCurrentKResource->resourceName() ) );
|
|
migrationCompletedHelper( instance );
|
|
}
|
|
|
|
private:
|
|
|
|
// This is called when a native migration or a migration to a bridged resource is
|
|
// successfully completed.
|
|
void migrationCompletedHelper( const Akonadi::AgentInstance & instance )
|
|
{
|
|
if ( mManager->standardResource() == mCurrentKResource ) {
|
|
mAgentForOldDefaultResource = instance.identifier();
|
|
}
|
|
mManager->setActive( mCurrentKResource, false );
|
|
mCurrentKResource = 0;
|
|
migrateNext();
|
|
}
|
|
|
|
void setupClientBridge()
|
|
{
|
|
if ( !mOmitClientBridge ) {
|
|
if ( !mClientBridgeFound ) {
|
|
emit message( Info, i18n( "Setting up client-side bridge..." ) );
|
|
T* clientBridge = mManager->createResource( QLatin1String("akonadi") );
|
|
if ( clientBridge ) {
|
|
mClientBridgeIdentifier = clientBridge->identifier();
|
|
clientBridge->setResourceName( i18n( "Akonadi Compatibility Resource" ) );
|
|
mManager->add( clientBridge );
|
|
mManager->setStandardResource( clientBridge );
|
|
emit message( Info, i18n( "Client-side bridge set up successfully." ) );
|
|
} else {
|
|
emit message( Error, i18n( "Could not create client-side bridge, check if Akonadi KResource bridge is installed." ) );
|
|
}
|
|
}
|
|
|
|
mManager->writeConfig();
|
|
const QString keyName( QLatin1String("DefaultAkonadiResourceIdentifier") );
|
|
KConfigGroup clientBridgeConfig( mConfig, QLatin1String("Resource_") + mClientBridgeIdentifier );
|
|
if ( !clientBridgeConfig.hasKey( keyName ) &&
|
|
!mAgentForOldDefaultResource.isEmpty() ) {
|
|
clientBridgeConfig.writeEntry( keyName, mAgentForOldDefaultResource );
|
|
}
|
|
}
|
|
}
|
|
|
|
void migrateUnknown()
|
|
{
|
|
if ( mUnknownTypeResources.isEmpty() ) {
|
|
return;
|
|
}
|
|
|
|
QSet<QString>::iterator setIt = mUnknownTypeResources.begin();
|
|
const QString kresId = *setIt;
|
|
mUnknownTypeResources.erase( setIt );
|
|
|
|
const KConfigGroup kresCfgGroup( mConfig, QString::fromLatin1( "Resource_%1" ).arg( kresId ) );
|
|
const QString resourceType = kresCfgGroup.readEntry( QLatin1String( "ResourceType" ), QString() );
|
|
const QString resourceName = kresCfgGroup.readEntry( QLatin1String( "ResourceName" ), QString() );
|
|
|
|
kDebug() << "migrating Unknown" << resourceName << ", type=" << resourceType << ",id=" << kresId;
|
|
|
|
if ( resourceType == QLatin1String( "imap" ) ) {
|
|
createKolabResource( kresId, resourceName );
|
|
} else {
|
|
migrateUnknownResource( kresId, resourceType, kresCfgGroup );
|
|
}
|
|
}
|
|
|
|
private:
|
|
KConfig *mConfig;
|
|
KRES::Manager<T> *mManager, *mBridgeManager;
|
|
typedef typename KRES::Manager<T>::Iterator ResourceIterator;
|
|
typename QList<T*>::const_iterator mIt;
|
|
QList<T*> mResourcesToMigrate;
|
|
bool mClientBridgeFound;
|
|
QString mClientBridgeIdentifier;
|
|
QString mAgentForOldDefaultResource;
|
|
QSet<QString> mUnknownTypeResources;
|
|
};
|
|
|
|
#endif
|