From kopete-devel Sat Aug 16 18:46:47 2008 From: =?ISO-8859-15?Q?Dennis_Nienh=FCser?= Date: Sat, 16 Aug 2008 18:46:47 +0000 To: kopete-devel Subject: [kopete-devel] [Patch] Extended D-Bus Interface Message-Id: <48A72097.7040809 () gentoo ! org> X-MARC-Message: https://marc.info/?l=kopete-devel&m=121891244018442 MIME-Version: 1 Content-Type: multipart/mixed; boundary="--------------070309090305050203090501" This is a multi-part message in MIME format. --------------070309090305050203090501 Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: 7bit Hi, currently our D-Bus interface is a bit (too) limited. As it's not clear when telepathy and co. will make the current approach obsolete, here's a patch to make more interesting things available via D-Bus. I'll add some disclaimers that it is subject to change and might be removed before 4.2 (as discussed on IRC). Changes include: - Methods previously using the displayName to locate contacts (unreliable) additionally understand protocol:account:contact triplets (as returned by contacts()), contact ids and for backward compatibility (and lazy people) still display names. - contactsByFilter() also supports "away" as filter (previously "online", "reachable", filecapable"). - new method openChat, similar to sendMessage except that no message is sent. - new method contactProperties reporting a QVariantMap with the following contact properties: id, displayName, online status, status message, reachability, path to avatar, pending messages (stringlist) - new signal contactChanged announcing that one of the properties has changed (so applications don't have to poll for it) I tested this interface with the contacts plasmoid in playground and it seems to work nice. Comments appreciated. Regards, Dennis --------------070309090305050203090501 Content-Type: text/x-diff; name="kopete-dbus.diff" Content-Transfer-Encoding: 8bit Content-Disposition: inline; filename="kopete-dbus.diff" Index: kopete/kopete/kopetedbusinterface_p.cpp =================================================================== --- kopete/kopete/kopetedbusinterface_p.cpp (revision 0) +++ kopete/kopete/kopetedbusinterface_p.cpp (revision 0) @@ -0,0 +1,187 @@ +/* + kopetedbusinterfaceprivate.h - Kopete D-Bus interface private class + + Copyright (c) 2008 by Dennis Nienhüser + + Kopete (c) 2002-2008 by the Kopete developers + + ************************************************************************* + * * + * 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 of the License, or (at your option) any later version. * + * * + ************************************************************************* + */ + +#include "kopetedbusinterface_p.h" + +#include + +#include +#include +#include +#include +#include +#include + +ContactStalker::ContactStalker(Kopete::MetaContact *contact) +{ + m_contact = contact; + QObject::connect( Kopete::ContactList::self(), + SIGNAL(metaContactRemoved( Kopete::MetaContact *)), + this, SLOT(slotMetaContactRemoved(Kopete::MetaContact *)) ); + QObject::connect( contact, SIGNAL(onlineStatusChanged(Kopete::MetaContact*,Kopete::OnlineStatus::StatusType)), + this, SLOT(slotEmitSignalDelayed())); + QObject::connect( contact, SIGNAL(displayNameChanged(const QString &, const QString &)), + this, SLOT(slotEmitSignalDelayed())); + QObject::connect( contact, SIGNAL(photoChanged()), + this, SLOT(slotEmitSignalDelayed())); + QObject::connect( contact, SIGNAL(contactAdded(Kopete::Contact*)), + this, SLOT(slotEmitSignalDelayed())); + QObject::connect( contact, SIGNAL(contactRemoved(Kopete::Contact*)), + this, SLOT(slotEmitSignalDelayed())); + + QObject::connect(Kopete::ChatSessionManager::self(), + SIGNAL( display( Kopete::Message &, Kopete::ChatSession *) ), + this, SLOT ( messageAppended( Kopete::Message &, Kopete::ChatSession *) ) ); + + m_lastChange = QTime::currentTime(); + slotEmitSignal(); +} + +void ContactStalker::slotEmitSignalDelayed() +{ + const int timeout(1500); + + if (m_lastChange.elapsed() >= timeout) + { + m_lastChange = QTime::currentTime(); + QTimer::singleShot(timeout, this, SLOT(slotEmitSignal())); + } +} + +void ContactStalker::slotEmitSignal() +{ + if (m_contact) + { + emit contactChanged(m_contact->metaContactId()); + } +} + +void ContactStalker::messageAppended(Kopete::Message &message, + Kopete::ChatSession *session) +{ + Q_UNUSED(session); + if(!m_contact) + { + return; + } + + if ( message.direction() == Kopete::Message::Inbound ) { + QString contactId = message.from()->metaContact()->metaContactId(); + if (contactId == m_contact->metaContactId()) + { + foreach(Kopete::Contact *subContact, m_contact->contacts()) + { + QList pendingMessages = KopeteViewManager::viewManager()->pendingMessages(subContact); + foreach(Kopete::MessageEvent *event, pendingMessages) + { + connect(event, SIGNAL(done(Kopete::MessageEvent*)), this, SLOT(slotEmitSignalDelayed())); + } + } + + emit contactChanged(contactId); + } + } +} + +void ContactStalker::slotMetaContactRemoved(Kopete::MetaContact *contact) +{ + if (contact == m_contact) + { + m_contact = 0L; + emit contactChanged(contact->metaContactId()); + } +} + +KopeteDBusInterfacePrivate::KopeteDBusInterfacePrivate() +{ + QObject::connect(Kopete::ContactList::self(), + SIGNAL(metaContactAdded(Kopete::MetaContact*)), + this, SLOT(slotMetaContactAdded(Kopete::MetaContact*))); + + foreach( Kopete::MetaContact *contact, Kopete::ContactList::self()->metaContacts() ) + { + this->slotMetaContactAdded(contact); + } +} + +void KopeteDBusInterfacePrivate::slotMetaContactAdded( + Kopete::MetaContact* contact) +{ + if ( contact ) { + ContactStalker * stalker = new ContactStalker(contact); + connect( stalker, SIGNAL(contactChanged(QString)), + this, SIGNAL(contactChanged(QString))); + } +} + +QStringList KopeteDBusInterfacePrivate::listContact(const QList< + Kopete::MetaContact*> &contactList) +{ + QStringList result; + + foreach(Kopete::MetaContact *contact, contactList){ + result << contact->metaContactId(); +} + +return result; +} + +Kopete::OnlineStatusManager::Categories KopeteDBusInterfacePrivate::status2Value( + const QString &status) +{ + Kopete::OnlineStatusManager::Categories statusValue; + if ( status.toLower() == QLatin1String("online") || status.toLower() + == QLatin1String("available") ) { + statusValue = Kopete::OnlineStatusManager::Online; + } else if ( status.toLower() == QLatin1String("busy") ) { + statusValue = Kopete::OnlineStatusManager::Busy; + } else if ( status.toLower() == QLatin1String("away") ) { + statusValue = Kopete::OnlineStatusManager::Away; + } + + return statusValue; +} + +Kopete::MetaContact *KopeteDBusInterfacePrivate::findContact( + const QString &nameOrId) +{ + Kopete::MetaContact *contact = 0L; + + if ( nameOrId.count(":") == 2 ) { + QStringList tokens = nameOrId.split(":"); + Q_ASSERT(tokens.size() == 3); + Kopete::Contact *candidate = Kopete::ContactList::self()->findContact( + tokens.at(0), tokens.at(1), tokens.at(2)); + if ( candidate ) { + contact = candidate->metaContact(); + } + } + + if ( !contact ) { + contact = Kopete::ContactList::self()->findMetaContactByContactId( + nameOrId); + } + + if ( !contact ) { + contact = Kopete::ContactList::self()->findMetaContactByDisplayName( + nameOrId); + } + + return contact; +} + +#include "kopetedbusinterface_p.moc" Index: kopete/kopete/kopetedbusinterface.cpp =================================================================== --- kopete/kopete/kopetedbusinterface.cpp (revision 847746) +++ kopete/kopete/kopetedbusinterface.cpp (working copy) @@ -40,47 +40,22 @@ #include #include #include +#include +#include +#include // Local includes #include "kopeteadaptor.h" +#include "kopetedbusinterface_p.h" -QStringList listContact(const QList &contactList) -{ - QStringList result; - - foreach(Kopete::MetaContact *contact, contactList) - { - result << contact->metaContactId(); - } - - return result; -} - -Kopete::OnlineStatusManager::Categories status2Value(const QString &status) -{ - Kopete::OnlineStatusManager::Categories statusValue; - if( status.toLower() == QLatin1String("online") || status.toLower() == QLatin1String("available") ) - { - statusValue = Kopete::OnlineStatusManager::Online; - } - else if( status.toLower() == QLatin1String("busy") ) - { - statusValue = Kopete::OnlineStatusManager::Busy; - } - else if( status.toLower() == QLatin1String("away") ) - { - statusValue = Kopete::OnlineStatusManager::Away; - } - - return statusValue; -} - -KopeteDBusInterface::KopeteDBusInterface(QObject *parent) - : QObject(parent) +KopeteDBusInterface::KopeteDBusInterface(QObject *parent) : + QObject(parent), d(new KopeteDBusInterfacePrivate()) { setObjectName("KopeteDBusInterface"); new KopeteAdaptor(this); QDBusConnection::sessionBus().registerObject("/Kopete", this); + + QObject::connect(d, SIGNAL(contactChanged(QString)), this, SIGNAL(contactChanged(QString))); } KopeteDBusInterface::~KopeteDBusInterface() @@ -91,24 +66,29 @@ { QStringList list; foreach(KPluginInfo p, Kopete::PluginManager::self()->availablePlugins("Protocols")) + { list << p.name(); + } return list; } QStringList KopeteDBusInterface::contacts() const { - return listContact(Kopete::ContactList::self()->metaContacts()); + return d->listContact(Kopete::ContactList::self()->metaContacts()); } QStringList KopeteDBusInterface::contactsByFilter(const QString &filter) const { - QList completeList = Kopete::ContactList::self()->metaContacts(); + QList completeList = + Kopete::ContactList::self()->metaContacts(); QList filteredList; Kopete::MetaContact *contact; if( filter.toLower() == QLatin1String("online") ) { + // "online" returns contacts that are not offline, which means that + // those being away, busy etc. are included as well. foreach(contact, completeList) { if( contact->isOnline() ) @@ -131,11 +111,22 @@ filteredList << contact; } } + else if ( filter.toLower() == QLatin1String("away") ) + { + foreach(contact, completeList) + { + if( contact->status() == Kopete::OnlineStatus::Away ) + { + filteredList << contact; + } + } + } - return listContact(filteredList); + return d->listContact(filteredList); } -void KopeteDBusInterface::setIdentityNickName(const QString &nickName, const QString &identityId) +void KopeteDBusInterface::setIdentityNickName(const QString &nickName, + const QString &identityId) { Kopete::Identity *identity = 0; @@ -150,11 +141,13 @@ if( identity ) { - identity->setProperty( Kopete::Global::Properties::self()->nickName(), nickName ); + identity->setProperty(Kopete::Global::Properties::self()->nickName(), + nickName); } } -void KopeteDBusInterface::setIdentityAvatar(const QString &avatarUrl, const QString &identityId) +void KopeteDBusInterface::setIdentityAvatar(const QString &avatarUrl, + const QString &identityId) { Kopete::Identity *identity = 0; @@ -177,11 +170,13 @@ avatarEntry = Kopete::AvatarManager::self()->add(avatarEntry); - identity->setProperty( Kopete::Global::Properties::self()->photo(), avatarEntry.path ); + identity->setProperty(Kopete::Global::Properties::self()->photo(), + avatarEntry.path); } } -void KopeteDBusInterface::setIdentityOnlineStatus(const QString &status, const QString &message, const QString &identityId) +void KopeteDBusInterface::setIdentityOnlineStatus(const QString &status, + const QString &message, const QString &identityId) { Kopete::Identity *identity = 0; @@ -196,7 +191,7 @@ if( identity ) { - identity->setOnlineStatus( status2Value(status), message ); + identity->setOnlineStatus(d->status2Value(status), message); } } @@ -214,11 +209,14 @@ QString KopeteDBusInterface::labelForIdentity(const QString & id) const { - Kopete::Identity * identity = Kopete::IdentityManager::self()->findIdentity(id); - if ( identity ) { + Kopete::Identity * identity = + Kopete::IdentityManager::self()->findIdentity(id); + if (identity) + { return identity->label(); } - else { + else + { return QString(); } } @@ -237,17 +235,22 @@ void KopeteDBusInterface::connectAll() { - Kopete::AccountManager::self()->setOnlineStatus( Kopete::OnlineStatusManager::Online, QString(), Kopete::AccountManager::ConnectIfOffline ); + Kopete::AccountManager::self()->setOnlineStatus( + Kopete::OnlineStatusManager::Online, QString(), + Kopete::AccountManager::ConnectIfOffline); } void KopeteDBusInterface::disconnectAll() { - Kopete::AccountManager::self()->setOnlineStatus( Kopete::OnlineStatusManager::Offline ); + Kopete::AccountManager::self()->setOnlineStatus( + Kopete::OnlineStatusManager::Offline); } -void KopeteDBusInterface::setOnlineStatus(const QString &status, const QString &message) +void KopeteDBusInterface::setOnlineStatus(const QString &status, + const QString &message) { - Kopete::AccountManager::self()->setOnlineStatus( status2Value(status), message ); + Kopete::AccountManager::self()->setOnlineStatus(d->status2Value(status), + message); } void KopeteDBusInterface::setStatusMessage(const QString &message) @@ -255,42 +258,61 @@ Kopete::AccountManager::self()->setStatusMessage(message); } -void KopeteDBusInterface::sendMessage(const QString &displayName, const QString &message) +void KopeteDBusInterface::sendMessage(const QString &contactId, + const QString &message) { - Kopete::MetaContact *destMetaContact = Kopete::ContactList::self()->findMetaContactByDisplayName(displayName); + Kopete::MetaContact *destMetaContact = d->findContact(contactId); if( destMetaContact && destMetaContact->isReachable() ) { Kopete::Contact *destContact = destMetaContact->execute(); if( destContact ) { - Kopete::Message newMessage( destContact->account()->myself(), destContact ); + Kopete::Message newMessage(destContact->account()->myself(), + destContact); newMessage.setPlainBody( message ); newMessage.setDirection( Kopete::Message::Outbound ); - destContact->manager(Kopete::Contact::CanCreate)->sendMessage( newMessage ); + destContact->manager(Kopete::Contact::CanCreate)->sendMessage( + newMessage); + } + } +} + +void KopeteDBusInterface::openChat(const QString &contactId) +{ + Kopete::MetaContact *contact = d->findContact(contactId); + if (contact && contact->isReachable()) + { + Kopete::Contact *preferredContact = contact->preferredContact(); + if (preferredContact && preferredContact->account() + && preferredContact != preferredContact->account()->myself()) + { + contact->execute(); } } } QString KopeteDBusInterface::getDisplayName(const QString &contactId) { - Kopete::MetaContact *contact = Kopete::ContactList::self()->findMetaContactByContactId(contactId); + Kopete::MetaContact *contact = d->findContact(contactId); if ( contact ) return contact->displayName(); else return ""; } -bool KopeteDBusInterface::isContactOnline(const QString &displayName) +bool KopeteDBusInterface::isContactOnline(const QString &contactId) { - Kopete::MetaContact *contact = Kopete::ContactList::self()->findMetaContactByDisplayName(displayName); + Kopete::MetaContact *contact = d->findContact(contactId); if ( contact ) return contact->isOnline(); else return false; } -bool KopeteDBusInterface::addContact(const QString &protocolName, const QString &accountId, const QString &contactId, const QString &displayName, const QString &groupName) +bool KopeteDBusInterface::addContact(const QString &protocolName, + const QString &accountId, const QString &contactId, + const QString &displayName, const QString &groupName) { QString protocolId = protocolName; if( !protocolName.contains("Protocol") ) @@ -299,7 +321,8 @@ } // Find the account using the given parameters on D-Bus - Kopete::Account *account = Kopete::AccountManager::self()->findAccount( protocolId, accountId ); + Kopete::Account *account = Kopete::AccountManager::self()->findAccount( + protocolId, accountId); if( account ) { @@ -318,7 +341,8 @@ if ( !groupName.isEmpty() ) realGroup = Kopete::ContactList::self()->findGroup( groupName ); - account->addContact( contactId, contactName, realGroup, Kopete::Account::DontChangeKABC); + account->addContact(contactId, contactName, realGroup, + Kopete::Account::DontChangeKABC); return true; } @@ -326,9 +350,10 @@ return false; } -void KopeteDBusInterface::sendFile(const QString &displayName, const QString &fileUrl) +void KopeteDBusInterface::sendFile(const QString &contactId, + const QString &fileUrl) { - Kopete::MetaContact *destMetaContact = Kopete::ContactList::self()->findMetaContactByDisplayName(displayName); + Kopete::MetaContact *destMetaContact = d->findContact(contactId); if( destMetaContact && destMetaContact->isReachable() ) { Kopete::Contact *destContact = destMetaContact->execute(); @@ -339,7 +364,8 @@ } } -bool KopeteDBusInterface::isConnected(const QString &protocolName, const QString &accountId) +bool KopeteDBusInterface::isConnected(const QString &protocolName, + const QString &accountId) { QString protocolId = protocolName; if( !protocolName.contains("Protocol") ) @@ -347,11 +373,13 @@ protocolId += QLatin1String("Protocol"); } - Kopete::Account *account = Kopete::AccountManager::self()->findAccount(protocolId, accountId); + Kopete::Account *account = Kopete::AccountManager::self()->findAccount( + protocolId, accountId); return account ? account->isConnected() : false; } -void KopeteDBusInterface::connect(const QString &protocolName, const QString &accountId) +void KopeteDBusInterface::connect(const QString &protocolName, + const QString &accountId) { QString protocolId = protocolName; if( !protocolName.contains("Protocol") ) @@ -359,14 +387,16 @@ protocolId += QLatin1String("Protocol"); } - Kopete::Account *account = Kopete::AccountManager::self()->findAccount(protocolId, accountId); + Kopete::Account *account = Kopete::AccountManager::self()->findAccount( + protocolId, accountId); if( account ) { account->connect(); } } -void KopeteDBusInterface::disconnect(const QString &protocolName, const QString &accountId) +void KopeteDBusInterface::disconnect(const QString &protocolName, + const QString &accountId) { QString protocolId = protocolName; if( !protocolName.contains("Protocol") ) @@ -374,11 +404,56 @@ protocolId += QLatin1String("Protocol"); } - Kopete::Account *account = Kopete::AccountManager::self()->findAccount(protocolId, accountId); + Kopete::Account *account = Kopete::AccountManager::self()->findAccount( + protocolId, accountId); if( account ) { account->disconnect(); } } +QVariantMap KopeteDBusInterface::contactProperties(const QString &contactId) +{ + QVariantMap properties; + Kopete::MetaContact *contact = d->findContact(contactId); + + if (contact) + { + properties["status"] = Kopete::OnlineStatus::statusTypeToString( + contact->status()); + properties["message_reachable"] = contact->isReachable(); + properties["file_reachable"] = contact->canAcceptFiles(); + properties["display_name"] = contact->displayName(); + properties["id"] = contact->metaContactId(); + if (contact->photoSource() == Kopete::MetaContact::SourceCustom) + { + properties["picture"] = contact->customPhoto().prettyUrl(); + } + else + { + properties["picture"] = contact->picture().path(); + } + properties["idle_time"] = qulonglong(contact->idleTime()); + if (contact->preferredContact()) + { + /** @todo: export status message title as well or merge both? */ + properties["status_message"] + = contact->preferredContact()->statusMessage().message(); + } + + QStringList messages; + foreach(Kopete::Contact *subContact, contact->contacts()) + { + QList pendingMessages = KopeteViewManager::viewManager()->pendingMessages(subContact); + foreach(Kopete::MessageEvent *event, pendingMessages) + { + messages << event->message().parsedBody(); + } + } + properties["pending_messages"] = messages; + } + + return properties; +} + #include "kopetedbusinterface.moc" Index: kopete/kopete/CMakeLists.txt =================================================================== --- kopete/kopete/CMakeLists.txt (revision 847746) +++ kopete/kopete/CMakeLists.txt (working copy) @@ -59,6 +59,7 @@ kopeteidentitystatusbaricon.cpp kopeteaccountstatusbaricon.cpp kopetedbusinterface.cpp + kopetedbusinterface_p.cpp infoeventwidget.cpp ) Index: kopete/kopete/kopetedbusinterface_p.h =================================================================== --- kopete/kopete/kopetedbusinterface_p.h (revision 0) +++ kopete/kopete/kopetedbusinterface_p.h (revision 0) @@ -0,0 +1,93 @@ +/* + kopetedbusinterfaceprivate.h - Kopete D-Bus interface private class + + Copyright (c) 2008 by Dennis Nienhüser + + Kopete (c) 2002-2008 by the Kopete developers + + ************************************************************************* + * * + * 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 of the License, or (at your option) any later version. * + * * + ************************************************************************* + */ + +#ifndef KOPETE_DBUS_INTERFACE_P_H +#define KOPETE_DBUS_INTERFACE_P_H + +#include +#include +#include + +#include "kopetemessage.h" +#include "kopetechatsession.h" +#include "kopetemetacontact.h" + +/** + * Tracks changes of a metacontact and reports them via signals + */ +class ContactStalker: public QObject +{ + Q_OBJECT + +public: + ContactStalker(Kopete::MetaContact *contact); + +Q_SIGNALS: + /** Emitted whenever a property of the tracked contact changed */ + void contactChanged(QString contactId); + +private Q_SLOTS: + void messageAppended( Kopete::Message &message, Kopete::ChatSession *session); + + void slotEmitSignal(); + + void slotEmitSignalDelayed(); + + void slotMetaContactRemoved(Kopete::MetaContact *contact); + +private: + Kopete::MetaContact *m_contact; + + QTime m_lastChange; +}; + +/** + * Tracks changes of all metacontacts and reports them via signals. + * Contains helper functions for KopeteDBusInterface + */ +class KopeteDBusInterfacePrivate: public QObject +{ +Q_OBJECT + +public: + KopeteDBusInterfacePrivate(); + + QStringList listContact(const QList &contactList); + + Kopete::OnlineStatusManager::Categories status2Value(const QString &status); + + /** + * Tries to locate a meta contact using first the protocol:account:contact + * triplet, if that fails the meta contact id, lastly the displayName. + * Returns 0 if nothing is found. + */ + Kopete::MetaContact *findContact(const QString &nameOrId); + +Q_SIGNALS: + /** + * Emmited whenever a contact's property changed + * @param contactId protocol:account:contact triplet of the + * contact with a property change + * */ + void contactChanged(QString contactId); + +private Q_SLOTS: + void slotMetaContactAdded(Kopete::MetaContact* contact); + +}; + +#endif // KOPETE_DBUS_INTERFACE_P_H Index: kopete/kopete/kopetedbusinterface.h =================================================================== --- kopete/kopete/kopetedbusinterface.h (revision 847746) +++ kopete/kopete/kopetedbusinterface.h (working copy) @@ -19,8 +19,9 @@ #define KOPETE_DBUSINTERFACE_H #include +#include -class QStringList; +class KopeteDBusInterfacePrivate; /** * @brief Public D-Bus interface for Kopete @@ -167,10 +168,16 @@ /** * @brief Send a message to the given contact - * @param displayName Metacontact display name to send a messasge + * @param contactId Metacontact ID or displayName to send a message to * @param message The message to send */ - void sendMessage(const QString &displayName, const QString &message); + void sendMessage(const QString &contactId, const QString &message); + + /** + * Open a chat window for the given contact + * @param contactId Metacontact ID or displayName + */ + void openChat(const QString &contactId); /** * @brief Adds a contact with the specified params. @@ -186,26 +193,39 @@ /** * @brief Send a file to the given contact - * @param displayName Metacontact display name to send a file + * @param contactId Metacontact ID or displayName to send a file to * @param fileUrl Url of the file to send */ - void sendFile( const QString &displayName, const QString &fileUrl ); + void sendFile( const QString &contactId, const QString &fileUrl ); /** * @brief Retrieve the Display Name from the given contact ID * @param contactId Metacontact contactId */ - QString getDisplayName(const QString &contactId); /** * @brief Get the Online Status of the contact - * @param displayName The displayName of the contact + * @param contactId Metacontact ID or displayName */ + bool isContactOnline(const QString &contactId); - bool isContactOnline(const QString &displayName); + /** + * Look up details for a specific contact + * @param contactId Contact ID or display Name + * @return A QVariantMap containing contact properties like online status, avatar, ... + */ + QVariantMap contactProperties(const QString &contactId); +Q_SIGNALS: + /** + * Contact properties have changed: displayName, avatar, pending messages... + * @param contactId ID of the contact whose properties have changed + */ + void contactChanged(QString contactId); +private: + KopeteDBusInterfacePrivate *d; }; #endif Index: kopete/kopete/org.kde.Kopete.xml =================================================================== --- kopete/kopete/org.kde.Kopete.xml (revision 847746) +++ kopete/kopete/org.kde.Kopete.xml (working copy) @@ -72,7 +72,7 @@ - + @@ -91,17 +91,27 @@ - + - + - + - + + + + + + + + + + + Index: kopete/libkopete/private/kopeteviewmanager.h =================================================================== --- kopete/libkopete/private/kopeteviewmanager.h (revision 847746) +++ kopete/libkopete/private/kopeteviewmanager.h (working copy) @@ -59,6 +59,12 @@ */ KopeteView *activeView() const; + /** + * Returns unread messages for the given contact + * @param contact Message sender + */ + QList pendingMessages( Kopete::Contact *contact ); + public slots: /** * Make a view visible and on top. Index: kopete/libkopete/private/kopeteviewmanager.cpp =================================================================== --- kopete/libkopete/private/kopeteviewmanager.cpp (revision 847746) +++ kopete/libkopete/private/kopeteviewmanager.cpp (working copy) @@ -484,6 +484,23 @@ } +QList KopeteViewManager::pendingMessages( Kopete::Contact *contact ) +{ + QList pending; + foreach (Kopete::MessageEvent *event, d->eventList) + { + const Kopete::Message &message = event->message(); + if ( event->state() == Kopete::MessageEvent::Nothing + && message.direction() == Kopete::Message::Inbound + && message.from() == contact ) + { + pending << event; + } + } + + return pending; +} + #include "kopeteviewmanager.moc" // vim: set noet ts=4 sts=4 sw=4: --------------070309090305050203090501 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ kopete-devel mailing list kopete-devel@kde.org https://mail.kde.org/mailman/listinfo/kopete-devel --------------070309090305050203090501--