Verified Commit b8206556 authored by Linus Jahn's avatar Linus Jahn
Browse files

Rewrite PresenceHandler/PresenceCache to QXmpp

parent 5850ae61
......@@ -13,7 +13,6 @@ set(KAIDAN_SOURCES
${CURDIR}/MessageModel.cpp
${CURDIR}/Notifications.cpp
${CURDIR}/PresenceCache.cpp
# ${CURDIR}/PresenceHandler.cpp
# ${CURDIR}/ServiceDiscoveryManager.cpp
# ${CURDIR}/UploadHandler.cpp
# ${CURDIR}/VCardManager.cpp
......
......@@ -53,6 +53,9 @@ ClientWorker::ClientWorker(Caches *caches, Kaidan *kaidan, bool enableLogging, Q
rosterManager = new RosterManager(kaidan, client, caches->rosterModel, this);
msgHandler = new MessageHandler(kaidan, client, caches->msgModel, this);
connect(client, &QXmppClient::presenceReceived,
caches->presCache, &PresenceCache::updatePresenceRequested);
connect(this, &ClientWorker::credentialsUpdated, this, &ClientWorker::setCredentials);
}
......
......@@ -86,6 +86,21 @@ namespace Enums {
MessageDocument
};
Q_ENUM_NS(MessageType)
/**
* Enumeration of contact availability states
*/
enum class AvailabilityTypes : quint8 {
PresError,
PresUnavailable,
PresOnline,
PresAway,
PresXA,
PresDND,
PresChat,
PresInvisible
};
Q_ENUM_NS(AvailabilityTypes)
}
// Needed workaround to trigger older CMake auto moc versions to generate moc
......
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2017-2018 Kaidan developers and contributors
* Copyright (C) 2016-2018 Kaidan developers and contributors
* (see the LICENSE file for a full list of copyright authors)
*
* Kaidan is free software: you can redistribute it and/or modify
......@@ -29,67 +29,70 @@
*/
#include "PresenceCache.h"
#include "Enums.h"
#include <QXmppUtils.h>
using namespace Enums;
PresenceCache::PresenceCache(QObject *parent) : QObject(parent)
{
connect(this, &PresenceCache::presenceArrived, this, &PresenceCache::updatePresence);
connect(this, &PresenceCache::updatePresenceRequested, this, &PresenceCache::updatePresence);
}
PresenceCache::~PresenceCache()
void PresenceCache::updatePresence(QXmppPresence presence)
{
for (auto &key : presences.keys()) {
delete presences[key];
presences.remove(key);
}
}
if (presence.type() != QXmppPresence::Available &&
presence.type() != QXmppPresence::Unavailable/* &&
presence.type() != QXmppPresence::Error*/)
return;
QString jid = QXmppUtils::jidToBareJid(presence.from());
QString resource = QXmppUtils::jidToResource(presence.from());
void PresenceCache::updatePresence(QString jid, QString resource,
gloox::Presence::PresenceType type, QString status)
{
if (!presences.contains(jid))
presences[jid] = new ContactPresences(jid);
presences[jid] = QMap<QString, QXmppPresence>();
presences[jid]->getResourcePresence(resource)->setType(type);
presences[jid]->getResourcePresence(resource)->setStatus(status);
presences[jid][resource] = presence;
emit presenceChanged(jid);
}
QString PresenceCache::getDefaultStatus(QString jid)
{
if (!presences.contains(jid))
presences[jid] = new ContactPresences(jid);
return presences[jid]->getDefaultPresence()->getStatus();
}
quint8 PresenceCache::getDefaultPresType(QString jid)
quint8 PresenceCache::getPresenceType(QString bareJid)
{
if (!presences.contains(jid))
presences[jid] = new ContactPresences(jid);
if (!presences.contains(bareJid))
return (quint8) AvailabilityTypes::PresUnavailable;
return presences[jid]->getDefaultPresence()->getType();
}
QXmppPresence pres = presences[bareJid].last();
ContactPresences::ContactPresences(QString jid, QObject* parent)
: jid(jid), defaultPresence(new EntityPresence(gloox::Presence::Unavailable, "")),
QObject(parent)
{
}
ContactPresences::~ContactPresences()
{
for (auto &key : presences.keys()) {
delete presences[key];
presences.remove(key);
if (pres.type() == QXmppPresence::Unavailable) {
return (quint8) AvailabilityTypes::PresUnavailable;
} else if (pres.type() == QXmppPresence::Available) {
switch (pres.availableStatusType()) {
case QXmppPresence::Online:
return (quint8) AvailabilityTypes::PresOnline;
case QXmppPresence::Away:
return (quint8) AvailabilityTypes::PresAway;
case QXmppPresence::XA:
return (quint8) AvailabilityTypes::PresXA;
case QXmppPresence::DND:
return (quint8) AvailabilityTypes::PresDND;
case QXmppPresence::Chat:
return (quint8) AvailabilityTypes::PresChat;
case QXmppPresence::Invisible:
return (quint8) AvailabilityTypes::PresInvisible;
default:
return (quint8) AvailabilityTypes::PresUnavailable;
}
} else if (pres.type() == QXmppPresence::Error) {
return (quint8) AvailabilityTypes::PresError;
}
return (quint8) AvailabilityTypes::PresUnavailable;
}
QQmlListProperty<QString> ContactPresences::getResources()
QString PresenceCache::getStatusText(QString bareJid)
{
QList<QString*> qList;
for (auto &key : presences.keys()) {
qList << &key;
}
return QQmlListProperty<QString>((QObject*) this, qList);
if (!presences.contains(bareJid))
return "";
return presences[bareJid].last().statusText();
}
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2017-2018 Kaidan developers and contributors
* Copyright (C) 2016-2018 Kaidan developers and contributors
* (see the LICENSE file for a full list of copyright authors)
*
* Kaidan is free software: you can redistribute it and/or modify
......@@ -34,99 +34,7 @@
#include <QObject>
#include <QMap>
#include <QQmlListProperty>
#include <gloox/presence.h>
/**
* @class EntityPresence Holds a presence for a single XMPP entity (JID with resource)
*/
class EntityPresence : public QObject
{
Q_OBJECT
Q_PROPERTY(quint8 type READ getType NOTIFY typeChanged)
Q_PROPERTY(QString status READ getStatus NOTIFY statusChanged)
public:
EntityPresence(gloox::Presence::PresenceType type, QString status)
: type(type), status(status)
{
}
quint8 getType() const
{
return (quint8) type;
}
void setType(quint8 type)
{
this->type = (gloox::Presence::PresenceType) type;
emit typeChanged();
}
QString getStatus() const
{
return status;
}
void setStatus(QString status)
{
this->status = status;
emit statusChanged();
}
signals:
void typeChanged();
void statusChanged();
private:
gloox::Presence::PresenceType type;
QString status;
};
/**
* @class ContactPresences Holds presences for each resource of a JID
*/
class ContactPresences : public QObject
{
Q_OBJECT
Q_PROPERTY(QQmlListProperty<QString> resources READ getResources NOTIFY resourcesChanged)
public:
ContactPresences(QString jid, QObject *parent = nullptr);
~ContactPresences();
QQmlListProperty<QString> getResources();
Q_INVOKABLE EntityPresence* getResourcePresence(QString resource)
{
if (!presences.contains(resource))
presences[resource] = new EntityPresence(gloox::Presence::Unavailable, QString());
return presences[resource];
}
Q_INVOKABLE QString getDefaultResource()
{
if (!presences.empty())
return presences.firstKey();
else
return "";
}
Q_INVOKABLE EntityPresence* getDefaultPresence()
{
if (!presences.empty())
return presences.first();
else
return defaultPresence;
}
signals:
void resourcesChanged();
private:
QMap<QString, EntityPresence*> presences;
QString jid;
EntityPresence *defaultPresence;
};
#include <QXmppPresence.h>
/**
* @class PresenceCache A cache for presence holders for certain JIDs
......@@ -136,43 +44,37 @@ class PresenceCache : public QObject
Q_OBJECT
public:
/**
* Default constructor
*/
PresenceCache(QObject *parent = nullptr);
/**
* Destructor
* Return one of the status texts from all resources
*/
~PresenceCache();
Q_INVOKABLE QString getStatusText(QString bareJid);
/**
* Get presences of a certain JID
* @param jid Account address of the presences
* Returns one of the presence types from all resources
*/
Q_INVOKABLE ContactPresences* getPresences(QString jid)
{
if (!presences.contains(jid))
presences[jid] = new ContactPresences(jid);
return presences[jid];
}
Q_INVOKABLE QString getDefaultStatus(QString jid);
Q_INVOKABLE quint8 getDefaultPresType(QString jid);
Q_INVOKABLE quint8 getPresenceType(QString bareJid);
signals:
void presenceArrived(QString jid, QString resource,
gloox::Presence::PresenceType type, QString status);
/**
* Notifies about changed presences
*/
void presenceChanged(QString jid);
/**
* Is connected to updatePresence
*/
void updatePresenceRequested(QXmppPresence presence);
private slots:
void updatePresence(QString jid, QString resource,
gloox::Presence::PresenceType type, QString status);
/**
* @brief Updates the presence cache, it will ignore subscribe presences
*/
void updatePresence(QXmppPresence presence);
private:
QMap<QString, ContactPresences*> presences;
QMap<QString, QMap<QString, QXmppPresence>> presences;
};
#endif // PRESENCECACHE_H
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2017-2018 Kaidan developers and contributors
* (see the LICENSE file for a full list of copyright authors)
*
* Kaidan is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, as a special exception, the author of Kaidan gives
* permission to link the code of its release with the OpenSSL
* project's "OpenSSL" library (or with modified versions of it that
* use the same license as the "OpenSSL" library), and distribute the
* linked executables. You must obey the GNU General Public License in
* all respects for all of the code used other than "OpenSSL". If you
* modify this file, you may extend this exception to your version of
* the file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
* Kaidan 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kaidan. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PresenceHandler.h"
#include "PresenceCache.h"
#include <QDebug>
PresenceHandler::PresenceHandler(gloox::Client *client, PresenceCache *cache)
: client(client), cache(cache)
{
client->registerPresenceHandler(this);
}
PresenceHandler::~PresenceHandler()
{
}
void PresenceHandler::handlePresence(const gloox::Presence &presence)
{
// Subscription requests are now managed in the RosterUpdater
emit cache->presenceArrived(
QString::fromStdString(presence.from().bare()),
QString::fromStdString(presence.from().resource()),
presence.subtype(), QString::fromStdString(presence.status())
);
}
/*
* Kaidan - A user-friendly XMPP client for every device!
*
* Copyright (C) 2017-2018 Kaidan developers and contributors
* (see the LICENSE file for a full list of copyright authors)
*
* Kaidan is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* In addition, as a special exception, the author of Kaidan gives
* permission to link the code of its release with the OpenSSL
* project's "OpenSSL" library (or with modified versions of it that
* use the same license as the "OpenSSL" library), and distribute the
* linked executables. You must obey the GNU General Public License in
* all respects for all of the code used other than "OpenSSL". If you
* modify this file, you may extend this exception to your version of
* the file, but you are not obligated to do so. If you do not wish to
* do so, delete this exception statement from your version.
*
* Kaidan 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kaidan. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PRESENCEHANDLER_H
#define PRESENCEHANDLER_H
#include <QObject>
#include <gloox/client.h>
#include <gloox/presence.h>
#include <gloox/presencehandler.h>
class PresenceCache;
class PresenceHandler : public gloox::PresenceHandler
{
public:
PresenceHandler(gloox::Client *client, PresenceCache *cache);
~PresenceHandler();
virtual void handlePresence(const gloox::Presence &presence);
private:
gloox::Client *client;
PresenceCache *cache;
};
#endif // PRESENCEHANDLER_H
......@@ -154,8 +154,7 @@ Q_DECL_EXPORT int main(int argc, char *argv[])
qRegisterMetaType<AvatarFileStorage*>("AvatarFileStorage*");
qRegisterMetaType<ContactMap>("ContactMap");
qRegisterMetaType<PresenceCache*>("PresenceCache*");
qRegisterMetaType<ContactPresences*>("ContactPresences*");
qRegisterMetaType<EntityPresence*>("EntityPresence*");
qRegisterMetaType<QXmppPresence>("QXmppPresence");
qRegisterMetaType<ClientWorker::Credentials>("Credentials");
qRegisterMetaType<Qt::ApplicationState>("Qt::ApplicationState");
qRegisterMetaType<QXmppClient::State>("QXmppClient::State");
......
......@@ -69,8 +69,8 @@ Kirigami.ScrollablePage {
name: model.name ? model.name : model.jid
jid: model.jid
lastMessage: model.lastMessage
presenceType: kaidan.presenceCache.getDefaultPresType(model.jid)
statusMsg: kaidan.presenceCache.getDefaultStatus(model.jid)
presenceType: kaidan.presenceCache.getPresenceType(model.jid)
statusMsg: kaidan.presenceCache.getStatusText(model.jid)
unreadMessages: model.unreadMessages
avatarImagePath: kaidan.avatarStorage.getHashOfJid(model.jid) !== "" ?
kaidan.avatarStorage.getAvatarUrl(model.jid) :
......@@ -105,9 +105,9 @@ Kirigami.ScrollablePage {
function newPresenceArrived(jid) {
if (jid === model.jid) {
rosterItem.presenceType = kaidan.presenceCache.
getDefaultPresType(model.jid)
getPresenceType(model.jid)
rosterItem.statusMsg = kaidan.presenceCache.
getDefaultStatus(model.jid)
getStatusText(model.jid)
}
}
......
......@@ -33,6 +33,7 @@ import QtQuick.Layouts 1.3
import QtQuick.Controls 2.0 as Controls
import QtGraphicalEffects 1.0
import org.kde.kirigami 2.0 as Kirigami
import im.kaidan.kaidan 1.0
Kirigami.SwipeListItem {
id: listItem
......@@ -120,7 +121,7 @@ Kirigami.SwipeListItem {
elide: Text.ElideRight
maximumLineCount: 1
text: {
presenceType === 7 ? // error presence type
presenceType === Enums.PresError ? // error presence type
qsTr("Error: Please check the JID.") :
kaidan.removeNewLinesFromString(lastMessage)
}
......@@ -144,14 +145,13 @@ Kirigami.SwipeListItem {
* Returns the colour beloning to the given presence status type
*/
function presenceTypeToColor(type) {
return type === 0 ? "green" : // available
type === 1 ? "darkgreen" : // chat
type === 2 ? "orange" : // away
type === 3 ? "orange" : // do not disturb
type === 4 ? "orange" : // extended away
type === 7 ? "red" : // error
type === 6 ? "red" : // error
"lightgrey" // unavailable (offline) (5), probe (6), invalid (8)
return type === Enums.PresOnline ? "green" :
type === Enums.PresChat ? "darkgreen" :
type === Enums.PresAway ? "orange" :
type === Enums.PresDND ? "orange" :
type === Enums.PresXA ? "orange" :
type === Enums.PresError ? "red" :
"lightgrey" // unavailable (offline)
}
/**
......@@ -168,14 +168,14 @@ Kirigami.SwipeListItem {
// presence status type
string += "<font color='" + presenceTypeToColor(statusType) + "'>"
string += statusType === 0 ? qsTr("Available") :
statusType === 1 ? qsTr("Free for chat") :
statusType === 2 ? qsTr("Away") :
statusType === 3 ? qsTr("Do not disturb") :
statusType === 4 ? qsTr("Away for longer") :
statusType === 5 ? qsTr("Offline") :
statusType === 7 ? qsTr("Error") :
qsTr("Invalid")
string += statusType === Enums.PresOnline ? qsTr("Available") :
statusType === Enums.PresChat ? qsTr("Free for chat") :
statusType === Enums.PresAway ? qsTr("Away") :
statusType === Enums.PresDND ? qsTr("Do not disturb") :
statusType === Enums.PresXA ? qsTr("Away for longer") :
statusType === Enums.PresUnavailable ? qsTr("Offline") :
statusType === Enums.PresError ? qsTr("Error") :
"Invalid" // should never be displayed
string += "</font>"
// presence status message
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment