Commit ac3810cc authored by Lasath Fernando's avatar Lasath Fernando

The Delegate Channels Patch a.k.a David's massive patch

In the plasmoid:
Convert plasmoid to a handler from an observer
Support delegate channels (via a nasty hack currently)
Add popout button to delegate to main text UI
Merge the conversationsModel and handler into one class
Fix exposing a load of items to QML for no reason.
Some additional tidying. (and some additional messying :-) )
Clear unread messages on TextChannel::pendingMessagesRemoved()

In the textUI:
Always raise the window in the main Text UI handleChannel unless
 hint explicitly says otherwise.
Additionally fixes a bug in which reconnecting an account could
cause the tabs to 'randomly' switch.

REVIEW: 103908
CCBUG: 293526
parent a0bd507f
......@@ -24,12 +24,16 @@
#include <KDebug>
#include "conversation-target.h"
#include "channel-delegator.h"
class Conversation::ConversationPrivate
{
public:
MessagesModel *messages;
ConversationTarget *target;
bool valid;
Tp::AccountPtr account;
};
Conversation::Conversation(const Tp::TextChannelPtr& channel,
......@@ -40,6 +44,8 @@ Conversation::Conversation(const Tp::TextChannelPtr& channel,
{
kDebug();
d->account = account;
d->messages = new MessagesModel(this);
d->messages->setTextChannel(channel);
......@@ -80,10 +86,15 @@ void Conversation::onChannelInvalidated(Tp::DBusProxy* proxy, const QString& err
Q_EMIT validityChanged(d->valid);
}
void Conversation::delegateToProperClient()
{
ChannelDelegator::delegateChannel(d->account, d->messages->textChannel());
}
void Conversation::requestClose()
{
kDebug();
d->messages->requestClose();
d->messages->textChannel()->requestClose();
}
Conversation::~Conversation()
......@@ -91,3 +102,4 @@ Conversation::~Conversation()
kDebug();
delete d;
}
......@@ -27,8 +27,10 @@
#include <TelepathyQt/TextChannel>
#include <KIcon>
#include "conversation-que-manager.h"
#include "conversation-que-manager.h"
#include "conversation-target.h"
#include "messages-model.h"
class ConversationTarget;
class MessagesModel;
......@@ -36,8 +38,8 @@ class KDE_TELEPATHY_CHAT_EXPORT Conversation : public QObject
{
Q_OBJECT
Q_PROPERTY(ConversationTarget* target READ target CONSTANT);
Q_PROPERTY(MessagesModel* messages READ messages CONSTANT);
Q_PROPERTY(QObject* target READ target CONSTANT);
Q_PROPERTY(QObject* messages READ messages CONSTANT);
Q_PROPERTY(bool valid READ isValid NOTIFY validityChanged);
public:
......@@ -54,6 +56,7 @@ Q_SIGNALS:
void validityChanged(bool isValid);
public Q_SLOTS:
void delegateToProperClient();
void requestClose();
private Q_SLOTS:
......
......@@ -19,27 +19,35 @@
#include "conversations-model.h"
#include "conversation.h"
#include "telepathy-text-observer.h"
#include <KDebug>
#include "conversation-target.h"
#include "messages-model.h"
#include "channel-delegator.h"
#include <KDebug>
#include <TelepathyQt/ChannelClassSpec>
#include <TelepathyQt/TextChannel>
#include <TelepathyQt/ClientRegistrar>
static inline Tp::ChannelClassSpecList channelClassList()
{
return Tp::ChannelClassSpecList() << Tp::ChannelClassSpec::textChat();
}
class ConversationsModel::ConversationsModelPrivate
{
public:
TelepathyTextObserver watcher;
QList<Conversation*> conversations;
};
ConversationsModel::ConversationsModel(QObject *parent) :
QAbstractListModel(parent),
ConversationsModel::ConversationsModel() :
QAbstractListModel(),
Tp::AbstractClientHandler(channelClassList()),
d(new ConversationsModelPrivate)
{
QHash<int, QByteArray> roles;
roles[ConversationRole] = "conversation";
setRoleNames(roles);
QObject::connect(&d->watcher, SIGNAL(newConversation(Conversation*)), SLOT(onInconmingConversation(Conversation*)));
}
QVariant ConversationsModel::data(const QModelIndex& index, int role) const
......@@ -60,32 +68,76 @@ int ConversationsModel::rowCount(const QModelIndex& parent) const
return d->conversations.count();
}
void ConversationsModel::onInconmingConversation(Conversation *newConvo)
void ConversationsModel::handleChannels(const Tp::MethodInvocationContextPtr<> &context,
const Tp::AccountPtr &account,
const Tp::ConnectionPtr &connection,
const QList<Tp::ChannelPtr> &channels,
const QList<Tp::ChannelRequestPtr> &channelRequests,
const QDateTime &userActionTime,
const HandlerInfo &handlerInfo)
{
//check if conversation's channel is already being handled, if so replace it
Q_UNUSED(connection);
Q_UNUSED(handlerInfo);
bool handled = false;
Tp::TextChannelPtr newChannel = newConvo->messages()->textChannel();
if (!newChannel->targetHandleType() == Tp::HandleTypeNone) {
//loop through all conversations checking for matches
Q_FOREACH(Conversation *convo, d->conversations) {
if (convo->target()->id() == newChannel->targetId() &&
convo->messages()->textChannel()->targetHandleType() == newChannel->targetHandleType()) {
convo->messages()->setTextChannel(newChannel);
newConvo->deleteLater();
handled = true;
break;
bool shouldDelegate = false;
//check that the channel is of type text
Tp::TextChannelPtr textChannel;
Q_FOREACH(const Tp::ChannelPtr & channel, channels) {
textChannel = Tp::TextChannelPtr::dynamicCast(channel);
if (textChannel) {
break;
}
}
Q_ASSERT(textChannel);
//find the relevant channelRequest
Q_FOREACH(const Tp::ChannelRequestPtr channelRequest, channelRequests) {
kDebug() << channelRequest->hints().allHints();
shouldDelegate = channelRequest->hints().hint(QLatin1String("org.freedesktop.Telepathy.ChannelRequest"), QLatin1String("DelegateToPreferredHandler")).toBool();
}
//loop through all conversations checking for matches
//if we are handling and we're not told to delegate it, update the text channel
//if we are handling but should delegate, call delegate channel
Q_FOREACH(Conversation *convo, d->conversations) {
if (convo->target()->id() == textChannel->targetId() &&
convo->messages()->textChannel()->targetHandleType() == textChannel->targetHandleType())
{
if (!shouldDelegate) {
convo->messages()->setTextChannel(textChannel);
} else {
if (convo->messages()->textChannel() == textChannel) {
ChannelDelegator::delegateChannel(account, textChannel, userActionTime);
}
}
handled = true;
break;
}
}
if (!handled) {
//if we are not handling channel already and should not delegate, add the conversation
//if we not handling the channel but should delegate it, do nothing.
if (!handled && !shouldDelegate) {
beginInsertRows(QModelIndex(), rowCount(), rowCount());
Conversation* newConvo = new Conversation(textChannel, account);
d->conversations.append(newConvo);
connect(newConvo, SIGNAL(validityChanged(bool)), SLOT(handleValidityChange(bool)));
endInsertRows();
context->setFinished();
}
}
bool ConversationsModel::bypassApproval() const
{
return true;
}
void ConversationsModel::handleValidityChange(bool valid)
......
......@@ -22,16 +22,18 @@
#include <QAbstractListModel>
#include <TelepathyQt/AbstractClientApprover>
#include "ktpchat_export.h"
class Conversation;
class KDE_TELEPATHY_CHAT_EXPORT ConversationsModel : public QAbstractListModel
class KDE_TELEPATHY_CHAT_EXPORT ConversationsModel : public QAbstractListModel, public Tp::AbstractClientHandler
{
Q_OBJECT
public:
explicit ConversationsModel(QObject *parent = 0);
explicit ConversationsModel();
virtual ~ConversationsModel();
virtual QVariant data ( const QModelIndex& index, int role = Qt::DisplayRole ) const;
......@@ -41,12 +43,20 @@ public:
ConversationRole = Qt::UserRole
};
void handleChannels(const Tp::MethodInvocationContextPtr<> &context,
const Tp::AccountPtr &account,
const Tp::ConnectionPtr &connection,
const QList<Tp::ChannelPtr> &channels,
const QList<Tp::ChannelRequestPtr> &channelRequests,
const QDateTime &userActionTime,
const HandlerInfo &handlerInfo);
bool bypassApproval() const;
private:
class ConversationsModelPrivate;
ConversationsModelPrivate *d;
private Q_SLOTS:
void onInconmingConversation(Conversation *convo);
void handleValidityChange(bool);
};
......
......@@ -113,7 +113,6 @@ void MessagesModel::setTextChannel(Tp::TextChannelPtr channel)
}
d->textChannel = channel;
Q_EMIT textChannelChanged(d->textChannel);
QList<Tp::ReceivedMessage> messageQueue = channel->messageQueue();
Q_FOREACH(Tp::ReceivedMessage message, messageQueue) {
......@@ -294,15 +293,6 @@ MessagesModel::~MessagesModel()
delete d;
}
void MessagesModel::requestClose()
{
kDebug();
Tp::PendingOperation *op = d->textChannel->requestClose();
connect(op, SIGNAL(finished(Tp::PendingOperation*)),
SLOT(verifyPendingOperation(Tp::PendingOperation*)));
}
void MessagesModel::printallmessages()
{
Q_FOREACH(MessageItem msg, d->messages) {
......
......@@ -54,12 +54,9 @@ public:
int unreadCount() const;
void acknowledgeAllMessages();
void requestClose();
//debug function. will do whatever I feel like at the time ;-)
Q_INVOKABLE void printallmessages();
Q_SIGNALS:
void textChannelChanged(Tp::TextChannelPtr newChannel);
void visibleToUserChanged(bool visible);
void unreadCountChanged(int unreadMesssagesCount);
......
......@@ -22,58 +22,14 @@
#include <KDebug>
#include <TelepathyQt/ChannelClassSpec>
#include <TelepathyQt/TextChannel>
#include <TelepathyQt/AccountFactory>
#include <TelepathyQt/ConnectionFactory>
#include <TelepathyQt/ClientRegistrar>
static inline Tp::ChannelClassSpecList channelClassList()
{
return Tp::ChannelClassSpecList() << Tp::ChannelClassSpec::textChat();
}
class TelepathyTextObserver::ConversationClientObserver :
public Tp::AbstractClientObserver
{
public:
virtual void observeChannels(
const Tp::MethodInvocationContextPtr<>& context,
const Tp::AccountPtr& account,
const Tp::ConnectionPtr& connection,
const QList< Tp::ChannelPtr >& channels,
const Tp::ChannelDispatchOperationPtr& dispatchOperation,
const QList< Tp::ChannelRequestPtr >& requestsSatisfied,
const Tp::AbstractClientObserver::ObserverInfo& observerInfo)
{
kDebug();
//check that the channel is of type text
Tp::TextChannelPtr textChannel;
Q_FOREACH(const Tp::ChannelPtr & channel, channels) {
textChannel = Tp::TextChannelPtr::dynamicCast(channel);
if (textChannel) {
break;
}
}
Q_ASSERT(textChannel);
Conversation *con = new Conversation(textChannel, account);
m_parent->newConversation(con);
}
ConversationClientObserver(TelepathyTextObserver *parent) :
AbstractClientObserver(channelClassList()),
m_parent(parent)
{
}
TelepathyTextObserver *m_parent;
};
TelepathyTextObserver::TelepathyTextObserver() :
observer(new ConversationClientObserver(this))
TelepathyTextObserver::TelepathyTextObserver(QObject* parent) :
QObject(parent),
m_handler(new ConversationsModel())
{
kDebug();
Tp::registerTypes();
......@@ -107,9 +63,16 @@ TelepathyTextObserver::TelepathyTextObserver() :
//TODO: check these to make sure I'm only requesting features I actually use.
m_registrar = Tp::ClientRegistrar::create(accountFactory, connectionFactory,
channelFactory, contactFactory);
m_registrar->registerClient(observer, QLatin1String("KDE.TextUi.ConversationWatcher"));
m_registrar->registerClient(m_handler, QLatin1String("KDE.TextUi.ConversationWatcher")); //KTp.ChatPlasmoid
}
TelepathyTextObserver::~TelepathyTextObserver()
{
}
\ No newline at end of file
qDebug() << "deleting text observer";
}
QAbstractListModel * TelepathyTextObserver::conversationModel()
{
Q_ASSERT(!m_handler.isNull());
return m_handler.data();
}
......@@ -22,23 +22,25 @@
#include "ktpchat_export.h"
#include <TelepathyQt/AbstractClient>
#include "conversations-model.h"
#include <TelepathyQt/AbstractClientHandler>
class Conversation;
class KDE_TELEPATHY_CHAT_EXPORT TelepathyTextObserver : public QObject
{
Q_OBJECT
Q_PROPERTY(QObject* conversations READ conversationModel CONSTANT)
public:
TelepathyTextObserver();
TelepathyTextObserver(QObject* parent=0);
~TelepathyTextObserver();
Q_SIGNALS:
void newConversation(Conversation *con);
QAbstractListModel* conversationModel();
private:
class ConversationClientObserver;
Tp::SharedPtr<ConversationClientObserver> observer;
Tp::SharedPtr<ConversationsModel> m_handler;
Tp::ClientRegistrarPtr m_registrar;
};
......
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