Changeset View
Changeset View
Standalone View
Standalone View
src/akonadicontrol/accountsintegration.cpp
- This file was added.
1 | /*************************************************************************** | ||||
---|---|---|---|---|---|
2 | * Copyright (c) 2019 Daniel Vrátil <dvratil@kde.org> * | ||||
3 | * * | ||||
4 | * This program is free software; you can redistribute it and/or modify * | ||||
5 | * it under the terms of the GNU Library General Public License as * | ||||
6 | * published by the Free Software Foundation; either version 2 of the * | ||||
7 | * License, or (at your option) any later version. * | ||||
8 | * * | ||||
9 | * This program is distributed in the hope that it will be useful, * | ||||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||||
12 | * GNU General Public License for more details. * | ||||
13 | * * | ||||
14 | * You should have received a copy of the GNU Library General Public * | ||||
15 | * License along with this program; if not, write to the * | ||||
16 | * Free Software Foundation, Inc., * | ||||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * | ||||
18 | ***************************************************************************/ | ||||
19 | | ||||
20 | #include "accountsintegration.h" | ||||
21 | #include "agentmanager.h" | ||||
22 | #include "akonadicontrol_debug.h" | ||||
23 | #include "accountsinterface.h" | ||||
24 | | ||||
25 | #include <private/dbus_p.h> | ||||
26 | | ||||
27 | #include <QDBusConnection> | ||||
28 | #include <QTimer> | ||||
29 | | ||||
30 | #include <Accounts/Account> | ||||
31 | #include <Accounts/Service> | ||||
32 | | ||||
33 | using namespace Akonadi; | ||||
34 | using namespace std::chrono_literals; | ||||
35 | | ||||
36 | namespace { | ||||
37 | | ||||
38 | static const auto akonadiAgentType = QStringLiteral("akonadi/agentType"); | ||||
39 | | ||||
40 | } | ||||
41 | | ||||
42 | AccountsIntegration::AccountsIntegration(AgentManager &agentManager) | ||||
43 | : QObject() | ||||
44 | , mAgentManager(agentManager) | ||||
45 | { | ||||
46 | connect(&mAccountsManager, &Accounts::Manager::accountCreated, | ||||
47 | this, &AccountsIntegration::onAccountAdded); | ||||
48 | connect(&mAccountsManager, &Accounts::Manager::accountRemoved, | ||||
49 | this, &AccountsIntegration::onAccountRemoved); | ||||
50 | | ||||
51 | const auto accounts = mAccountsManager.accountList(); | ||||
52 | for (const auto account : accounts) { | ||||
53 | connect(mAccountsManager.account(account), &Accounts::Account::enabledChanged, | ||||
54 | this, &AccountsIntegration::onAccountServiceEnabled); | ||||
55 | } | ||||
56 | } | ||||
57 | | ||||
58 | akOptional<QString> AccountsIntegration::agentForAccount(const QString &agentType, Accounts::AccountId accountId) const | ||||
59 | { | ||||
60 | const auto instances = mAgentManager.agentInstances(); | ||||
61 | for (const auto &identifier : instances) { | ||||
62 | if (mAgentManager.agentInstanceType(identifier) == agentType) { | ||||
63 | const auto serviceName = Akonadi::DBus::agentServiceName(identifier, Akonadi::DBus::Resource); | ||||
64 | org::kde::Akonadi::Accounts accountsIface(serviceName, QStringLiteral("/Accounts"), QDBusConnection::sessionBus()); | ||||
65 | if (!accountsIface.isValid()) { | ||||
66 | continue; | ||||
67 | } | ||||
68 | | ||||
69 | if (accountsIface.getAccountId() == accountId) { | ||||
70 | return identifier; | ||||
71 | } | ||||
72 | } | ||||
73 | } | ||||
74 | return nullopt; | ||||
75 | } | ||||
76 | | ||||
77 | void AccountsIntegration::configureAgentInstance(const QString &identifier, Accounts::AccountId accountId, int attempt) | ||||
78 | { | ||||
79 | const auto serviceName = Akonadi::DBus::agentServiceName(identifier, Akonadi::DBus::Resource); | ||||
80 | org::kde::Akonadi::Accounts accountsIface(serviceName, QStringLiteral("/Accounts"), QDBusConnection::sessionBus()); | ||||
81 | if (!accountsIface.isValid()) { | ||||
82 | if (attempt >= 3) { | ||||
83 | qCWarning(AKONADICONTROL_LOG) << "The resource" << identifier << "does not provide the Accounts DBus interface. Will remove the agent"; | ||||
84 | mAgentManager.removeAgentInstance(identifier); | ||||
85 | } else { | ||||
86 | QTimer::singleShot(2s, this, [this, identifier, accountId, attempt]() { | ||||
87 | configureAgentInstance(identifier, accountId, attempt + 1); | ||||
88 | }); | ||||
89 | } | ||||
90 | return; | ||||
91 | } | ||||
92 | | ||||
93 | accountsIface.setAccountId(accountId); | ||||
94 | qCDebug(AKONADICONTROL_LOG) << "Configured resource" << identifier << "for account" << accountId; | ||||
95 | } | ||||
96 | | ||||
97 | void AccountsIntegration::createAgent(const QString &agentType, Accounts::AccountId accountId) | ||||
98 | { | ||||
99 | const auto identifier = mAgentManager.createAgentInstance(agentType); | ||||
100 | qCDebug(AKONADICONTROL_LOG) << "Created resource" << identifier << "for account" << accountId; | ||||
101 | configureAgentInstance(identifier, accountId); | ||||
102 | } | ||||
103 | | ||||
104 | void AccountsIntegration::removeAgentInstance(const QString &identifier) | ||||
105 | { | ||||
106 | mAgentManager.removeAgentInstance(identifier); | ||||
107 | } | ||||
108 | | ||||
109 | void AccountsIntegration::onAccountAdded(Accounts::AccountId accId) | ||||
110 | { | ||||
111 | qCDebug(AKONADICONTROL_LOG) << "Online account ID" << accId << "added."; | ||||
112 | auto account = mAccountsManager.account(accId); | ||||
113 | if (!account || !account->isEnabled()) { | ||||
114 | return; | ||||
115 | } | ||||
116 | | ||||
117 | const auto enabledServices = account->enabledServices(); | ||||
118 | for (const auto &service : enabledServices) { | ||||
119 | account->selectService(service); | ||||
120 | const auto agentType = account->valueAsString(akonadiAgentType); | ||||
121 | if (agentType.isEmpty()) { | ||||
122 | continue; // doesn't support Akonadi :-( | ||||
123 | } | ||||
124 | const auto agent = agentForAccount(agentType, accId); | ||||
125 | if (!agent.has_value()) { | ||||
126 | createAgent(agentType, account->id()); | ||||
127 | } | ||||
128 | // Always go through all services, there may be more! | ||||
129 | } | ||||
130 | account->selectService(); | ||||
131 | | ||||
132 | connect(account, &Accounts::Account::enabledChanged, | ||||
133 | this, &AccountsIntegration::onAccountServiceEnabled); | ||||
134 | } | ||||
135 | | ||||
136 | void AccountsIntegration::onAccountRemoved(Accounts::AccountId accId) | ||||
137 | { | ||||
138 | qCDebug(AKONADICONTROL_LOG) << "Online account ID" << accId << "removed."; | ||||
139 | | ||||
140 | const auto instances = mAgentManager.agentInstances(); | ||||
141 | for (const auto &instance : instances) { | ||||
142 | const auto serviceName = DBus::agentServiceName(instance, DBus::Resource); | ||||
143 | org::kde::Akonadi::Accounts accountIface(serviceName, QStringLiteral("/Accounts"), QDBusConnection::sessionBus()); | ||||
144 | if (!accountIface.isValid()) { | ||||
145 | continue; | ||||
146 | } | ||||
147 | | ||||
148 | if (accountIface.getAccountId() == accId) { | ||||
149 | removeAgentInstance(instance); | ||||
150 | } | ||||
151 | } | ||||
152 | } | ||||
153 | | ||||
154 | void AccountsIntegration::onAccountServiceEnabled(const QString &serviceType, bool enabled) | ||||
155 | { | ||||
156 | if (serviceType.isEmpty()) { | ||||
157 | return; | ||||
158 | } | ||||
159 | | ||||
160 | auto account = qobject_cast<Accounts::Account*>(sender()); | ||||
161 | qCDebug(AKONADICONTROL_LOG) << "Online account ID" << account->id() << "service" << serviceType << "has been" << (enabled ? "enabled" : "disabled"); | ||||
162 | | ||||
163 | const auto service = mAccountsManager.service(serviceType); | ||||
164 | account->selectService(service); | ||||
165 | const auto agentType = account->valueAsString(akonadiAgentType); | ||||
166 | account->selectService(); | ||||
167 | if (agentType.isEmpty()) { | ||||
168 | return; // this service does not support Akonadi (yet -;) | ||||
169 | } | ||||
170 | | ||||
171 | const auto identifier = agentForAccount(agentType, account->id()); | ||||
172 | if (enabled && !identifier.has_value()) { | ||||
173 | createAgent(agentType, account->id()); | ||||
174 | } else if (!enabled && identifier.has_value()) { | ||||
175 | removeAgentInstance(identifier.value()); | ||||
176 | } | ||||
177 | } |