~ubuntu-branches/ubuntu/saucy/kopete/saucy-proposed

« back to all changes in this revision

Viewing changes to libkopete/kopetemessagehandlerchain.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2013-06-21 02:22:39 UTC
  • Revision ID: package-import@ubuntu.com-20130621022239-63l3zc8p0nf26pt6
Tags: upstream-4.10.80
ImportĀ upstreamĀ versionĀ 4.10.80

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    kopetemessagehandlerchain.h - Kopete Message Handler Chain
 
3
 
 
4
    Copyright (c) 2004      by Richard Smith         <kde@metafoo.co.uk>
 
5
    Kopete    (c) 2002-2004 by the Kopete developers <kopete-devel@kde.org>
 
6
 
 
7
    *************************************************************************
 
8
    *                                                                       *
 
9
    * This library is free software; you can redistribute it and/or         *
 
10
    * modify it under the terms of the GNU Lesser General Public            *
 
11
    * License as published by the Free Software Foundation; either          *
 
12
    * version 2 of the License, or (at your option) any later version.      *
 
13
    *                                                                       *
 
14
    *************************************************************************
 
15
*/
 
16
 
 
17
#include "kopetemessagehandlerchain.h"
 
18
#include "kopetemessagehandler.h"
 
19
#include "kopetemessageevent.h"
 
20
#include "kopetechatsession.h"
 
21
 
 
22
#include <kdebug.h>
 
23
 
 
24
#include <QMap>
 
25
#include <QTimer>
 
26
#include <QList>
 
27
 
 
28
namespace Kopete
 
