1/*
2 Copyright (c) 2009 Volker Krause <vkrause@kde.org>
3
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.
8
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.
13
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
17 02110-1301, USA.
18*/
19
20#include "resource.h"
21
22#include <akonadi/agenttype.h>
23#include <akonadi/agentmanager.h>
24#include <akonadi/agentinstancecreatejob.h>
25
26#include <KDebug>
27#include <KLocalizedString>
28
29#include <QMetaMethod>
30#include <QVariant>
31#include <QtDBus/qdbusinterface.h>
32#include <QtDBus/qdbusreply.h>
33
34using namespace Akonadi;
35
36static QVariant::Type argumentType( const QMetaObject *mo, const QString &method )
37{
38 QMetaMethod m;
39 for ( int i = 0; i < mo->methodCount(); ++i ) {
40 const QString signature = QString::fromLatin1( mo->method( i ).signature() );
41 if ( signature.contains( method + QLatin1Char( '(' ) ) ) {
42 m = mo->method( i );
43 break;
44 }
45 }
46
47 if ( !m.signature() ) {
48 kWarning() << "Did not find D-Bus method: " << method << " available methods are:";
49 for ( int i = 0; i < mo->methodCount(); ++i )
50 kWarning() << mo->method( i ).signature();
51 return QVariant::Invalid;
52 }
53
54 const QList<QByteArray> argTypes = m.parameterTypes();
55 if ( argTypes.count() != 1 )
56 return QVariant::Invalid;
57
58 return QVariant::nameToType( argTypes.first() );
59}
60
61Resource::Resource(const QString& type, QObject* parent) :
62 SetupObject( parent ),
63 m_typeIdentifier( type )
64{
65}
66
67void Resource::setOption( const QString &key, const QVariant &value )
68{
69 m_settings.insert( key, value );
70}
71
72void Resource::setName( const QString &name )
73{
74 m_name = name;
75}
76
77void Resource::create()
78{
79 const AgentType type = AgentManager::self()->type( m_typeIdentifier );
80 if ( !type.isValid() ) {
81 emit error( i18n( "Resource type '%1' is not available.", m_typeIdentifier ) );
82 return;
83 }
84
85 // check if unique instance already exists
86 kDebug() << type.capabilities();
87 if ( type.capabilities().contains( QLatin1String( "Unique" ) ) ) {
88 foreach ( const AgentInstance &instance, AgentManager::self()->instances() ) {
89 kDebug() << instance.type().identifier() << ( instance.type() == type );
90 if ( instance.type() == type ) {
91 emit finished( i18n( "Resource '%1' is already set up.", type.name() ) );
92 return;
93 }
94 }
95 }
96
97 emit info( i18n( "Creating resource instance for '%1'...", type.name() ) );
98 AgentInstanceCreateJob *job = new AgentInstanceCreateJob( type, this );
99 connect( job, SIGNAL(result(KJob*)), SLOT(instanceCreateResult(KJob*)) );
100 job->start();
101}
102
103
104void Resource::instanceCreateResult(KJob* job)
105{
106 if ( job->error() ) {
107 emit error( i18n( "Failed to create resource instance: %1", job->errorText() ) );
108 return;
109 }
110
111 m_instance = qobject_cast<AgentInstanceCreateJob*>( job )->instance();
112
113 if ( !m_settings.isEmpty() ) {
114 emit info( i18n( "Configuring resource instance..." ) );
115 QDBusInterface iface( QLatin1String("org.freedesktop.Akonadi.Resource.") + m_instance.identifier(), QLatin1String("/Settings") );
116 if ( !iface.isValid() ) {
117 emit error( i18n( "Unable to configure resource instance." ) );
118 return;
119 }
120
121 // configure resource
122 if ( !m_name.isEmpty() )
123 m_instance.setName( m_name );
124 QMap<QString, QVariant>::const_iterator end( m_settings.constEnd() );
125 for ( QMap<QString, QVariant>::const_iterator it = m_settings.constBegin(); it != end; ++it ) {
126 kDebug() << "Setting up " << it.key() << " for agent " << m_instance.identifier();
127 const QString methodName = QString::fromLatin1( "set%1" ).arg( it.key() );
128 QVariant arg = it.value();
129 const QVariant::Type targetType = argumentType( iface.metaObject(), methodName );
130 if ( !arg.canConvert( targetType ) ) {
131 emit error( i18n( "Could not convert value of setting '%1' to required type %2.", it.key(), QLatin1String(QVariant::typeToName( targetType )) ) );
132 return;
133 }
134 arg.convert( targetType );
135 QDBusReply<void> reply = iface.call( methodName, arg );
136 if ( !reply.isValid() ) {
137 emit error( i18n( "Could not set setting '%1': %2", it.key(), reply.error().message() ) );
138 return;
139 }
140 }
141 m_instance.reconfigure();
142 }
143
144 emit finished( i18n( "Resource setup completed." ) );
145}
146
147void Resource::destroy()
148{
149 if ( m_instance.isValid() ) {
150 AgentManager::self()->removeInstance( m_instance );
151 emit info( i18n( "Removed resource instance for '%1'.", m_instance.type().name() ) );
152 }
153}
154
155QString Resource::identifier()
156{
157 return m_instance.identifier();
158}
159
160void Resource::reconfigure()
161{
162 m_instance.reconfigure();
163}
164
165
166