20 #include "firstrun_p.h" 21 #include "dbusconnectionpool.h" 22 #include "servermanager.h" 24 #include <akonadi/agentinstance.h> 25 #include <akonadi/agentinstancecreatejob.h> 26 #include <akonadi/agentmanager.h> 27 #include <akonadi/agenttype.h> 30 #include <KConfigGroup> 34 #include <KStandardDirs> 36 #include <QtDBus/QDBusConnection> 37 #include <QtDBus/QDBusInterface> 38 #include <QtDBus/QDBusReply> 39 #include <QtCore/QDir> 40 #include <QtCore/QMetaMethod> 41 #include <QtCore/QMetaObject> 43 static char FIRSTRUN_DBUSLOCK[] =
"org.kde.Akonadi.Firstrun.lock";
47 Firstrun::Firstrun(QObject *parent)
49 , mConfig(new KConfig(
ServerManager::addNamespace(QLatin1String(
"akonadi-firstrunrc"))))
60 if (DBusConnectionPool::threadConnection().registerService(QLatin1String(FIRSTRUN_DBUSLOCK))) {
61 findPendingDefaults();
62 kDebug() << mPendingDefaults;
65 kDebug() <<
"D-Bus lock found, so someone else does the work for us already.";
72 DBusConnectionPool::threadConnection().unregisterService(QLatin1String(FIRSTRUN_DBUSLOCK));
77 void Firstrun::findPendingDefaults()
79 const KConfigGroup cfg(mConfig,
"ProcessedDefaults");
80 foreach (
const QString &dirName, KGlobal::dirs()->findDirs(
"data", QLatin1String(
"akonadi/firstrun"))) {
81 const QStringList files = QDir(dirName).entryList(QDir::Files | QDir::Readable);
82 foreach (
const QString &fileName, files) {
83 const QString fullName = dirName + fileName;
85 const QString
id = KConfigGroup(&c,
"Agent").readEntry(
"Id", QString());
87 kWarning() <<
"Found invalid default configuration in " << fullName;
93 mPendingDefaults << dirName + fileName;
97 #ifndef KDEPIM_NO_KRESOURCES 99 mPendingKres << QLatin1String(
"contact") << QLatin1String(
"calendar");
103 #ifndef KDEPIM_NO_KRESOURCES 104 static QString resourceTypeForMimetype(
const QStringList &mimeTypes)
106 if (mimeTypes.contains(QLatin1String(
"text/directory"))) {
107 return QString::fromLatin1(
"contact");
109 if (mimeTypes.contains(QLatin1String(
"text/calendar"))) {
110 return QString::fromLatin1(
"calendar");
116 void Firstrun::migrateKresType(
const QString &resourceFamily)
118 mResourceFamily = resourceFamily;
119 KConfig config(QLatin1String(
"kres-migratorrc"));
120 KConfigGroup migrationCfg(&config,
"Migration");
121 const bool enabled = migrationCfg.readEntry(
"Enabled",
false);
122 const bool setupClientBridge = migrationCfg.readEntry(
"SetupClientBridge",
true);
123 const int currentVersion = migrationCfg.readEntry(QString::fromLatin1(
"Version-%1").arg(resourceFamily), 0);
124 const int targetVersion = migrationCfg.readEntry(
"TargetVersion", 0);
125 if (enabled && currentVersion < targetVersion) {
126 kDebug() <<
"Performing migration of legacy KResource settings. Good luck!";
127 mProcess =
new KProcess(
this);
128 connect(mProcess, SIGNAL(finished(
int)), SLOT(migrationFinished(
int)));
129 QStringList args = QStringList() << QLatin1String(
"--interactive-on-change")
130 << QLatin1String(
"--type") << resourceFamily;
131 if (!setupClientBridge) {
132 args << QLatin1String(
"--omit-client-bridge");
134 mProcess->setProgram(QLatin1String(
"kres-migrator"), args);
136 if (!mProcess->waitForStarted()) {
137 migrationFinished(-1);
145 void Firstrun::migrationFinished(
int exitCode)
149 kDebug() <<
"KResource -> Akonadi migration has been successful";
150 KConfig config(QLatin1String(
"kres-migratorrc"));
151 KConfigGroup migrationCfg(&config,
"Migration");
152 const int targetVersion = migrationCfg.readEntry(
"TargetVersion", 0);
153 migrationCfg.writeEntry(QString::fromLatin1(
"Version-%1").arg(mResourceFamily), targetVersion);
155 }
else if (exitCode != 1) {
157 kError() <<
"KResource -> Akonadi migration failed!";
158 kError() <<
"command was: " << mProcess->program();
159 kError() <<
"exit code: " << mProcess->exitCode();
160 kError() <<
"stdout: " << mProcess->readAllStandardOutput();
161 kError() <<
"stderr: " << mProcess->readAllStandardError();
168 void Firstrun::setupNext()
170 delete mCurrentDefault;
173 if (mPendingDefaults.isEmpty()) {
174 #ifndef KDEPIM_NO_KRESOURCES 175 if (!mPendingKres.isEmpty()) {
176 migrateKresType(mPendingKres.takeFirst());
184 mCurrentDefault =
new KConfig(mPendingDefaults.takeFirst());
185 const KConfigGroup agentCfg = KConfigGroup(mCurrentDefault,
"Agent");
189 kError() <<
"Unable to obtain agent type for default resource agent configuration " << mCurrentDefault->
name();
194 #ifndef KDEPIM_NO_KRESOURCES 197 const QString kresType = resourceTypeForMimetype(type.
mimeTypes());
198 if (!kresType.isEmpty()) {
199 const QString kresCfgFile = KStandardDirs::locateLocal(
"config", QString::fromLatin1(
"kresources/%1/stdrc").arg(kresType));
200 KConfig resCfg(kresCfgFile);
201 const KConfigGroup resGroup(&resCfg,
"General");
202 bool legacyResourceFound =
false;
203 const QStringList kresResources = resGroup.readEntry(
"ResourceKeys", QStringList())
204 + resGroup.readEntry(
"PassiveResourceKeys", QStringList());
205 foreach (
const QString &kresResource, kresResources) {
206 const KConfigGroup cfg(&resCfg, QString::fromLatin1(
"Resource_%1").arg(kresResource));
207 if (cfg.readEntry(
"ResourceType", QString()) != QLatin1String(
"akonadi")) {
208 legacyResourceFound =
true;
212 if (legacyResourceFound) {
213 kDebug() <<
"ignoring " << mCurrentDefault->name() <<
" as there is a KResource setup for its type already.";
214 KConfigGroup cfg(mConfig,
"ProcessedDefaults");
215 cfg.writeEntry(agentCfg.readEntry(
"Id", QString()), QString::fromLatin1(
"kres"));
224 connect(job, SIGNAL(result(KJob*)), SLOT(instanceCreated(KJob*)));
228 void Firstrun::instanceCreated(KJob *job)
230 Q_ASSERT(mCurrentDefault);
233 kError() <<
"Creating agent instance failed for " << mCurrentDefault->name();
239 const KConfigGroup agentCfg = KConfigGroup(mCurrentDefault,
"Agent");
240 const QString agentName = agentCfg.readEntry(
"Name", QString());
241 if (!agentName.isEmpty()) {
246 const KConfigGroup settings = KConfigGroup(mCurrentDefault,
"Settings");
248 QDBusInterface *iface =
new QDBusInterface(QString::fromLatin1(
"org.freedesktop.Akonadi.Agent.%1").arg(instance.
identifier()),
249 QLatin1String(
"/Settings"), QString(),
250 DBusConnectionPool::threadConnection(),
this);
251 if (!iface->isValid()) {
252 kError() <<
"Unable to obtain the KConfigXT D-Bus interface of " << instance.
identifier();
258 foreach (
const QString &setting, settings.keyList()) {
259 kDebug() <<
"Setting up " << setting <<
" for agent " << instance.
identifier();
260 const QString methodName = QString::fromLatin1(
"set%1").arg(setting);
261 const QVariant::Type argType = argumentType(iface->metaObject(), methodName);
262 if (argType == QVariant::Invalid) {
263 kError() <<
"Setting " << setting <<
" not found in agent configuration interface of " << instance.
identifier();
268 if (argType == QVariant::String) {
271 arg = settings.readPathEntry(setting, QString());
273 arg = settings.readEntry(setting, QVariant(argType));
276 const QDBusReply<void> reply = iface->call(methodName, arg);
277 if (!reply.isValid()) {
278 kError() <<
"Setting " << setting <<
" failed for agent " << instance.
identifier();
282 iface->call(QLatin1String(
"writeConfig"));
289 KConfigGroup cfg(mConfig,
"ProcessedDefaults");
290 cfg.writeEntry(agentCfg.readEntry(
"Id", QString()), instance.
identifier());
296 QVariant::Type Firstrun::argumentType(
const QMetaObject *mo,
const QString &method)
299 for (
int i = 0; i < mo->methodCount(); ++i) {
300 const QString signature = QString::fromLatin1(mo->method(i).signature());
301 if (signature.startsWith(method)) {
306 if (!m.signature()) {
307 return QVariant::Invalid;
310 const QList<QByteArray> argTypes = m.parameterTypes();
311 if (argTypes.count() != 1) {
312 return QVariant::Invalid;
315 return QVariant::nameToType(argTypes.first());
318 #include "moc_firstrun_p.cpp" void synchronize()
Triggers the agent instance to start synchronization.
bool isValid() const
Returns whether the agent type is valid.
QString identifier() const
Returns the unique identifier of the agent instance.
Provides methods to control the Akonadi server process.
void reconfigure() const
Tell the agent that its configuration has been changed remotely via D-Bus.
A representation of an agent type.
AgentType type(const QString &identifier) const
Returns the agent type with the given identifier or an invalid agent type if the identifier does not ...
void setName(const QString &name)
Sets the user visible name of the agent instance.
Job for creating new agent instances.
FreeBusyManager::Singleton.
static AgentManager * self()
Returns the global instance of the agent manager.
A representation of an agent instance.
QString name() const
Returns the i18n'ed name of the agent type.
QStringList mimeTypes() const
Returns the list of supported mime types of the agent type.
static bool hasInstanceIdentifier()
Returns true if we are connected to a non-default Akonadi server instance.
void start()
Starts the instance creation.