29
{
 
30
 
 
31
class MessageHandlerChainTerminator : public MessageHandler
 
32
{
 
33
public:
 
34
        void handleMessage( MessageEvent *event )
 
35
        {
 
36
                kError( 14010 ) << "message got to end of chain!" << endl;
 
37
                event->discard();
 
38
        }
 
39
        int capabilities()
 
40
        {
 
41
                kError( 14010 ) << "request got to end of chain!" << endl;
 
42
                return 0;
 
43
        }
 
44
};
 
45
 
 
46
// BEGIN MessageHandlerChain
 
47
 
 
48
class MessageHandlerChain::Private
 
49
{
 
50
public:
 
51
        Private() : first(0) {}
 
52
        MessageHandler *first;
 
53
};
 
54
 
 
55
MessageHandlerChain::Ptr MessageHandlerChain::create( ChatSession *manager, Message::MessageDirection direction )
 
56
{
 
57
        // create the handler chain
 
58
        MessageHandlerChain *chain = new MessageHandlerChain;
 
59
        
 
60
        // grab the list of handler factories
 
61
        typedef MessageHandlerFactory::FactoryList FactoryList;
 
62
        FactoryList factories = MessageHandlerFactory::messageHandlerFactories();
 
63
        
 
64
        // create a sorted list of handlers
 
65
        typedef QList<MessageHandler*> HandlerList;
 
66
        typedef QMap<int,HandlerList> HandlerMap;
 
67
        HandlerMap handlers;
 
68
        uint count = 0;
 
69
        for( FactoryList::Iterator it = factories.begin(); it != factories.end(); ++it )
 
70
        {
 
71
                int position = (*it)->filterPosition( manager, direction );
 
72
                if ( position == MessageHandlerFactory::StageDoNotCreate )
 
73
                        continue;
 
74
                MessageHandler *handler = (*it)->create( manager, direction );
 
75
                if ( handler )
 
76
                {
 
77
                        ++count;
 
78
                        handlers[ position ].append( handler );
 
79
                }
 
80
        }
 
81
        
 
82
        kDebug(14010) << "got " << count << " handlers for chain";
 
83
        
 
84
        // add the handlers to the chain
 
85
        MessageHandler *curr = 0;
 
86
        for( HandlerMap::Iterator it = handlers.begin(); it != handlers.end(); ++it )
 
87
        {
 
88
                for ( HandlerList::Iterator handlerIt = (*it).begin(); handlerIt != (*it).end(); ++handlerIt )
 
89
                {
 
90
                        if ( curr )
 
91
                                curr->setNext( *handlerIt );
 
92
                        else
 
93
                                chain->d->first = *handlerIt;
 
94
                        curr = *handlerIt;
 
95
                }
 
96
        }
 
97
        
 
98
        // add a terminator to avoid crashes if the message somehow manages to get to the
 
99
        // end of the chain. maybe we should use a MessageHandlerFactory for this too?
 
100
        MessageHandler *terminator = new MessageHandlerChainTerminator;
 
101
        if ( curr )
 
102
                curr->setNext( terminator );
 
103
        else // empty chain: might happen for dir == Internal
 
104
                chain->d->first = terminator;
 
105
        
 
106
        return MessageHandlerChain::Ptr(chain);
 
107
}
 
108
 
 
109
MessageHandlerChain::MessageHandlerChain()
 
110
 : QObject( 0 ), d( new Private )
 
111
{
 
112
}
 
113
 
 
114
MessageHandlerChain::~MessageHandlerChain()
 
115
{
 
116
        kDebug(14010) ;
 
117
        MessageHandler *handler = d->first;
 
118
        while( handler )
 
119
        {
 
120
                MessageHandler *next = handler->next();
 
121
                delete handler;
 
122
                handler = next;
 
123
        }
 
124
        delete d;
 
125
}
 
126
 
 
127
 
 
128
ProcessMessageTask *MessageHandlerChain::processMessage( const Message &message )
 
129
{
 
130
        MessageEvent *event = new MessageEvent( message );
 
131
        return new ProcessMessageTask( MessageHandlerChain::Ptr(this), event );
 
132
}
 
133
 
 
134
int MessageHandlerChain::capabilities()
 
135
{
 
136
        return d->first->capabilities();
 
137
}
 
138
 
 
139
// END MessageHandlerChain
 
140
 
 
141
// BEGIN ProcessMessageTask
 
142
 
 
143
class ProcessMessageTask::Private
 
144
{
 
145
public:
 
146
        Private( MessageHandlerChain::Ptr chain, MessageEvent *event ) : chain(chain), event(event) {}
 
147
        MessageHandlerChain::Ptr chain;
 
148
        MessageEvent *event;
 
149
};
 
150
 
 
151
ProcessMessageTask::ProcessMessageTask( MessageHandlerChain::Ptr chain, MessageEvent *event )
 
152
 : d( new Private(chain, event) )
 
153
{
 
154
        QTimer::singleShot( 0, this, SLOT(start()) );
 
155
        connect( event, SIGNAL(done(Kopete::MessageEvent*)), this, SLOT(slotDone()) );
 
156
        event->message().manager()->ref();
 
157
}
 
158
 
 
159
ProcessMessageTask::~ProcessMessageTask()
 
160
{
 
161
        delete d;
 
162
}
 
163
 
 
164
void ProcessMessageTask::start()
 
165
{
 
166
        d->chain->d->first->handleMessageInternal( d->event );
 
167
}
 
168
 
 
169
void ProcessMessageTask::slotDone()
 
170
{
 
171
        if ( d->event->message().manager() ) // In case manager was deleted during exit
 
172
                d->event->message().manager()->deref();
 
173
 
 
174
        emitResult();
 
175
}
 
176
 
 
177
void ProcessMessageTask::kill(bool quite)
 
178
{
 
179
        Q_UNUSED(quite);
 
180
}
 
181
 
 
182
 
 
183
MessageEvent *ProcessMessageTask::event()
 
184
{
 
185
        return d->event;
 
186
}
 
187
 
 
188
//END ProcessMessageTask
 
189
 
 
190
}
 
191
 
 
192
#include "kopetemessagehandlerchain.moc"
 
193
 
 
194
// vim: set noet ts=4 sts=4 sw=4: