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 | |
34 | using namespace Akonadi; |
35 | |
36 | static 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 | |
61 | Resource::Resource(const QString& type, QObject* parent) : |
62 | SetupObject( parent ), |
63 | m_typeIdentifier( type ) |
64 | { |
65 | } |
66 | |
67 | void Resource::setOption( const QString &key, const QVariant &value ) |
68 | { |
69 | m_settings.insert( key, value ); |
70 | } |
71 | |
72 | void Resource::setName( const QString &name ) |
73 | { |
74 | m_name = name; |
75 | } |
76 | |
77 | void 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 | |
104 | void 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 | |
147 | void 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 | |
155 | QString Resource::identifier() |
156 | { |
157 | return m_instance.identifier(); |
158 | } |
159 | |
160 | void Resource::reconfigure() |
161 | { |
162 | m_instance.reconfigure(); |
163 | } |
164 | |
165 | |
166 | |