forked from blue/squawk
Basic presence with subnodes
This commit is contained in:
parent
de21036456
commit
e8eaced6e9
@ -1,5 +1,6 @@
|
|||||||
#include "account.h"
|
#include "account.h"
|
||||||
#include <qxmpp/QXmppRosterManager.h>
|
#include <qxmpp/QXmppRosterManager.h>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
using namespace Core;
|
using namespace Core;
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
|||||||
{
|
{
|
||||||
QObject::connect(&client, SIGNAL(connected()), this, SLOT(onClientConnected()));
|
QObject::connect(&client, SIGNAL(connected()), this, SLOT(onClientConnected()));
|
||||||
QObject::connect(&client, SIGNAL(disconnected()), this, SLOT(onClientDisconnected()));
|
QObject::connect(&client, SIGNAL(disconnected()), this, SLOT(onClientDisconnected()));
|
||||||
|
QObject::connect(&client, SIGNAL(presenceReceived(const QXmppPresence&)), this, SLOT(onPresenceReceived(const QXmppPresence&)));
|
||||||
|
|
||||||
QXmppRosterManager& rm = client.rosterManager();
|
QXmppRosterManager& rm = client.rosterManager();
|
||||||
|
|
||||||
@ -23,6 +24,7 @@ Account::Account(const QString& p_login, const QString& p_server, const QString&
|
|||||||
QObject::connect(&rm, SIGNAL(itemAdded(const QString&)), this, SLOT(onRosterItemAdded(const QString&)));
|
QObject::connect(&rm, SIGNAL(itemAdded(const QString&)), this, SLOT(onRosterItemAdded(const QString&)));
|
||||||
QObject::connect(&rm, SIGNAL(itemRemoved(const QString&)), this, SLOT(onRosterItemRemoved(const QString&)));
|
QObject::connect(&rm, SIGNAL(itemRemoved(const QString&)), this, SLOT(onRosterItemRemoved(const QString&)));
|
||||||
QObject::connect(&rm, SIGNAL(itemChanged(const QString&)), this, SLOT(onRosterItemChanged(const QString&)));
|
QObject::connect(&rm, SIGNAL(itemChanged(const QString&)), this, SLOT(onRosterItemChanged(const QString&)));
|
||||||
|
//QObject::connect(&rm, SIGNAL(presenceChanged(const QString&, const QString&)), this, SLOT(onRosterPresenceChanged(const QString&, const QString&)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Account::~Account()
|
Account::~Account()
|
||||||
@ -116,6 +118,9 @@ void Core::Account::onRosterItemChanged(const QString& bareJid)
|
|||||||
QSet<QString> newGroups = re.groups();
|
QSet<QString> newGroups = re.groups();
|
||||||
QSet<QString> oldGroups;
|
QSet<QString> oldGroups;
|
||||||
|
|
||||||
|
|
||||||
|
QStringList res = rm.getResources(bareJid);
|
||||||
|
|
||||||
emit changeContact(bareJid, re.name());
|
emit changeContact(bareJid, re.name());
|
||||||
|
|
||||||
for (std::map<QString, std::set<QString>>::iterator itr = groups.begin(), end = groups.end(); itr != end; ++itr) {
|
for (std::map<QString, std::set<QString>>::iterator itr = groups.begin(), end = groups.end(); itr != end; ++itr) {
|
||||||
@ -204,3 +209,50 @@ void Core::Account::addedAccount(const QString& jid)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Core::Account::onPresenceReceived(const QXmppPresence& presence)
|
||||||
|
{
|
||||||
|
QString id = presence.from();
|
||||||
|
QStringList comps = id.split("/");
|
||||||
|
QString jid = comps.front();
|
||||||
|
QString resource = comps.back();
|
||||||
|
|
||||||
|
switch (presence.type()) {
|
||||||
|
case QXmppPresence::Error:
|
||||||
|
qDebug() << "An error reported by presence from " << id;
|
||||||
|
break;
|
||||||
|
case QXmppPresence::Available:{
|
||||||
|
QDateTime lastInteraction = presence.lastUserInteraction();
|
||||||
|
if (!lastInteraction.isValid()) {
|
||||||
|
lastInteraction = QDateTime::currentDateTime();
|
||||||
|
}
|
||||||
|
emit addPresence(jid, resource, {
|
||||||
|
{"lastActivity", lastInteraction},
|
||||||
|
{"availability", presence.availableStatusType()}, //TODO check and handle invisible
|
||||||
|
{"status", presence.statusText()}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QXmppPresence::Unavailable:
|
||||||
|
emit removePresence(jid, resource);
|
||||||
|
break;
|
||||||
|
case QXmppPresence::Subscribe:
|
||||||
|
qDebug("xmpp presence \"subscribe\" received, do not yet know what to do, skipping");
|
||||||
|
case QXmppPresence::Subscribed:
|
||||||
|
qDebug("xmpp presence \"subscribed\" received, do not yet know what to do, skipping");
|
||||||
|
case QXmppPresence::Unsubscribe:
|
||||||
|
qDebug("xmpp presence \"unsubscribe\" received, do not yet know what to do, skipping");
|
||||||
|
case QXmppPresence::Unsubscribed:
|
||||||
|
qDebug("xmpp presence \"unsubscribed\" received, do not yet know what to do, skipping");
|
||||||
|
case QXmppPresence::Probe:
|
||||||
|
qDebug("xmpp presence \"probe\" received, do not yet know what to do, skipping");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::Account::onRosterPresenceChanged(const QString& bareJid, const QString& resource)
|
||||||
|
{
|
||||||
|
//not used for now;
|
||||||
|
qDebug() << "presence changed for " << bareJid << " resource " << resource;
|
||||||
|
const QXmppPresence& presence = client.rosterManager().getPresence(bareJid, resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -35,6 +35,8 @@ signals:
|
|||||||
void removeContact(const QString& jid);
|
void removeContact(const QString& jid);
|
||||||
void removeContact(const QString& jid, const QString& group);
|
void removeContact(const QString& jid, const QString& group);
|
||||||
void changeContact(const QString& jid, const QString& name);
|
void changeContact(const QString& jid, const QString& name);
|
||||||
|
void addPresence(const QString& jid, const QString& name, const QMap<QString, QVariant>& data);
|
||||||
|
void removePresence(const QString& jid, const QString& name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString name;
|
QString name;
|
||||||
@ -52,6 +54,8 @@ private slots:
|
|||||||
void onRosterItemAdded(const QString& bareJid);
|
void onRosterItemAdded(const QString& bareJid);
|
||||||
void onRosterItemChanged(const QString& bareJid);
|
void onRosterItemChanged(const QString& bareJid);
|
||||||
void onRosterItemRemoved(const QString& bareJid);
|
void onRosterItemRemoved(const QString& bareJid);
|
||||||
|
void onRosterPresenceChanged(const QString& bareJid, const QString& resource);
|
||||||
|
void onPresenceReceived(const QXmppPresence& presence);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addedAccount(const QString &bareJid);
|
void addedAccount(const QString &bareJid);
|
||||||
|
@ -80,6 +80,9 @@ void Core::Squawk::addAccount(const QString& login, const QString& server, const
|
|||||||
connect(acc, SIGNAL(removeContact(const QString&)), this, SLOT(onAccountRemoveContact(const QString&)));
|
connect(acc, SIGNAL(removeContact(const QString&)), this, SLOT(onAccountRemoveContact(const QString&)));
|
||||||
connect(acc, SIGNAL(removeContact(const QString&, const QString&)), this, SLOT(onAccountRemoveContact(const QString&, const QString&)));
|
connect(acc, SIGNAL(removeContact(const QString&, const QString&)), this, SLOT(onAccountRemoveContact(const QString&, const QString&)));
|
||||||
connect(acc, SIGNAL(changeContact(const QString&, const QString&)), this, SLOT(onAccountChangeContact(const QString&, const QString&)));
|
connect(acc, SIGNAL(changeContact(const QString&, const QString&)), this, SLOT(onAccountChangeContact(const QString&, const QString&)));
|
||||||
|
connect(acc, SIGNAL(addPresence(const QString&, const QString&, const QMap<QString, QVariant>&)),
|
||||||
|
this, SLOT(onAccountAddPresence(const QString&, const QString&, const QMap<QString, QVariant>&)));
|
||||||
|
connect(acc, SIGNAL(removePresence(const QString&, const QString&)), this, SLOT(onAccountRemovePresence(const QString&, const QString&)));
|
||||||
|
|
||||||
QMap<QString, QVariant> map = {
|
QMap<QString, QVariant> map = {
|
||||||
{"login", login},
|
{"login", login},
|
||||||
@ -153,3 +156,15 @@ void Core::Squawk::onAccountRemoveContact(const QString& jid, const QString& gro
|
|||||||
Account* acc = static_cast<Account*>(sender());
|
Account* acc = static_cast<Account*>(sender());
|
||||||
emit removeContact(acc->getName(), jid, group);
|
emit removeContact(acc->getName(), jid, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Core::Squawk::onAccountAddPresence(const QString& jid, const QString& name, const QMap<QString, QVariant>& data)
|
||||||
|
{
|
||||||
|
Account* acc = static_cast<Account*>(sender());
|
||||||
|
emit addPresence(acc->getName(), jid, name, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::Squawk::onAccountRemovePresence(const QString& jid, const QString& name)
|
||||||
|
{
|
||||||
|
Account* acc = static_cast<Account*>(sender());
|
||||||
|
emit removePresence(acc->getName(), jid, name);
|
||||||
|
}
|
||||||
|
@ -31,6 +31,8 @@ signals:
|
|||||||
void removeContact(const QString& account, const QString& jid);
|
void removeContact(const QString& account, const QString& jid);
|
||||||
void removeContact(const QString& account, const QString& jid, const QString& group);
|
void removeContact(const QString& account, const QString& jid, const QString& group);
|
||||||
void changeContact(const QString& account, const QString& jid, const QString& name);
|
void changeContact(const QString& account, const QString& jid, const QString& name);
|
||||||
|
void addPresence(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data);
|
||||||
|
void removePresence(const QString& account, const QString& jid, const QString& name);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void start();
|
void start();
|
||||||
@ -57,6 +59,8 @@ private slots:
|
|||||||
void onAccountRemoveContact(const QString& jid);
|
void onAccountRemoveContact(const QString& jid);
|
||||||
void onAccountRemoveContact(const QString& jid, const QString& group);
|
void onAccountRemoveContact(const QString& jid, const QString& group);
|
||||||
void onAccountChangeContact(const QString& jid, const QString& name);
|
void onAccountChangeContact(const QString& jid, const QString& name);
|
||||||
|
void onAccountAddPresence(const QString& jid, const QString& name, const QMap<QString, QVariant>& data);
|
||||||
|
void onAccountRemovePresence(const QString& jid, const QString& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
12
global.h
12
global.h
@ -13,6 +13,18 @@ enum ConnectionState {
|
|||||||
error
|
error
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Availability {
|
||||||
|
online,
|
||||||
|
away,
|
||||||
|
extendedAway,
|
||||||
|
busy,
|
||||||
|
chatty,
|
||||||
|
offline
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Availability availabilityHighest = offline;
|
||||||
|
static const Availability availabilityLowest = online;
|
||||||
|
|
||||||
static const std::deque<QString> ConnectionStateNames = {"Disconnected", "Connecting", "Connected", "Error"};
|
static const std::deque<QString> ConnectionStateNames = {"Disconnected", "Connecting", "Connected", "Error"};
|
||||||
static const std::deque<QString> ConnectionStateThemeIcons = {"network-disconnect", "view-refresh", "network-connect", "state-error"};
|
static const std::deque<QString> ConnectionStateThemeIcons = {"network-disconnect", "view-refresh", "network-connect", "state-error"};
|
||||||
|
|
||||||
|
3
main.cpp
3
main.cpp
@ -41,6 +41,9 @@ int main(int argc, char *argv[])
|
|||||||
QObject::connect(squawk, SIGNAL(removeContact(const QString&, const QString&)), &w, SLOT(removeContact(const QString&, const QString&)));
|
QObject::connect(squawk, SIGNAL(removeContact(const QString&, const QString&)), &w, SLOT(removeContact(const QString&, const QString&)));
|
||||||
QObject::connect(squawk, SIGNAL(removeContact(const QString&, const QString&, const QString&)), &w, SLOT(removeContact(const QString&, const QString&, const QString&)));
|
QObject::connect(squawk, SIGNAL(removeContact(const QString&, const QString&, const QString&)), &w, SLOT(removeContact(const QString&, const QString&, const QString&)));
|
||||||
QObject::connect(squawk, SIGNAL(changeContact(const QString&, const QString&, const QString&)), &w, SLOT(changeContact(const QString&, const QString&, const QString&)));
|
QObject::connect(squawk, SIGNAL(changeContact(const QString&, const QString&, const QString&)), &w, SLOT(changeContact(const QString&, const QString&, const QString&)));
|
||||||
|
QObject::connect(squawk, SIGNAL(addPresence(const QString&, const QString&, const QString&, const QMap<QString, QVariant>&)),
|
||||||
|
&w, SLOT(addPresence(const QString&, const QString&, const QString&, const QMap<QString, QVariant>&)));
|
||||||
|
QObject::connect(squawk, SIGNAL(removePresence(const QString&, const QString&, const QString&)), &w, SLOT(removePresence(const QString&, const QString&, const QString&)));
|
||||||
|
|
||||||
coreThread->start();
|
coreThread->start();
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ set(squawkUI_SRC
|
|||||||
models/item.cpp
|
models/item.cpp
|
||||||
models/account.cpp
|
models/account.cpp
|
||||||
models/contact.cpp
|
models/contact.cpp
|
||||||
|
models/presence.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# Tell CMake to create the helloworld executable
|
# Tell CMake to create the helloworld executable
|
||||||
|
@ -17,7 +17,7 @@ void Models::Account::setState(int p_state)
|
|||||||
{
|
{
|
||||||
if (state != p_state) {
|
if (state != p_state) {
|
||||||
state = p_state;
|
state = p_state;
|
||||||
emit changed(2);
|
changed(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ void Models::Account::setLogin(const QString& p_login)
|
|||||||
{
|
{
|
||||||
if (login != p_login) {
|
if (login != p_login) {
|
||||||
login = p_login;
|
login = p_login;
|
||||||
emit changed(3);
|
changed(3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ void Models::Account::setPassword(const QString& p_password)
|
|||||||
{
|
{
|
||||||
if (password != p_password) {
|
if (password != p_password) {
|
||||||
password = p_password;
|
password = p_password;
|
||||||
emit changed(4);
|
changed(4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ void Models::Account::setServer(const QString& p_server)
|
|||||||
{
|
{
|
||||||
if (server != p_server) {
|
if (server != p_server) {
|
||||||
server = p_server;
|
server = p_server;
|
||||||
emit changed(1);
|
changed(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,17 +63,19 @@ void Models::Accounts::addAccount(Account* account)
|
|||||||
{
|
{
|
||||||
beginInsertRows(QModelIndex(), accs.size(), accs.size());
|
beginInsertRows(QModelIndex(), accs.size(), accs.size());
|
||||||
accs.push_back(account);
|
accs.push_back(account);
|
||||||
connect(account, SIGNAL(changed(int)), this, SLOT(onAccountChanged(int)));
|
connect(account, SIGNAL(childChanged(Item*, int, int)), this, SLOT(onAccountChanged(Item*, int, int)));
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Models::Accounts::onAccountChanged(int column)
|
void Models::Accounts::onAccountChanged(Item* item, int row, int col)
|
||||||
{
|
{
|
||||||
Account* acc = static_cast<Account*>(sender());
|
Account* acc = getAccount(row);
|
||||||
|
if (item != acc) {
|
||||||
|
return; //it means the signal is emitted by one of accounts' children, not exactly him, this model has no interest in that
|
||||||
|
}
|
||||||
|
|
||||||
if (column < columnCount(QModelIndex())) {
|
if (col < columnCount(QModelIndex())) {
|
||||||
int row = acc->row();
|
emit dataChanged(createIndex(row, col, this), createIndex(row, col, this));
|
||||||
emit dataChanged(createIndex(row, column, this), createIndex(row, column, this));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ private:
|
|||||||
static std::deque<QString> columns;
|
static std::deque<QString> columns;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onAccountChanged(int column);
|
void onAccountChanged(Item* item, int row, int col);
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
#include "contact.h"
|
#include "contact.h"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
Models::Contact::Contact(const QMap<QString, QVariant>& data, Models::Item* parentItem):
|
Models::Contact::Contact(const QMap<QString, QVariant>& data, Models::Item* parentItem):
|
||||||
Item(Item::contact, data, parentItem),
|
Item(Item::contact, data, parentItem),
|
||||||
jid(data.value("jid").toString()),
|
jid(data.value("jid").toString()),
|
||||||
state(data.value("state").toInt())
|
state(Shared::offline),
|
||||||
|
presences()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,20 +22,20 @@ void Models::Contact::setJid(const QString p_jid)
|
|||||||
{
|
{
|
||||||
if (jid != p_jid) {
|
if (jid != p_jid) {
|
||||||
jid = p_jid;
|
jid = p_jid;
|
||||||
emit changed(1);
|
changed(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Models::Contact::getState() const
|
Shared::Availability Models::Contact::getState() const
|
||||||
{
|
{
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Models::Contact::setState(int p_state)
|
void Models::Contact::setState(Shared::Availability p_state)
|
||||||
{
|
{
|
||||||
if (state != p_state) {
|
if (state != p_state) {
|
||||||
state = p_state;
|
state = p_state;
|
||||||
emit changed(2);
|
changed(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,6 +69,78 @@ void Models::Contact::update(const QString& field, const QVariant& value)
|
|||||||
} else if (field == "jid") {
|
} else if (field == "jid") {
|
||||||
setJid(value.toString());
|
setJid(value.toString());
|
||||||
} else if (field == "state") {
|
} else if (field == "state") {
|
||||||
setState(value.toInt());
|
unsigned int iState = value.toUInt();
|
||||||
|
if (iState <= Shared::availabilityHighest) {
|
||||||
|
Shared::Availability state = static_cast<Shared::Availability>(iState);
|
||||||
|
setState(state);
|
||||||
|
} else {
|
||||||
|
qDebug("An attempt to set wrong state to the contact");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Contact::addPresence(const QString& p_name, const QMap<QString, QVariant>& data)
|
||||||
|
{
|
||||||
|
QMap<QString, Presence*>::iterator itr = presences.find(p_name);
|
||||||
|
|
||||||
|
if (itr == presences.end()) {
|
||||||
|
Presence* pr = new Presence(data);
|
||||||
|
pr->setName(p_name);
|
||||||
|
presences.insert(p_name, pr);
|
||||||
|
appendChild(pr);
|
||||||
|
} else {
|
||||||
|
Presence* pr = itr.value();
|
||||||
|
for (QMap<QString, QVariant>::const_iterator itr = data.begin(), end = data.end(); itr != end; ++itr) {
|
||||||
|
pr->update(itr.key(), itr.value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Contact::removePresence(const QString& name)
|
||||||
|
{
|
||||||
|
QMap<QString, Presence*>::iterator itr = presences.find(name);
|
||||||
|
|
||||||
|
if (itr == presences.end()) {
|
||||||
|
} else {
|
||||||
|
Presence* pr = itr.value();
|
||||||
|
presences.erase(itr);
|
||||||
|
removeChild(pr->row());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Contact::refresh()
|
||||||
|
{
|
||||||
|
QDateTime lastActivity;
|
||||||
|
Presence* presence = 0;
|
||||||
|
for (QMap<QString, Presence*>::iterator itr = presences.begin(), end = presences.end(); itr != end; ++itr) {
|
||||||
|
Presence* pr = itr.value();
|
||||||
|
QDateTime la = pr->getLastActivity();
|
||||||
|
|
||||||
|
if (la > lastActivity) {
|
||||||
|
lastActivity = la;
|
||||||
|
presence = pr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (presence != 0) {
|
||||||
|
setState(presence->getAvailability());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Contact::_removeChild(int index)
|
||||||
|
{
|
||||||
|
Item::_removeChild(index);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Contact::appendChild(Models::Item* child)
|
||||||
|
{
|
||||||
|
Item::appendChild(child);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Contact::changed(int col)
|
||||||
|
{
|
||||||
|
Item::changed(col);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
#define MODELS_CONTACT_H
|
#define MODELS_CONTACT_H
|
||||||
|
|
||||||
#include "item.h"
|
#include "item.h"
|
||||||
|
#include "presence.h"
|
||||||
|
#include "../../global.h"
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
namespace Models {
|
namespace Models {
|
||||||
|
|
||||||
@ -13,19 +16,32 @@ public:
|
|||||||
~Contact();
|
~Contact();
|
||||||
|
|
||||||
QString getJid() const;
|
QString getJid() const;
|
||||||
void setJid(const QString p_jid);
|
|
||||||
|
|
||||||
int getState() const;
|
Shared::Availability getState() const;
|
||||||
void setState(int p_state);
|
|
||||||
|
|
||||||
int columnCount() const override;
|
int columnCount() const override;
|
||||||
QVariant data(int column) const override;
|
QVariant data(int column) const override;
|
||||||
|
|
||||||
void update(const QString& field, const QVariant& value);
|
void update(const QString& field, const QVariant& value);
|
||||||
|
|
||||||
|
void addPresence(const QString& name, const QMap<QString, QVariant>& data);
|
||||||
|
void removePresence(const QString& name);
|
||||||
|
|
||||||
|
void appendChild(Models::Item * child) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void refresh();
|
||||||
|
void changed(int col) override;
|
||||||
|
void _removeChild(int index) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setState(Shared::Availability p_state);
|
||||||
|
void setJid(const QString p_jid);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString jid;
|
QString jid;
|
||||||
int state;
|
Shared::Availability state;
|
||||||
|
QMap<QString, Presence*> presences;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
#include "item.h"
|
#include "item.h"
|
||||||
|
|
||||||
using namespace Models;
|
|
||||||
|
|
||||||
Models::Item::Item(Type p_type, const QMap<QString, QVariant> &p_data, Item *p_parent):
|
Models::Item::Item(Type p_type, const QMap<QString, QVariant> &p_data, Item *p_parent):
|
||||||
QObject(),
|
QObject(),
|
||||||
type(p_type),
|
type(p_type),
|
||||||
@ -24,13 +22,38 @@ void Models::Item::setName(const QString& p_name)
|
|||||||
{
|
{
|
||||||
if (name != p_name) {
|
if (name != p_name) {
|
||||||
name = p_name;
|
name = p_name;
|
||||||
emit changed(0);
|
changed(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Models::Item::appendChild(Models::Item* child)
|
void Models::Item::appendChild(Models::Item* child)
|
||||||
{
|
{
|
||||||
|
bool moving = false;
|
||||||
|
int oldRow = child->row();
|
||||||
|
int newRow = this->childCount();
|
||||||
|
if (child->parent != 0) {
|
||||||
|
moving = true;
|
||||||
|
emit childIsAboutToBeMoved(child->parent, oldRow, oldRow, this, newRow);
|
||||||
|
child->parent->_removeChild(oldRow);
|
||||||
|
} else {
|
||||||
|
emit childIsAboutToBeInserted(this, newRow, newRow);
|
||||||
|
}
|
||||||
childItems.push_back(child);
|
childItems.push_back(child);
|
||||||
|
child->parent = this;
|
||||||
|
|
||||||
|
QObject::connect(child, SIGNAL(childChanged(Item*, int, int)), this, SIGNAL(childChanged(Item*, int, int)));
|
||||||
|
QObject::connect(child, SIGNAL(childIsAboutToBeInserted(Item*, int, int)), this, SIGNAL(childIsAboutToBeInserted(Item*, int, int)));
|
||||||
|
QObject::connect(child, SIGNAL(childInserted()), this, SIGNAL(childInserted()));
|
||||||
|
QObject::connect(child, SIGNAL(childIsAboutToBeRemoved(Item*, int, int)), this, SIGNAL(childIsAboutToBeRemoved(Item*, int, int)));
|
||||||
|
QObject::connect(child, SIGNAL(childRemoved()), this, SIGNAL(childRemoved()));
|
||||||
|
QObject::connect(child, SIGNAL(childIsAboutToBeMoved(Item*, int, int, Item*, int)), this, SIGNAL(childIsAboutToBeMoved(Item*, int, int, Item*, int)));
|
||||||
|
QObject::connect(child, SIGNAL(childMoved()), this, SIGNAL(childMoved()));
|
||||||
|
|
||||||
|
if (moving) {
|
||||||
|
emit childMoved();
|
||||||
|
} else {
|
||||||
|
emit childInserted();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Models::Item * Models::Item::child(int row)
|
Models::Item * Models::Item::child(int row)
|
||||||
@ -74,7 +97,6 @@ QString Models::Item::getName() const
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QVariant Models::Item::data(int column) const
|
QVariant Models::Item::data(int column) const
|
||||||
{
|
{
|
||||||
if (column != 0) {
|
if (column != 0) {
|
||||||
@ -85,14 +107,31 @@ QVariant Models::Item::data(int column) const
|
|||||||
|
|
||||||
void Models::Item::removeChild(int index)
|
void Models::Item::removeChild(int index)
|
||||||
{
|
{
|
||||||
childItems.erase(childItems.begin() + index);
|
emit childIsAboutToBeRemoved(this, index, index);
|
||||||
|
removeChild(index);
|
||||||
|
emit childRemoved();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Models::Item::setParent(Models::Item* p_parent)
|
void Models::Item::_removeChild(int index)
|
||||||
{
|
{
|
||||||
parent = p_parent;
|
Item* child = childItems[index];
|
||||||
|
|
||||||
|
QObject::connect(child, SIGNAL(childChanged(Item*, int, int)), this, SIGNAL(childChanged(Item*, int, int)));
|
||||||
|
QObject::connect(child, SIGNAL(childIsAboutToBeInserted(Item*, int, int)), this, SIGNAL(childIsAboutToBeInserted(Item*, int, int)));
|
||||||
|
QObject::connect(child, SIGNAL(childInserted()), this, SIGNAL(childInserted()));
|
||||||
|
QObject::connect(child, SIGNAL(childIsAboutToBeRemoved(Item*, int, int)), this, SIGNAL(childIsAboutToBeRemoved(Item*, int, int)));
|
||||||
|
QObject::connect(child, SIGNAL(childRemoved()), this, SIGNAL(childRemoved()));
|
||||||
|
QObject::connect(child, SIGNAL(childIsAboutToBeMoved(Item*, int, int, Item*, int)), this, SIGNAL(childIsAboutToBeMoved(Item*, int, int, Item*, int)));
|
||||||
|
QObject::connect(child, SIGNAL(childMoved()), this, SIGNAL(childMoved()));
|
||||||
|
|
||||||
|
childItems.erase(childItems.begin() + index);
|
||||||
|
child->parent = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Models::Item::changed(int col)
|
||||||
|
{
|
||||||
|
if (parent != 0) {
|
||||||
|
emit childChanged(this, row(), col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,6 +17,7 @@ class Item : public QObject{
|
|||||||
group,
|
group,
|
||||||
contact,
|
contact,
|
||||||
conversation,
|
conversation,
|
||||||
|
presence,
|
||||||
root
|
root
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -24,11 +25,17 @@ class Item : public QObject{
|
|||||||
~Item();
|
~Item();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void changed(int col);
|
void childChanged(Item* item, int row, int col);
|
||||||
|
void childIsAboutToBeInserted(Item* parent, int first, int last);
|
||||||
|
void childInserted();
|
||||||
|
void childIsAboutToBeRemoved(Item* parent, int first, int last);
|
||||||
|
void childRemoved();
|
||||||
|
void childIsAboutToBeMoved(Item* source, int first, int last, Item* destination, int newIndex);
|
||||||
|
void childMoved();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void appendChild(Item *child);
|
virtual void appendChild(Item *child);
|
||||||
void removeChild(int index);
|
virtual void removeChild(int index);
|
||||||
QString getName() const;
|
QString getName() const;
|
||||||
void setName(const QString& name);
|
void setName(const QString& name);
|
||||||
|
|
||||||
@ -38,16 +45,32 @@ class Item : public QObject{
|
|||||||
virtual QVariant data(int column) const;
|
virtual QVariant data(int column) const;
|
||||||
int row() const;
|
int row() const;
|
||||||
Item *parentItem();
|
Item *parentItem();
|
||||||
void setParent(Item* p_parent);
|
|
||||||
|
|
||||||
const Type type;
|
const Type type;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void changed(int col);
|
||||||
|
virtual void _removeChild(int index);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QString name;
|
QString name;
|
||||||
std::deque<Item*> childItems;
|
std::deque<Item*> childItems;
|
||||||
Item* parent;
|
Item* parent;
|
||||||
|
|
||||||
|
protected slots:
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Shared {
|
||||||
|
static const std::deque<QString> AvailabilityIcons = {
|
||||||
|
"im-user-online",
|
||||||
|
"im-user-away",
|
||||||
|
"im-user-away",
|
||||||
|
"im-user-busy",
|
||||||
|
"im-user-online",
|
||||||
|
"im-user-offline"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif // MODELS_ITEM_H
|
#endif // MODELS_ITEM_H
|
||||||
|
119
ui/models/presence.cpp
Normal file
119
ui/models/presence.cpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* <one line to give the program's name and a brief idea of what it does.>
|
||||||
|
* Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
*
|
||||||
|
* This program 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.
|
||||||
|
*
|
||||||
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "presence.h"
|
||||||
|
|
||||||
|
Models::Presence::Presence(const QMap<QString, QVariant>& data, Item* parentItem):
|
||||||
|
Item(Item::presence, data, parentItem),
|
||||||
|
availability(Shared::offline),
|
||||||
|
lastActivity(data.value("lastActivity").toDateTime()),
|
||||||
|
status(data.value("status").toString())
|
||||||
|
{
|
||||||
|
QMap<QString, QVariant>::const_iterator itr = data.find("availability");
|
||||||
|
if (itr != data.end()) {
|
||||||
|
setAvailability(itr.value().toUInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Models::Presence::~Presence()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int Models::Presence::columnCount() const
|
||||||
|
{
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant Models::Presence::data(int column) const
|
||||||
|
{
|
||||||
|
switch (column) {
|
||||||
|
case 0:
|
||||||
|
return Item::data(column);
|
||||||
|
case 1:
|
||||||
|
return lastActivity;
|
||||||
|
case 2:
|
||||||
|
return availability;
|
||||||
|
case 3:
|
||||||
|
return status;
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Shared::Availability Models::Presence::getAvailability() const
|
||||||
|
{
|
||||||
|
return availability;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDateTime Models::Presence::getLastActivity() const
|
||||||
|
{
|
||||||
|
return lastActivity;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Models::Presence::getStatus() const
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Presence::setAvailability(Shared::Availability p_avail)
|
||||||
|
{
|
||||||
|
if (availability != p_avail) {
|
||||||
|
availability = p_avail;
|
||||||
|
changed(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Presence::setAvailability(unsigned int avail)
|
||||||
|
{
|
||||||
|
if (avail <= Shared::availabilityHighest) {
|
||||||
|
Shared::Availability state = static_cast<Shared::Availability>(avail);
|
||||||
|
setAvailability(state);
|
||||||
|
} else {
|
||||||
|
qDebug("An attempt to set wrong state to the contact");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Models::Presence::setLastActivity(const QDateTime& p_time)
|
||||||
|
{
|
||||||
|
if (lastActivity != p_time) {
|
||||||
|
lastActivity = p_time;
|
||||||
|
changed(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Presence::setStatus(const QString& p_state)
|
||||||
|
{
|
||||||
|
if (status != p_state) {
|
||||||
|
status = p_state;
|
||||||
|
changed(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Presence::update(const QString& key, const QVariant& value)
|
||||||
|
{
|
||||||
|
if (key == "name") {
|
||||||
|
setName(value.toString());
|
||||||
|
} else if (key == "status") {
|
||||||
|
setStatus(value.toString());
|
||||||
|
} else if (key == "availability") {
|
||||||
|
setAvailability(value.toUInt());
|
||||||
|
} else if (key == "lastActivity") {
|
||||||
|
setLastActivity(value.toDateTime());
|
||||||
|
}
|
||||||
|
}
|
58
ui/models/presence.h
Normal file
58
ui/models/presence.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* <one line to give the program's name and a brief idea of what it does.>
|
||||||
|
* Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
*
|
||||||
|
* This program 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.
|
||||||
|
*
|
||||||
|
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MODELS_PRESENCE_H
|
||||||
|
#define MODELS_PRESENCE_H
|
||||||
|
|
||||||
|
#include "item.h"
|
||||||
|
#include "../../global.h"
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
namespace Models {
|
||||||
|
|
||||||
|
class Presence : public Models::Item
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit Presence(const QMap<QString, QVariant> &data, Item *parentItem = 0);
|
||||||
|
~Presence();
|
||||||
|
|
||||||
|
virtual int columnCount() const override;
|
||||||
|
virtual QVariant data(int column) const override;
|
||||||
|
|
||||||
|
Shared::Availability getAvailability() const;
|
||||||
|
void setAvailability(Shared::Availability p_avail);
|
||||||
|
void setAvailability(unsigned int avail);
|
||||||
|
|
||||||
|
QDateTime getLastActivity() const;
|
||||||
|
void setLastActivity(const QDateTime& p_time);
|
||||||
|
|
||||||
|
QString getStatus() const;
|
||||||
|
void setStatus(const QString& p_state);
|
||||||
|
|
||||||
|
void update(const QString& key, const QVariant& value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Shared::Availability availability;
|
||||||
|
QDateTime lastActivity;
|
||||||
|
QString status;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // MODELS_PRESENCE_H
|
@ -17,6 +17,13 @@ Models::Roster::Roster(QObject* parent):
|
|||||||
SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)),
|
SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)),
|
||||||
this,
|
this,
|
||||||
SLOT(onAccountDataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
|
SLOT(onAccountDataChanged(const QModelIndex&, const QModelIndex&, const QVector<int>&)));
|
||||||
|
connect(root, SIGNAL(childChanged(Item*, int, int)), this, SLOT(onChildChanged(Item*, int, int)));
|
||||||
|
connect(root, SIGNAL(childIsAboutToBeInserted(Item*, int, int)), this, SLOT(onChildIsAboutToBeInserted(Item*, int, int)));
|
||||||
|
connect(root, SIGNAL(childInserted()), this, SLOT(onChildInserted()));
|
||||||
|
connect(root, SIGNAL(childIsAboutToBeRemoved(Item*, int, int)), this, SLOT(onChildIsAboutToBeRemoved(Item*, int, int)));
|
||||||
|
connect(root, SIGNAL(childRemoved()), this, SLOT(onChildRemoved()));
|
||||||
|
connect(root, SIGNAL(childIsAboutToBeMoved(Item*, int, int, Item*, int)), this, SLOT(onChildIsAboutToBeMoved(Item*, int, int, Item*, int)));
|
||||||
|
connect(root, SIGNAL(childMoved()), this, SLOT(onChildMoved()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Models::Roster::~Roster()
|
Models::Roster::~Roster()
|
||||||
@ -27,12 +34,10 @@ Models::Roster::~Roster()
|
|||||||
|
|
||||||
void Models::Roster::addAccount(const QMap<QString, QVariant>& data)
|
void Models::Roster::addAccount(const QMap<QString, QVariant>& data)
|
||||||
{
|
{
|
||||||
Account* acc = new Account(data, root);
|
Account* acc = new Account(data);
|
||||||
beginInsertRows(QModelIndex(), root->childCount(), root->childCount());
|
|
||||||
root->appendChild(acc);
|
root->appendChild(acc);
|
||||||
accounts.insert(std::make_pair(acc->getName(), acc));
|
accounts.insert(std::make_pair(acc->getName(), acc));
|
||||||
accountsModel->addAccount(acc);
|
accountsModel->addAccount(acc);
|
||||||
endInsertRows();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant Models::Roster::data (const QModelIndex& index, int role) const
|
QVariant Models::Roster::data (const QModelIndex& index, int role) const
|
||||||
@ -70,15 +75,12 @@ QVariant Models::Roster::data (const QModelIndex& index, int role) const
|
|||||||
break;
|
break;
|
||||||
case Item::contact:{
|
case Item::contact:{
|
||||||
Contact* contact = static_cast<Contact*>(item);
|
Contact* contact = static_cast<Contact*>(item);
|
||||||
int state = contact->getState();
|
result = QIcon::fromTheme(Shared::AvailabilityIcons[contact->getState()]);
|
||||||
switch (state) {
|
|
||||||
case 0:
|
|
||||||
result = QIcon::fromTheme("im-user-offline");
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
result = QIcon::fromTheme("im-user-online");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case Item::presence:{
|
||||||
|
Presence* presence = static_cast<Presence*>(item);
|
||||||
|
result = QIcon::fromTheme(Shared::AvailabilityIcons[presence->getAvailability()]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -237,11 +239,9 @@ void Models::Roster::addGroup(const QString& account, const QString& name)
|
|||||||
std::map<QString, Account*>::iterator itr = accounts.find(account);
|
std::map<QString, Account*>::iterator itr = accounts.find(account);
|
||||||
if (itr != accounts.end()) {
|
if (itr != accounts.end()) {
|
||||||
Account* acc = itr->second;
|
Account* acc = itr->second;
|
||||||
Item* group = new Item(Item::group, {{"name", name}}, acc);
|
Item* group = new Item(Item::group, {{"name", name}});
|
||||||
beginInsertRows(createIndex(acc->row(), 0, acc), acc->childCount(), acc->childCount());
|
|
||||||
acc->appendChild(group);
|
acc->appendChild(group);
|
||||||
groups.insert(std::make_pair(id, group));
|
groups.insert(std::make_pair(id, group));
|
||||||
endInsertRows();
|
|
||||||
} else {
|
} else {
|
||||||
qDebug() << "An attempt to add group " << name << " to non existing account " << account << ", skipping";
|
qDebug() << "An attempt to add group " << name << " to non existing account " << account << ", skipping";
|
||||||
}
|
}
|
||||||
@ -300,24 +300,16 @@ void Models::Roster::addContact(const QString& account, const QString& jid, cons
|
|||||||
if (ca->getJid() == jid) {
|
if (ca->getJid() == jid) {
|
||||||
qDebug() << "An attempt to add a already existing contact " << name << " to the group " << group << ", contact will be moved from ungrouped contacts of " << account;
|
qDebug() << "An attempt to add a already existing contact " << name << " to the group " << group << ", contact will be moved from ungrouped contacts of " << account;
|
||||||
|
|
||||||
beginMoveRows(createIndex(acc->row(), 0, acc), i, i, createIndex(parent->row(), 0, parent), parent->childCount());
|
|
||||||
contact = ca;
|
|
||||||
acc->removeChild(i);
|
|
||||||
ca->setParent(parent);
|
|
||||||
parent->appendChild(ca);
|
parent->appendChild(ca);
|
||||||
endMoveRows();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
contact = new Contact({{"name", name}, {"jid", jid}, {"state", 0}}, parent);
|
contact = new Contact({{"name", name}, {"jid", jid}, {"state", 0}});
|
||||||
beginInsertRows(createIndex(parent->row(), 0, parent), parent->childCount(), parent->childCount());
|
|
||||||
parent->appendChild(contact);
|
parent->appendChild(contact);
|
||||||
contacts.insert(std::make_pair(id, contact));
|
contacts.insert(std::make_pair(id, contact));
|
||||||
endInsertRows();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Models::Roster::removeGroup(const QString& account, const QString& name)
|
void Models::Roster::removeGroup(const QString& account, const QString& name)
|
||||||
@ -332,9 +324,7 @@ void Models::Roster::removeGroup(const QString& account, const QString& name)
|
|||||||
Item* parent = item->parentItem();
|
Item* parent = item->parentItem();
|
||||||
int row = item->row();
|
int row = item->row();
|
||||||
|
|
||||||
beginRemoveRows(createIndex(parent->row(), 0, parent), row, row);
|
|
||||||
parent->removeChild(row);
|
parent->removeChild(row);
|
||||||
endRemoveRows();
|
|
||||||
|
|
||||||
std::deque<Contact*> toInsert;
|
std::deque<Contact*> toInsert;
|
||||||
for (int i = 0; item->childCount() > 0; ++i) {
|
for (int i = 0; item->childCount() > 0; ++i) {
|
||||||
@ -360,13 +350,10 @@ void Models::Roster::removeGroup(const QString& account, const QString& name)
|
|||||||
|
|
||||||
if (toInsert.size() > 0) {
|
if (toInsert.size() > 0) {
|
||||||
Account* acc = accounts.find("account")->second;
|
Account* acc = accounts.find("account")->second;
|
||||||
beginInsertRows(createIndex(acc->row(), 0, acc), acc->childCount(), acc->childCount() + toInsert.size() - 1);
|
|
||||||
for (int i = 0; i < toInsert.size(); ++i) {
|
for (int i = 0; i < toInsert.size(); ++i) {
|
||||||
Contact* cont = toInsert[i];
|
Contact* cont = toInsert[i];
|
||||||
cont->setParent(acc);
|
acc->appendChild(cont); //TODO optimisation
|
||||||
acc->appendChild(cont);
|
|
||||||
}
|
}
|
||||||
endInsertRows();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete item;
|
delete item;
|
||||||
@ -396,10 +383,8 @@ void Models::Roster::removeContact(const QString& account, const QString& jid)
|
|||||||
if (parent->type == Item::group && parent->childCount() == 1) {
|
if (parent->type == Item::group && parent->childCount() == 1) {
|
||||||
toRemove.insert(parent->getName());
|
toRemove.insert(parent->getName());
|
||||||
}
|
}
|
||||||
int row = contact->row();
|
|
||||||
beginRemoveRows(createIndex(parent->row(), 0, parent), row, row);
|
parent->removeChild(contact->row());
|
||||||
parent->removeChild(row);
|
|
||||||
endRemoveRows();
|
|
||||||
delete contact;
|
delete contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,13 +420,84 @@ void Models::Roster::removeContact(const QString& account, const QString& jid, c
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int row = cont->row();
|
gr->removeChild(cont->row());
|
||||||
beginRemoveRows(createIndex(gr->row(), 0, gr), row, row);
|
|
||||||
gr->removeChild(row);
|
|
||||||
endRemoveRows();
|
|
||||||
delete cont;
|
delete cont;
|
||||||
|
|
||||||
if (gr->childCount() == 0) {
|
if (gr->childCount() == 0) {
|
||||||
removeGroup(account, group);
|
removeGroup(account, group);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Models::Roster::onChildChanged(Models::Item* item, int row, int col)
|
||||||
|
{
|
||||||
|
QModelIndex index = createIndex(row, col, item);
|
||||||
|
emit dataChanged(index, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Roster::onChildIsAboutToBeInserted(Models::Item* parent, int first, int last)
|
||||||
|
{
|
||||||
|
int row = 0;
|
||||||
|
if (parent != root) {
|
||||||
|
row = parent->row();
|
||||||
|
beginInsertRows(createIndex(row, 0, parent), first, last);
|
||||||
|
} else {
|
||||||
|
beginInsertRows(QModelIndex(), first, last);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Roster::onChildIsAboutToBeMoved(Models::Item* source, int first, int last, Models::Item* destination, int newIndex)
|
||||||
|
{
|
||||||
|
int oldRow = 0;
|
||||||
|
if (source != root) {
|
||||||
|
oldRow = source->row();
|
||||||
|
}
|
||||||
|
int newRow = 0;
|
||||||
|
if (destination != root) {
|
||||||
|
newRow = destination->row();
|
||||||
|
}
|
||||||
|
beginMoveRows(createIndex(oldRow, 0, source), first, last, createIndex(newRow, 0, destination), newIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Roster::onChildIsAboutToBeRemoved(Models::Item* parent, int first, int last)
|
||||||
|
{
|
||||||
|
int row = 0;
|
||||||
|
if (parent != root) {
|
||||||
|
row = parent->row();
|
||||||
|
}
|
||||||
|
beginRemoveRows(createIndex(row, 0, parent), first, last);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Roster::onChildInserted()
|
||||||
|
{
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Roster::onChildMoved()
|
||||||
|
{
|
||||||
|
endMoveRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Roster::onChildRemoved()
|
||||||
|
{
|
||||||
|
endRemoveRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Roster::addPresence(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data)
|
||||||
|
{
|
||||||
|
ElId contactId(account, jid);
|
||||||
|
std::multimap<ElId, Contact*>::iterator cBeg = contacts.lower_bound(contactId);
|
||||||
|
std::multimap<ElId, Contact*>::iterator cEnd = contacts.upper_bound(contactId);
|
||||||
|
for (;cBeg != cEnd; ++cBeg) {
|
||||||
|
cBeg->second->addPresence(name, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Models::Roster::removePresence(const QString& account, const QString& jid, const QString& name)
|
||||||
|
{
|
||||||
|
ElId contactId(account, jid);
|
||||||
|
std::multimap<ElId, Contact*>::iterator cBeg = contacts.lower_bound(contactId);
|
||||||
|
std::multimap<ElId, Contact*>::iterator cEnd = contacts.upper_bound(contactId);
|
||||||
|
for (;cBeg != cEnd; ++cBeg) {
|
||||||
|
cBeg->second->removePresence(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -30,6 +30,8 @@ public:
|
|||||||
void removeContact(const QString& account, const QString& jid, const QString& group);
|
void removeContact(const QString& account, const QString& jid, const QString& group);
|
||||||
void removeContact(const QString& account, const QString& jid);
|
void removeContact(const QString& account, const QString& jid);
|
||||||
void changeContact(const QString& account, const QString& jid, const QString& name);
|
void changeContact(const QString& account, const QString& jid, const QString& name);
|
||||||
|
void addPresence(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data);
|
||||||
|
void removePresence(const QString& account, const QString& jid, const QString& name);
|
||||||
|
|
||||||
QVariant data ( const QModelIndex& index, int role ) const override;
|
QVariant data ( const QModelIndex& index, int role ) const override;
|
||||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||||
@ -49,6 +51,13 @@ private:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onAccountDataChanged(const QModelIndex& tl, const QModelIndex& br, const QVector<int>& roles);
|
void onAccountDataChanged(const QModelIndex& tl, const QModelIndex& br, const QVector<int>& roles);
|
||||||
|
void onChildChanged(Item* item, int row, int col);
|
||||||
|
void onChildIsAboutToBeInserted(Item* parent, int first, int last);
|
||||||
|
void onChildInserted();
|
||||||
|
void onChildIsAboutToBeRemoved(Item* parent, int first, int last);
|
||||||
|
void onChildRemoved();
|
||||||
|
void onChildIsAboutToBeMoved(Item* source, int first, int last, Item* destination, int newIndex);
|
||||||
|
void onChildMoved();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class ElId {
|
class ElId {
|
||||||
|
@ -116,5 +116,15 @@ void Squawk::removeContact(const QString& account, const QString& jid, const QSt
|
|||||||
rosterModel.removeContact(account, jid, group);
|
rosterModel.removeContact(account, jid, group);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Squawk::addPresence(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data)
|
||||||
|
{
|
||||||
|
rosterModel.addPresence(account, jid, name, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Squawk::removePresence(const QString& account, const QString& jid, const QString& name)
|
||||||
|
{
|
||||||
|
rosterModel.removePresence(account, jid, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,6 +38,8 @@ public slots:
|
|||||||
void removeContact(const QString& account, const QString& jid, const QString& group);
|
void removeContact(const QString& account, const QString& jid, const QString& group);
|
||||||
void removeContact(const QString& account, const QString& jid);
|
void removeContact(const QString& account, const QString& jid);
|
||||||
void changeContact(const QString& account, const QString& jid, const QString& name);
|
void changeContact(const QString& account, const QString& jid, const QString& name);
|
||||||
|
void addPresence(const QString& account, const QString& jid, const QString& name, const QMap<QString, QVariant>& data);
|
||||||
|
void removePresence(const QString& account, const QString& jid, const QString& name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QScopedPointer<Ui::Squawk> m_ui;
|
QScopedPointer<Ui::Squawk> m_ui;
|
||||||
|
Loading…
Reference in New Issue
Block a user