diff --git a/KTp/global-presence.cpp b/KTp/global-presence.cpp index a0df98d..57d0c36 100644 --- a/KTp/global-presence.cpp +++ b/KTp/global-presence.cpp @@ -1,398 +1,395 @@ /* * Global Presence - wraps calls to set and get presence for all accounts. * * Copyright (C) 2011 David Edmundson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "global-presence.h" #include #include #include #include #include #include #include #include #include "types.h" #include "ktp-debug.h" namespace KTp { GlobalPresence::GlobalPresence(QObject *parent) : QObject(parent), m_connectionStatus(GlobalPresence::Disconnected), m_changingPresence(false), m_hasEnabledAccounts(false) { Tp::registerTypes(); m_statusHandlerInterface = new QDBusInterface(QLatin1String("org.freedesktop.Telepathy.Client.KTp.KdedIntegrationModule"), QLatin1String("/StatusHandler"), QString(), QDBusConnection::sessionBus(), this); m_requestedPresence.setStatus(Tp::ConnectionPresenceTypeUnset, QLatin1String("unset"), QString()); m_currentPresence.setStatus(Tp::ConnectionPresenceTypeUnset, QLatin1String("unset"), QString()); } void GlobalPresence::setAccountManager(const Tp::AccountManagerPtr &accountManager) { m_accountManager = accountManager; m_enabledAccounts = m_accountManager->enabledAccounts(); m_onlineAccounts = m_accountManager->onlineAccounts(); for (const Tp::AccountPtr &account : m_enabledAccounts->accounts()) { onAccountEnabledChanged(account); } connect(m_enabledAccounts.data(), &Tp::AccountSet::accountAdded, this, &GlobalPresence::onAccountEnabledChanged); connect(m_enabledAccounts.data(), &Tp::AccountSet::accountRemoved, this, &GlobalPresence::onAccountEnabledChanged); if (!m_accountManager->isReady()) { qCWarning(KTP_COMMONINTERNALS) << "GlobalPresence used with unready account manager"; } else { Q_EMIT accountManagerReady(); } } void GlobalPresence::addAccountManager(const Tp::AccountManagerPtr &accountManager) { connect(accountManager->becomeReady(), &Tp::PendingReady::finished, [=] (Tp::PendingOperation* op) { if (op->isError()) { qCDebug(KTP_COMMONINTERNALS) << op->errorName(); qCDebug(KTP_COMMONINTERNALS) << op->errorMessage(); qCDebug(KTP_COMMONINTERNALS) << "Something unexpected happened to" << "the core part of your Instant Messaging system and it couldn't" << "be initialized. Try restarting the client."; return; } setAccountManager(accountManager); }); } Tp::AccountManagerPtr GlobalPresence::accountManager() const { return m_accountManager; } GlobalPresence::ConnectionStatus GlobalPresence::connectionStatus() const { return m_connectionStatus; } KTp::Presence GlobalPresence::currentPresence() const { return m_currentPresence; } QString GlobalPresence::currentPresenceMessage() const { return m_currentPresence.statusMessage(); } QIcon GlobalPresence::currentPresenceIcon() const { return m_currentPresence.icon(); } QString GlobalPresence::currentPresenceIconName() const { return m_currentPresence.iconName(); } QString GlobalPresence::currentPresenceName() const { return m_currentPresence.displayString(); } GlobalPresence::ConnectionPresenceType GlobalPresence::currentPresenceType() const { switch(m_currentPresence.type()) { case Tp::ConnectionPresenceTypeAvailable: return GlobalPresence::Available; case Tp::ConnectionPresenceTypeBusy: return GlobalPresence::Busy; case Tp::ConnectionPresenceTypeAway: return GlobalPresence::Away; case Tp::ConnectionPresenceTypeExtendedAway: return GlobalPresence::ExtendedAway; case Tp::ConnectionPresenceTypeHidden: return GlobalPresence::Hidden; case Tp::ConnectionPresenceTypeOffline: return GlobalPresence::Offline; default: return GlobalPresence::Unknown; } } KTp::Presence GlobalPresence::requestedPresence() const { return m_requestedPresence; } QString GlobalPresence::requestedPresenceName() const { return m_requestedPresence.displayString(); } bool GlobalPresence::isChangingPresence() const { return m_changingPresence; } KTp::Presence GlobalPresence::globalPresence() const { KTp::Presence globalPresence; globalPresence.setStatus(Tp::ConnectionPresenceTypeUnset, QLatin1String("unset"), QString()); if (m_statusHandlerInterface->property("requestedGlobalPresence").isValid()) { globalPresence = KTp::Presence(qdbus_cast(m_statusHandlerInterface->property("requestedGlobalPresence"))); } return globalPresence; } void GlobalPresence::setPresence(const KTp::Presence &presence, PresenceClass presenceClass) { if (m_enabledAccounts.isNull()) { qCWarning(KTP_COMMONINTERNALS) << "Requested presence change on empty accounts set"; return; } if (!presence.isValid()) { qCWarning(KTP_COMMONINTERNALS) << "Invalid requested presence"; return; } QDBusPendingCall call = m_statusHandlerInterface->asyncCall(QLatin1String("setRequestedGlobalPresence"), QVariant::fromValue(presence.barePresence()), QVariant::fromValue(presenceClass)); } void GlobalPresence::setPresence(GlobalPresence::ConnectionPresenceType type, QString message, PresenceClass presenceClass) { KTp::Presence presence; switch (type) { case GlobalPresence::Available: presence = KTp::Presence::available(message); break; case GlobalPresence::Busy: presence = KTp::Presence::busy(message); break; case GlobalPresence::Away: presence = KTp::Presence::away(message); break; case GlobalPresence::ExtendedAway: presence = KTp::Presence::xa(message); break; case GlobalPresence::Hidden: presence = KTp::Presence::hidden(message); break; case GlobalPresence::Offline: presence = KTp::Presence::offline(message); break; case GlobalPresence::Unknown: presence = KTp::Presence(Tp::Presence(Tp::ConnectionPresenceTypeUnknown, QLatin1String("unknown"), message)); break; case GlobalPresence::Unset: presence = KTp::Presence(Tp::Presence(Tp::ConnectionPresenceTypeUnset, QLatin1String("unset"), message)); break; default: qCDebug(KTP_COMMONINTERNALS) << "You should not be here!"; } setPresence(presence, presenceClass); } void GlobalPresence::onAccountEnabledChanged(const Tp::AccountPtr &account) { if (account->isEnabled()) { connect(account.data(), &Tp::Account::connectionStatusChanged, this, &GlobalPresence::onConnectionStatusChanged); connect(account.data(), &Tp::Account::changingPresence, this, &GlobalPresence::onChangingPresence); connect(account.data(), &Tp::Account::requestedPresenceChanged, this, &GlobalPresence::onRequestedPresenceChanged); connect(account.data(), &Tp::Account::currentPresenceChanged, this, &GlobalPresence::onCurrentPresenceChanged); } else { disconnect(account.data()); } onCurrentPresenceChanged(account->currentPresence()); onRequestedPresenceChanged(account->requestedPresence()); onChangingPresence(account->isChangingPresence()); onConnectionStatusChanged(account->connectionStatus()); if (m_hasEnabledAccounts != !m_enabledAccounts.data()->accounts().isEmpty()) { m_hasEnabledAccounts = !m_enabledAccounts.data()->accounts().isEmpty(); Q_EMIT enabledAccountsChanged(m_hasEnabledAccounts); } qCDebug(KTP_COMMONINTERNALS) << "Account" << account->uniqueIdentifier() << "enabled:" << account->isEnabled(); } void GlobalPresence::onCurrentPresenceChanged(const Tp::Presence ¤tPresence) { /* basic idea of choosing global presence it to make it reflects the presence * over all accounts, usually this is used to indicates user the whole system * status. * * If there isn't any account, currentPresence should be offline, since there is nothing * online. * If there's only one account, then currentPresence should represent the presence * of this account. * If there're more than one accounts, the situation is more complicated. * There can be some accounts is still connecting (thus it's offline), and there can be * some accounts doesn't support the presence you're choosing. The user-chosen presence * priority will be higher than standard presence order. * * Example: * user choose to be online, 1 account online, 1 account offline, current presence * should be online, since online priority is higher than offline. * user chooses a presence supported by part of the account, current presence will be * the one chosen by user, to indicate there is at least one account supports it. * user choose a presence supported by no account, current presence will be chosen * from all accounts based on priority, and it also indicates there is no account support * the user-chosen presence. */ KTp::Presence highestCurrentPresence = KTp::Presence::offline(); if (m_currentPresence == KTp::Presence(currentPresence)) { return; } else { for (const Tp::AccountPtr &account : m_enabledAccounts->accounts()) { if (KTp::Presence(account->currentPresence()) > highestCurrentPresence) { highestCurrentPresence = KTp::Presence(account->currentPresence()); } } } if (m_currentPresence != highestCurrentPresence) { m_currentPresence = highestCurrentPresence; Q_EMIT currentPresenceChanged(m_currentPresence); qCDebug(KTP_COMMONINTERNALS) << "Current presence changed:" << m_currentPresence.status() << m_currentPresence.statusMessage(); } } void GlobalPresence::onRequestedPresenceChanged(const Tp::Presence &requestedPresence) { KTp::Presence highestRequestedPresence = KTp::Presence::offline(); if (m_requestedPresence == KTp::Presence(requestedPresence)) { return; } else { for (const Tp::AccountPtr &account : m_enabledAccounts->accounts()) { if (KTp::Presence(account->requestedPresence()) > highestRequestedPresence) { highestRequestedPresence = KTp::Presence(account->requestedPresence()); } } } if (m_requestedPresence != highestRequestedPresence) { m_requestedPresence = highestRequestedPresence; Q_EMIT requestedPresenceChanged(m_requestedPresence); qCDebug(KTP_COMMONINTERNALS) << "Requested presence changed:" << m_requestedPresence.status() << m_requestedPresence.statusMessage(); } } void GlobalPresence::onChangingPresence(bool isChangingPresence) { bool changing = false; if (m_changingPresence == isChangingPresence) { return; } else { for (const Tp::AccountPtr &account : m_enabledAccounts->accounts()) { changing = account->isChangingPresence(); if (account->isChangingPresence()) { break; } } } if (m_changingPresence != changing) { m_changingPresence = changing; Q_EMIT changingPresence(m_changingPresence); qCDebug(KTP_COMMONINTERNALS) << "Presence changing:" << m_changingPresence; } } void GlobalPresence::onConnectionStatusChanged(Tp::ConnectionStatus connectionStatus) { GlobalPresence::ConnectionStatus changedConnectionStatus = GlobalPresence::Disconnected; QList accountConnectionStatuses; bool hasConnectionError = false; if (m_connectionStatus == ConnectionStatus(connectionStatus)) { return; } else { for (const Tp::AccountPtr &account : m_enabledAccounts->accounts()) { accountConnectionStatuses << ConnectionStatus(account->connectionStatus()); if (!account->connectionError().isEmpty()) { hasConnectionError = true; } } } if (accountConnectionStatuses.contains(GlobalPresence::Connecting)) { changedConnectionStatus = GlobalPresence::Connecting; } else if (accountConnectionStatuses.contains(GlobalPresence::Connected)) { changedConnectionStatus = GlobalPresence::Connected; } m_hasConnectionError = hasConnectionError; if (m_connectionStatus != changedConnectionStatus) { m_connectionStatus = changedConnectionStatus; Q_EMIT connectionStatusChanged(m_connectionStatus); qCDebug(KTP_COMMONINTERNALS) << "Connection status changed:" << m_connectionStatus; } } bool GlobalPresence::hasEnabledAccounts() const { return m_hasEnabledAccounts; } bool GlobalPresence::hasConnectionError() const { return m_hasConnectionError; } Tp::AccountSetPtr GlobalPresence::onlineAccounts() const { return m_onlineAccounts; } Tp::AccountSetPtr GlobalPresence::enabledAccounts() const { return m_enabledAccounts; } } - - -#include "global-presence.moc"