File indexing completed on 2023-05-30 11:40:29
0001 /* 0002 Copyright (C) 2017-2018 James D. Smith <smithjd15@gmail.com> 0003 Copyright (C) 2014 David Edmundson <kde@davidedmundson.co.uk> 0004 Copyright (C) 2011 Martin Klapetek <martin.klapetek@gmail.com> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Lesser General Public 0008 License as published by the Free Software Foundation; either 0009 version 2.1 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Lesser General Public License for more details. 0015 0016 You should have received a copy of the GNU Lesser General Public 0017 License along with this library; if not, write to the Free Software 0018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 0019 */ 0020 0021 #include "status-handler.h" 0022 0023 #include "autoaway.h" 0024 #include "screensaveraway.h" 0025 0026 #include "account-status-helper.h" 0027 #include "status-message-parser.h" 0028 0029 #include "ktp_kded_debug.h" 0030 0031 #include <QTimer> 0032 #include <QVariant> 0033 #include <QHash> 0034 0035 #include <TelepathyQt/Account> 0036 #include <TelepathyQt/AccountSet> 0037 #include <TelepathyQt/AccountManager> 0038 #include <TelepathyQt/Constants> 0039 #include <TelepathyQt/Presence> 0040 0041 StatusHandler::StatusHandler(QObject* parent) 0042 : QObject(parent), 0043 m_enabledAccounts(KTp::accountManager()->enabledAccounts()) 0044 { 0045 QDBusConnection::sessionBus().registerObject(QLatin1String("/StatusHandler"), this); 0046 0047 QDBusConnection::sessionBus().connect(QString(), QLatin1String("/Telepathy"), QLatin1String("org.kde.Telepathy"), 0048 QLatin1String("settingsChange"), this, SIGNAL(settingsChanged())); 0049 0050 m_accountStatusHelper = new AccountStatusHelper(this); 0051 0052 m_parsers[QLatin1String("GlobalPresence")] = new StatusMessageParser(this); 0053 connect(m_parsers[QLatin1String("GlobalPresence")], &StatusMessageParser::statusMessageChanged, [=] { 0054 qCDebug(KTP_KDED_MODULE) << "global presence parser has new status message" << m_parsers[QLatin1String("GlobalPresence")]->statusMessage(); 0055 setPresence(); 0056 }); 0057 0058 m_parsers[QLatin1String("PluginPresence")] = new StatusMessageParser(this); 0059 connect(m_parsers[QLatin1String("PluginPresence")], &StatusMessageParser::statusMessageChanged, [=] { 0060 qCDebug(KTP_KDED_MODULE) << "plugin presence parser has new status message" << m_parsers[QLatin1String("PluginPresence")]->statusMessage(); 0061 setPresence(); 0062 }); 0063 0064 auto addAccount = [=] (const Tp::AccountPtr &account) { 0065 // Connect a new status message parser for the account. 0066 m_parsers[account->uniqueIdentifier()] = new StatusMessageParser(this); 0067 connect(m_parsers[account->uniqueIdentifier()], &StatusMessageParser::statusMessageChanged, m_parsers[account->uniqueIdentifier()], [=] { 0068 qCDebug(KTP_KDED_MODULE) << "account" << account->uniqueIdentifier() << "parser has new status message" << m_parsers[account->uniqueIdentifier()]->statusMessage(); 0069 setPresence(account->uniqueIdentifier()); 0070 }); 0071 0072 qCDebug(KTP_KDED_MODULE) << "new parser:" << account->uniqueIdentifier(); 0073 0074 // Watch for automatic presence changes from the account. 0075 connect(account.data(), &Tp::Account::automaticPresenceChanged, account.data(), [=] (const Tp::Presence &automaticPresence) { 0076 m_accountStatusHelper->setRequestedAccountPresence(account->uniqueIdentifier(), automaticPresence.barePresence(), AccountStatusHelper::Persistent); 0077 }); 0078 }; 0079 0080 for (const Tp::AccountPtr &account : m_enabledAccounts->accounts()) { 0081 addAccount(account); 0082 } 0083 0084 m_pluginPresence.setStatus(Tp::ConnectionPresenceTypeUnset, QLatin1String("unset"), QString()); 0085 0086 AutoAway *autoAway = new AutoAway(this); 0087 ScreenSaverAway *screenSaverAway = new ScreenSaverAway(this); 0088 0089 //earlier in list = lower priority 0090 m_queuePlugins << screenSaverAway << autoAway; 0091 0092 for (TelepathyKDEDModulePlugin* plugin : m_queuePlugins) { 0093 connect(plugin, &TelepathyKDEDModulePlugin::pluginChanged, [=] () { 0094 QList<TelepathyKDEDModulePlugin*> activePlugins; 0095 for (TelepathyKDEDModulePlugin* plugin : m_queuePlugins) { 0096 if (plugin->pluginState() != TelepathyKDEDModulePlugin::Active) 0097 continue; 0098 0099 if (KTp::Presence::sortPriority(plugin->requestedPresence().type()) 0100 >= KTp::Presence::sortPriority(m_pluginPresence.type())) { 0101 activePlugins.prepend(plugin); 0102 } else { 0103 activePlugins.append(plugin); 0104 } 0105 } 0106 0107 if (activePlugins.isEmpty()) { 0108 m_pluginPresence.setStatus(Tp::ConnectionPresenceTypeUnset, QLatin1String("unset"), QString()); 0109 } else { 0110 m_pluginPresence = activePlugins.at(0)->requestedPresence(); 0111 } 0112 0113 m_parsers[(QLatin1String("PluginPresence"))]->parseStatusMessage(m_pluginPresence.statusMessage()); 0114 qCDebug(KTP_KDED_MODULE) << "plugin queue activation:" << m_pluginPresence.status() 0115 << m_parsers[(QLatin1String("PluginPresence"))]->statusMessage(); 0116 0117 setPresence(); 0118 }); 0119 0120 connect(this, &StatusHandler::settingsChanged, plugin, &TelepathyKDEDModulePlugin::reloadConfig); 0121 } 0122 0123 connect(m_accountStatusHelper, &AccountStatusHelper::statusChange, [=] (const QString &accountUID) { 0124 if (accountUID.isEmpty()) { 0125 m_parsers[QLatin1String("GlobalPresence")]->parseStatusMessage(m_accountStatusHelper->requestedGlobalPresence().statusMessage); 0126 } else { 0127 Tp::Presence presence = Tp::Presence(qvariant_cast<Tp::SimplePresence>(m_accountStatusHelper->requestedAccountPresences().value(accountUID))); 0128 m_parsers[accountUID]->parseStatusMessage(presence.statusMessage()); 0129 0130 // The global presence parser must be set for accounts using the global presence. 0131 if ((presence.type() == Tp::ConnectionPresenceTypeUnset) 0132 && (m_parsers[QLatin1String("GlobalPresence")]->statusMessage().isEmpty() 0133 != m_accountStatusHelper->requestedGlobalPresence().statusMessage.isEmpty())) { 0134 m_parsers[QLatin1String("GlobalPresence")]->parseStatusMessage(m_accountStatusHelper->requestedGlobalPresence().statusMessage); 0135 } 0136 } 0137 0138 setPresence(accountUID); 0139 }); 0140 0141 connect(m_enabledAccounts.data(), &Tp::AccountSet::accountAdded, [=] (const Tp::AccountPtr &account) { 0142 addAccount(account); 0143 }); 0144 0145 connect(m_enabledAccounts.data(), &Tp::AccountSet::accountRemoved, [=] (const Tp::AccountPtr &account) { 0146 disconnect(account.data(), &Tp::Account::requestedPresenceChanged, account.data(), Q_NULLPTR); 0147 disconnect(m_parsers[account->uniqueIdentifier()], &StatusMessageParser::statusMessageChanged, m_parsers[account->uniqueIdentifier()], Q_NULLPTR); 0148 m_parsers.remove(account->uniqueIdentifier()); 0149 parkAccount(account); 0150 }); 0151 } 0152 0153 StatusHandler::~StatusHandler() 0154 { 0155 QDBusConnection::sessionBus().unregisterObject(QLatin1String("/StatusHandler"), QDBusConnection::UnregisterTree); 0156 0157 for (const Tp::AccountPtr &account : KTp::accountManager()->onlineAccounts()->accounts()) { 0158 disconnect(account.data(), &Tp::Account::requestedPresenceChanged, account.data(), Q_NULLPTR); 0159 parkAccount(account); 0160 } 0161 } 0162 0163 void StatusHandler::setPresence(const QString &accountUID) 0164 { 0165 const QString &globalParsedMessage = m_parsers[QLatin1String("GlobalPresence")]->statusMessage(); 0166 const QString &pluginParsedMessage = m_parsers[QLatin1String("PluginPresence")]->statusMessage(); 0167 const QHash<QString, QString> &pluginTokens = m_parsers[QLatin1String("PluginPresence")]->tokens(); 0168 0169 auto accountPresence = [&] (const QString &accountUID) { 0170 Tp::Presence presence = Tp::Presence(qvariant_cast<Tp::SimplePresence>(m_accountStatusHelper->requestedAccountPresences().value(accountUID))); 0171 QHash<QString, QString> tokens; 0172 0173 if ((presence.type() == Tp::ConnectionPresenceTypeUnset) 0174 || (m_accountStatusHelper->requestedGlobalPresence().type == Tp::Presence::offline().type())) { 0175 tokens = m_parsers[QLatin1String("GlobalPresence")]->tokens(); 0176 presence = Tp::Presence(m_accountStatusHelper->requestedGlobalPresence()); 0177 presence.setStatusMessage(globalParsedMessage); 0178 } else { 0179 tokens = m_parsers[accountUID]->tokens(); 0180 0181 if (tokens.contains((QLatin1String("%um"))) && tokens[(QLatin1String("%um"))] == QLatin1String("g")) { 0182 presence.setStatusMessage(globalParsedMessage); 0183 } else { 0184 presence.setStatusMessage(m_parsers[accountUID]->statusMessage()); 0185 } 0186 } 0187 0188 bool sourcePluginQueue = (presence.type() != Tp::ConnectionPresenceTypeHidden) 0189 && (presence.type() != Tp::ConnectionPresenceTypeOffline) 0190 && (m_pluginPresence.type() != Tp::ConnectionPresenceTypeUnset); 0191 0192 if (sourcePluginQueue) { 0193 if (KTp::Presence::sortPriority(presence.type()) < KTp::Presence::sortPriority(m_pluginPresence.type())) { 0194 presence = Tp::Presence(m_pluginPresence.type(), m_pluginPresence.status(), QString()); 0195 } 0196 0197 if (!pluginTokens.contains(QLatin1String("%um")) && !tokens.contains(QLatin1String("%um"))) { 0198 presence.setStatusMessage(pluginParsedMessage); 0199 } else if (tokens.contains((QLatin1String("%um"))) && tokens[(QLatin1String("%um"))] == QLatin1String("g")) { 0200 presence.setStatusMessage(globalParsedMessage); 0201 } 0202 } 0203 0204 return presence; 0205 }; 0206 0207 for (const Tp::AccountPtr &account : m_enabledAccounts->accounts()) { 0208 if (!accountUID.isEmpty() && (accountUID != account->uniqueIdentifier())) { 0209 continue; 0210 } 0211 0212 const Tp::Presence presence = accountPresence(account->uniqueIdentifier()); 0213 connect(account->setRequestedPresence(presence), &Tp::PendingOperation::finished, [=] (Tp::PendingOperation *op) { 0214 if (!op->isError()) { 0215 qCDebug(KTP_KDED_MODULE) << account->uniqueIdentifier() << "requested presence change to" << presence.status() << "with status message" << presence.statusMessage(); 0216 } else { 0217 qCWarning(KTP_KDED_MODULE()) << account->uniqueIdentifier() << "requested presence change error:" << op->errorMessage(); 0218 } 0219 }); 0220 } 0221 } 0222 0223 void StatusHandler::parkAccount(const Tp::AccountPtr &account) 0224 { 0225 Tp::SimplePresence accountPresence = qvariant_cast<Tp::SimplePresence>(m_accountStatusHelper->requestedAccountPresences().value(account->uniqueIdentifier())); 0226 if (accountPresence.type == Tp::ConnectionPresenceTypeUnset) { 0227 accountPresence = m_accountStatusHelper->requestedGlobalPresence(); 0228 } 0229 accountPresence.statusMessage = QLatin1String(); 0230 0231 account->setRequestedPresence(Tp::Presence(accountPresence)); 0232 }