Commit 5ed8ed32 authored by James D. Smith's avatar James D. Smith

Integrate Status Handler.

API additions and cleanup.
Bugfixes and documentation.
REVIEW: 130188
parent 3d528b55
......@@ -73,6 +73,7 @@ void QmlPlugins::registerTypes(const char *uri)
qRegisterMetaType<Tp::AccountManagerPtr>();
qRegisterMetaType<KTp::ContactPtr>();
qRegisterMetaType<Tp::AccountPtr>();
qRegisterMetaType<Tp::AccountSetPtr>();
QMetaType::registerComparators<KTp::Presence>();
}
......
......@@ -22,7 +22,13 @@
#include "accounts-list-model.h"
#include <QIcon>
#include <QDBusInterface>
#include <QDBusPendingCall>
#include <QVariant>
#include "debug.h"
#include "types.h"
#include <KLocalizedString>
#include <KPixmapSequence>
......@@ -31,12 +37,18 @@
#include <TelepathyQt/Account>
#include <TelepathyQt/AccountSet>
#include <TelepathyQt/Constants>
#include <TelepathyQt/Presence>
class KTp::AccountsListModel::Private {
class KTp::AccountsListModel::Private : public QObject {
Q_OBJECT
public:
QList<Tp::AccountPtr> accounts;
Tp::AccountSetPtr accountSet;
QDBusInterface *statusHandler;
Q_SIGNALS:
void statusHandlerStatusChange(const QString &accountUID);
};
......@@ -44,6 +56,14 @@ KTp::AccountsListModel::AccountsListModel(QObject *parent)
: QAbstractListModel(parent),
d(new AccountsListModel::Private)
{
Tp::registerTypes();
d->statusHandler = new QDBusInterface(QLatin1String("org.freedesktop.Telepathy.Client.KTp.KdedIntegrationModule"),
QLatin1String("/StatusHandler"),
QString(),
QDBusConnection::sessionBus(), this);
connect(d->statusHandler, SIGNAL(statusChange(QString)), d, SIGNAL(statusHandlerStatusChange(QString)));
}
KTp::AccountsListModel::~AccountsListModel()
......@@ -59,6 +79,10 @@ QHash<int, QByteArray> KTp::AccountsListModel::roleNames() const
roles[ConnectionStateIconRole] = "connectionStateIcon";
roles[ConnectionErrorMessageDisplayRole] = "connectionErrorMessage";
roles[ConnectionProtocolNameRole] = "connectionProtocolName";
roles[StatusHandlerSessionPresenceRole] = "statusHandlerSessionPresence";
roles[StatusHandlerPresenceRole] = "statusHandlerPresence";
roles[RequestedPresenceRole] = "requestedPresence";
roles[IconNameRole] = "iconName";
roles[EnabledRole] = "enabled";
roles[AccountRole] = "account";
return roles;
......@@ -74,12 +98,12 @@ void KTp::AccountsListModel::setAccountSet(const Tp::AccountSetPtr &accountSet)
Q_FOREACH(const Tp::AccountPtr &account, d->accountSet->accounts()) {
onAccountAdded(account);
}
connect(d->accountSet.data(), SIGNAL(accountAdded(Tp::AccountPtr)), SLOT(onAccountAdded(Tp::AccountPtr)));
connect(d->accountSet.data(), SIGNAL(accountRemoved(Tp::AccountPtr)), SLOT(onAccountRemoved(Tp::AccountPtr)));
}
int KTp::AccountsListModel::rowCount(const QModelIndex & parent) const
int KTp::AccountsListModel::rowCount(const QModelIndex &parent) const
{
// If the index is the root item, then return the row count.
if (parent == QModelIndex()) {
......@@ -91,15 +115,6 @@ int KTp::AccountsListModel::rowCount(const QModelIndex & parent) const
return 0;
}
int KTp::AccountsListModel::columnCount(const QModelIndex& parent) const
{
Q_UNUSED(parent);
// Column count is always 1
return 1;
}
QVariant KTp::AccountsListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
......@@ -138,6 +153,23 @@ QVariant KTp::AccountsListModel::data(const QModelIndex &index, int role) const
data = QVariant(account->protocolName());
break;
case AccountsListModel::StatusHandlerSessionPresenceRole:
case AccountsListModel::StatusHandlerPresenceRole:
if (d->statusHandler->property("requestedAccountPresences").toHash().contains(account->uniqueIdentifier())) {
data = QVariant::fromValue<KTp::Presence>(KTp::Presence(qdbus_cast<Tp::SimplePresence>(d->statusHandler->property("requestedAccountPresences").toHash().value(account->uniqueIdentifier()))));
} else {
data = QVariant::fromValue<KTp::Presence>(Tp::Presence(Tp::ConnectionPresenceTypeUnset, QLatin1String("unset"), QString()));
}
break;
case AccountsListModel::RequestedPresenceRole:
data = QVariant::fromValue<KTp::Presence>(account->requestedPresence());
break;
case AccountsListModel::IconNameRole:
data = QVariant(account->iconName());
break;
case AccountsListModel::EnabledRole:
if (account->isEnabled()) {
data = QVariant(Qt::Checked);
......@@ -162,6 +194,24 @@ bool KTp::AccountsListModel::setData(const QModelIndex &index, const QVariant &v
if (!index.isValid()) {
return false;
}
if ((role == AccountsListModel::StatusHandlerSessionPresenceRole) || (role == AccountsListModel::StatusHandlerPresenceRole)) {
const QVariant &accountUID = QVariant::fromValue<QString>(index.data(AccountRole).value<Tp::AccountPtr>()->uniqueIdentifier());
const QVariant &presence = QVariant::fromValue<Tp::SimplePresence>(qvariant_cast<KTp::Presence>(value).barePresence());
QVariant presenceClass;
if (role == AccountsListModel::StatusHandlerPresenceRole) {
presenceClass = QVariant::fromValue<uint>(0);
} else {
presenceClass = QVariant::fromValue<uint>(1);
}
QDBusPendingCall call = d->statusHandler->asyncCall(QLatin1String("setRequestedAccountPresence"), accountUID, presence, presenceClass);
return true;
}
if (role == AccountsListModel::RequestedPresenceRole) {
index.data(AccountRole).value<Tp::AccountPtr>()->setRequestedPresence(qvariant_cast<KTp::Presence>(value));
return true;
}
if (role == AccountsListModel::EnabledRole) {
//this is index from QSortFilterProxyModel
index.data(AccountRole).value<Tp::AccountPtr>()->setEnabled(value.toInt() == Qt::Checked);
......@@ -171,19 +221,6 @@ bool KTp::AccountsListModel::setData(const QModelIndex &index, const QVariant &v
return false;
}
QModelIndex KTp::AccountsListModel::index(int row, int column, const QModelIndex& parent) const
{
if (row < 0 || column < 0 || parent != QModelIndex()) {
return QModelIndex();
}
if (row < rowCount() && column < columnCount()) {
return createIndex(row, column);
}
return QModelIndex();
}
void KTp::AccountsListModel::onAccountAdded(const Tp::AccountPtr &account)
{
qCDebug(KTP_MODELS) << "Creating a new Account from account:" << account.data();
......@@ -208,8 +245,17 @@ void KTp::AccountsListModel::onAccountAdded(const Tp::AccountPtr &account)
qCDebug(KTP_MODELS) << "Account not already in model. Create new Account from account:"
<< account.data();
beginInsertRows(QModelIndex(), d->accounts.size(), d->accounts.size());
d->accounts.append(account);
auto accountIdentifiersLessThan = [] (const Tp::AccountPtr &account, const Tp::AccountPtr &other) {
if (account->serviceName() == other->serviceName()) {
return (QString::localeAwareCompare(account->normalizedName(), other->normalizedName()) < 0);
} else {
return (QString::localeAwareCompare(account->serviceName(), other->serviceName()) < 0);
}
};
int row = std::lower_bound(d->accounts.constBegin(), d->accounts.constEnd(), account, accountIdentifiersLessThan) - d->accounts.constBegin();
beginInsertRows(QModelIndex(), row, row);
d->accounts.insert(row, account);
endInsertRows();
connect(account.data(),
......@@ -230,13 +276,19 @@ void KTp::AccountsListModel::onAccountAdded(const Tp::AccountPtr &account)
connect(account.data(),
SIGNAL(stateChanged(bool)),
SLOT(onAccountUpdated()));
connect(d, &AccountsListModel::Private::statusHandlerStatusChange, [=] (const QString &accountUID) {
if (accountUID == account->uniqueIdentifier()) {
onAccountUpdated();
}
});
}
}
void KTp::AccountsListModel::onAccountRemoved(const Tp::AccountPtr &account)
{
beginRemoveRows(QModelIndex(), d->accounts.indexOf(account), d->accounts.indexOf(account));
d->accounts.removeAll(account);
int row = d->accounts.indexOf(account);
beginRemoveRows(QModelIndex(), row, row);
d->accounts.removeAt(row);
endRemoveRows();
}
......@@ -300,4 +352,11 @@ const QString KTp::AccountsListModel::connectionStatusReason(const Tp::AccountPt
}
}
QVariant KTp::AccountsListModel::get(int row, const QByteArray& role) const
{
//TODO: cache roles?
QHash<int, QByteArray> roles = roleNames();
return index(row, 0).data(roles.key(role));
}
#include "accounts-list-model.moc"
......@@ -22,9 +22,8 @@
#ifndef KTP_ACCOUNTS_LIST_MODEL_H
#define KTP_ACCOUNTS_LIST_MODEL_H
#include <QtCore/QAbstractListModel>
#include <TelepathyQt/Account>
#include <QAbstractListModel>
#include <QVariant>
#include <KTp/Models/ktpmodels_export.h>
#include <KTp/types.h>
......@@ -35,6 +34,7 @@ namespace KTp
class KTPMODELS_EXPORT AccountsListModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(int count READ rowCount);
Q_DISABLE_COPY(AccountsListModel);
public:
......@@ -44,6 +44,10 @@ public:
ConnectionStateIconRole,
ConnectionErrorMessageDisplayRole,
ConnectionProtocolNameRole,
StatusHandlerSessionPresenceRole,
StatusHandlerPresenceRole,
RequestedPresenceRole,
IconNameRole,
EnabledRole,
AccountRole
};
......@@ -54,11 +58,11 @@ public:
QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE;
void setAccountSet(const Tp::AccountSetPtr &accountSet);
virtual int rowCount(const QModelIndex & parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
Q_SCRIPTABLE QVariant get(int row, const QByteArray& role) const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
virtual bool setData(const QModelIndex &index, const QVariant &value, int role);
virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
private Q_SLOTS:
void onAccountAdded(const Tp::AccountPtr &account);
......
......@@ -26,12 +26,15 @@
#include <QFontDatabase>
#include <QIcon>
#include <QtDBus/QtDBus>
#include <QVariant>
#include <KSharedConfig>
#include <KLocalizedString>
#include <KConfig>
#include <KConfigGroup>
#include <KTp/presence.h>
#include <functional>
#include "types.h"
......@@ -40,20 +43,6 @@
namespace KTp
{
struct PresenceModelGreaterThan : public std::function<bool(KTp::Presence,KTp::Presence)>
{
inline bool operator()(const KTp::Presence& presence, const KTp::Presence& other)
{
if (KTp::Presence::sortPriority(presence.type()) < KTp::Presence::sortPriority(other.type())) {
return true;
} else if (KTp::Presence::sortPriority(presence.type()) == KTp::Presence::sortPriority(other.type())) {
return (presence.statusMessage() < other.statusMessage());
} else {
return false;
}
}
};
PresenceModel::PresenceModel(QObject *parent) :
QAbstractListModel(parent)
{
......@@ -102,14 +91,10 @@ void PresenceModel::propagationChange(const QVariantList modelChange)
}
}
QVariant PresenceModel::data(int index) const
int PresenceModel::rowCount(const QModelIndex &parent) const
{
if (index < 0 || index >= m_presences.size()) {
qCDebug(KTP_MODELS) << "invalid index data requested" << index;
return QVariant();
}
return QVariant::fromValue<KTp::Presence>(m_presences[index]);
Q_UNUSED(parent)
return m_presences.size();
}
QVariant PresenceModel::data(const QModelIndex &index, int role) const
......@@ -123,13 +108,13 @@ QVariant PresenceModel::data(const QModelIndex &index, int role) const
switch (role) {
case Qt::DisplayRole:
if (presence.statusMessage().isEmpty()) {
return presence.displayString();
return QVariant(presence.displayString());
} else {
return presence.statusMessage();
return QVariant(presence.statusMessage());
}
case Qt::DecorationRole:
return presence.icon();
return QVariant(presence.icon());
case Qt::FontRole:
if (presence.statusMessage().isEmpty()) {
......@@ -144,16 +129,44 @@ QVariant PresenceModel::data(const QModelIndex &index, int role) const
return QVariant::fromValue<KTp::Presence>(presence);
case IconNameRole:
return presence.iconName();
return QVariant(presence.iconName());
}
return QVariant();
}
int PresenceModel::rowCount(const QModelIndex &parent) const
QModelIndexList PresenceModel::match(const QModelIndex &start, int role, const QVariant &value, int hits, Qt::MatchFlags flags) const
{
Q_UNUSED(parent)
return m_presences.size();
Q_UNUSED(flags);
QModelIndexList items;
for (int i = 0; i < m_presences.size(); i++) {
if (i < start.row())
continue;
const KTp::Presence &presence = m_presences[i];
if (role == Qt::DisplayRole) {
if (presence.statusMessage().isEmpty()
&& (presence.displayString() == qvariant_cast<QString>(value))) {
items.append(createIndex(i, 0));
} else if (presence.statusMessage() == qvariant_cast<QString>(value)) {
items.append(createIndex(i, 0));
}
}
if (role == PresenceRole) {
const KTp::Presence &matchPresence = qvariant_cast<KTp::Presence>(value);
if (presence == matchPresence) {
items.append(createIndex(i, 0));
}
}
if (items.size() == hits) {
return items;
}
}
return items;
}
void PresenceModel::loadPresences()
......@@ -204,23 +217,25 @@ void PresenceModel::modifyModel(const KTp::Presence &presence)
if (m_presences.contains(presence)) {
int row = m_presences.indexOf(presence);
beginRemoveRows(QModelIndex(), row, row);
m_presences.removeAt(row);
endRemoveRows();
m_presences.removeOne(presence);
} else {
m_presences.append(presence);
// Identical presence types with status messages are compared with the
// status messages in ascending order.
std::sort(m_presences.begin(), m_presences.end(), PresenceModelGreaterThan());
int index = m_presences.indexOf(presence);
beginInsertRows(QModelIndex(), index, index);
auto presenceMessageGreaterThan = [] (const KTp::Presence &presence, const KTp::Presence &other) {
if (KTp::Presence::sortPriority(presence.type()) == KTp::Presence::sortPriority(other.type())) {
return (QString::localeAwareCompare(presence.statusMessage(), other.statusMessage()) < 0);
} else {
return (KTp::Presence::sortPriority(presence.type()) < KTp::Presence::sortPriority(other.type()));
}
};
int row = std::lower_bound(m_presences.constBegin(), m_presences.constEnd(), presence, presenceMessageGreaterThan) - m_presences.constBegin();
beginInsertRows(QModelIndex(), row, row);
m_presences.insert(row, presence);
endInsertRows();
}
Q_EMIT countChanged();
}
QModelIndex PresenceModel::addPresence(const KTp::Presence &presence)
......
......@@ -23,6 +23,7 @@
#define PRESENCEMODEL_H
#include <QAbstractListModel>
#include <QVariant>
#include <KConfigGroup>
......@@ -35,7 +36,8 @@ namespace KTp
class KTPMODELS_EXPORT PresenceModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
Q_PROPERTY(int count READ rowCount)
public:
explicit PresenceModel(QObject *parent = 0);
~PresenceModel();
......@@ -63,18 +65,15 @@ public:
Q_SCRIPTABLE QVariant get(int row, const QByteArray& role) const;
//protected:
virtual QVariant data(const QModelIndex &index, int role) const;
virtual QVariant data(int index) const;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
virtual QModelIndexList match(const QModelIndex &start, int role, const QVariant &value, int hits = 1, Qt::MatchFlags flags = Qt::MatchFlags(Qt::MatchStartsWith | Qt::MatchWrap)) const;
virtual QHash<int, QByteArray> roleNames() const;
public Q_SLOTS:
/** Incoming changes from other models */
void propagationChange(const QVariantList modelChange);
Q_SIGNALS:
void countChanged();
private:
void modifyModel(const KTp::Presence &presence);
void propagateChange(const KTp::Presence &presence);
......
This diff is collapsed.
This diff is collapsed.
......@@ -76,6 +76,22 @@ QString Presence::iconName(bool useImIcons) const
}
}
bool Presence::operator ==(const Presence &other) const
{
if (sortPriority(type()) == sortPriority(other.type())) {
if (statusMessage() == other.statusMessage()) {
return true;
}
}
return false;
}
bool Presence::operator !=(const Presence &other) const
{
return !(other == *this);
}
bool Presence::operator <(const Presence &other) const
{
if (sortPriority(type()) > sortPriority(other.type())) {
......
......@@ -68,6 +68,16 @@ public:
*/
QString displayString() const;
/**
* \brief Returns if the presences are equivalent
*/
bool operator ==(const Presence &other) const;
/**
* \brief Returns if the presences are not equivalent
*/
bool operator !=(const Presence &other) const;
/**
* \brief Returns which presence is "less available"
*/
......
......@@ -27,6 +27,7 @@
#include <TelepathyQt/TextChannel>
#include <TelepathyQt/Account>
#include <TelepathyQt/AccountSet>
#include <TelepathyQt/AccountManager>
#include <QVariant>
......@@ -111,6 +112,7 @@ const QHash<Tp::ConnectionPresenceType, QString> s_presenceStrings = {
{ Tp::ConnectionPresenceTypeError, QStringLiteral("error") }
};
Q_DECLARE_METATYPE(Tp::AccountSetPtr);
Q_DECLARE_METATYPE(Tp::AccountPtr)
Q_DECLARE_METATYPE(KTp::ContactPtr)
Q_DECLARE_METATYPE(Tp::AccountManagerPtr);
......
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