xref: /glogg/src/signalmux.cpp (revision 9cacd6a97a0b10112ec2ce02191415958748faec)
1313a820fSNicolas Bonnefon /*
2313a820fSNicolas Bonnefon  * Copyright (C) 2013 Nicolas Bonnefon and other contributors
3313a820fSNicolas Bonnefon  *
4313a820fSNicolas Bonnefon  * This file is part of glogg.
5313a820fSNicolas Bonnefon  *
6313a820fSNicolas Bonnefon  * glogg is free software: you can redistribute it and/or modify
7313a820fSNicolas Bonnefon  * it under the terms of the GNU General Public License as published by
8313a820fSNicolas Bonnefon  * the Free Software Foundation, either version 3 of the License, or
9313a820fSNicolas Bonnefon  * (at your option) any later version.
10313a820fSNicolas Bonnefon  *
11313a820fSNicolas Bonnefon  * glogg is distributed in the hope that it will be useful,
12313a820fSNicolas Bonnefon  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13313a820fSNicolas Bonnefon  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14313a820fSNicolas Bonnefon  * GNU General Public License for more details.
15313a820fSNicolas Bonnefon  *
16313a820fSNicolas Bonnefon  * You should have received a copy of the GNU General Public License
17313a820fSNicolas Bonnefon  * along with glogg.  If not, see <http://www.gnu.org/licenses/>.
18313a820fSNicolas Bonnefon  */
19313a820fSNicolas Bonnefon 
20313a820fSNicolas Bonnefon #include "signalmux.h"
21313a820fSNicolas Bonnefon 
22313a820fSNicolas Bonnefon #include <algorithm>
23313a820fSNicolas Bonnefon #include <QObject>
24313a820fSNicolas Bonnefon 
25313a820fSNicolas Bonnefon #include "log.h"
26313a820fSNicolas Bonnefon 
SignalMux()27313a820fSNicolas Bonnefon SignalMux::SignalMux() :
28313a820fSNicolas Bonnefon     connectionList_()
29313a820fSNicolas Bonnefon {
30313a820fSNicolas Bonnefon     currentDocument_ = nullptr;
31313a820fSNicolas Bonnefon }
32313a820fSNicolas Bonnefon 
connect(QObject * sender,const char * signal,const char * slot)33313a820fSNicolas Bonnefon void SignalMux::connect( QObject *sender,
34313a820fSNicolas Bonnefon         const char *signal, const char *slot )
35313a820fSNicolas Bonnefon {
36313a820fSNicolas Bonnefon     Connection new_connection = {
37313a820fSNicolas Bonnefon             sender,
38313a820fSNicolas Bonnefon             nullptr,
39313a820fSNicolas Bonnefon             signal,
40313a820fSNicolas Bonnefon             slot };
41313a820fSNicolas Bonnefon 
42313a820fSNicolas Bonnefon     connectionList_.push_back( new_connection );
43313a820fSNicolas Bonnefon 
44313a820fSNicolas Bonnefon     connect( new_connection );
45313a820fSNicolas Bonnefon }
46313a820fSNicolas Bonnefon 
disconnect(QObject * sender,const char * signal,const char * slot)47313a820fSNicolas Bonnefon void SignalMux::disconnect( QObject *sender,
48313a820fSNicolas Bonnefon         const char *signal, const char *slot )
49313a820fSNicolas Bonnefon {
50313a820fSNicolas Bonnefon     // Find any signal that match our description
51313a820fSNicolas Bonnefon     auto connection = std::find_if(
52313a820fSNicolas Bonnefon             connectionList_.begin(), connectionList_.end(),
53313a820fSNicolas Bonnefon             [sender, signal, slot]( const Connection& c ) -> bool
54313a820fSNicolas Bonnefon             { return ((QObject*)c.source == sender) && (c.sink == nullptr) &&
55313a820fSNicolas Bonnefon                 (qstrcmp( c.signal, signal) == 0) && (qstrcmp( c.slot, slot) == 0); } );
56313a820fSNicolas Bonnefon 
57313a820fSNicolas Bonnefon     if ( connection != connectionList_.end() )
58313a820fSNicolas Bonnefon     {
59313a820fSNicolas Bonnefon         disconnect( *connection );
60313a820fSNicolas Bonnefon 
61313a820fSNicolas Bonnefon         connectionList_.erase( connection );
62313a820fSNicolas Bonnefon     }
63313a820fSNicolas Bonnefon     else
64313a820fSNicolas Bonnefon     {
65313a820fSNicolas Bonnefon         LOG( logERROR ) << "SignalMux disconnecting a non-existing signal";
66313a820fSNicolas Bonnefon     }
67313a820fSNicolas Bonnefon }
68313a820fSNicolas Bonnefon 
69313a820fSNicolas Bonnefon // Upstream signals
connect(const char * signal,QObject * receiver,const char * slot)70313a820fSNicolas Bonnefon void SignalMux::connect( const char* signal,
71313a820fSNicolas Bonnefon         QObject* receiver, const char* slot )
72313a820fSNicolas Bonnefon {
73313a820fSNicolas Bonnefon     Connection new_connection = {
74313a820fSNicolas Bonnefon             nullptr,
75313a820fSNicolas Bonnefon             receiver,
76313a820fSNicolas Bonnefon             signal,
77313a820fSNicolas Bonnefon             slot };
78313a820fSNicolas Bonnefon 
79313a820fSNicolas Bonnefon     connectionList_.push_back( new_connection );
80313a820fSNicolas Bonnefon 
81313a820fSNicolas Bonnefon     connect( new_connection );
82313a820fSNicolas Bonnefon }
83313a820fSNicolas Bonnefon 
disconnect(const char * signal,QObject * receiver,const char * slot)84313a820fSNicolas Bonnefon void SignalMux::disconnect( const char *signal,
85313a820fSNicolas Bonnefon         QObject* receiver, const char *slot )
86313a820fSNicolas Bonnefon {
87313a820fSNicolas Bonnefon     // Find any signal that match our description
88313a820fSNicolas Bonnefon     auto connection = std::find_if(
89313a820fSNicolas Bonnefon             connectionList_.begin(), connectionList_.end(),
90313a820fSNicolas Bonnefon             [receiver, signal, slot]( const Connection& c ) -> bool
91313a820fSNicolas Bonnefon             { return ((QObject*)c.sink == receiver) && (c.source == nullptr) &&
92313a820fSNicolas Bonnefon                 (qstrcmp( c.signal, signal) == 0) && (qstrcmp( c.slot, slot) == 0); } );
93313a820fSNicolas Bonnefon 
94313a820fSNicolas Bonnefon     if ( connection != connectionList_.end() )
95313a820fSNicolas Bonnefon     {
96313a820fSNicolas Bonnefon         disconnect( *connection );
97313a820fSNicolas Bonnefon 
98313a820fSNicolas Bonnefon         connectionList_.erase( connection );
99313a820fSNicolas Bonnefon     }
100313a820fSNicolas Bonnefon     else
101313a820fSNicolas Bonnefon     {
102313a820fSNicolas Bonnefon         LOG( logERROR ) << "SignalMux disconnecting a non-existing signal";
103313a820fSNicolas Bonnefon     }
104313a820fSNicolas Bonnefon }
105313a820fSNicolas Bonnefon 
setCurrentDocument(QObject * current_document)106313a820fSNicolas Bonnefon void SignalMux::setCurrentDocument( QObject* current_document )
107313a820fSNicolas Bonnefon {
10832e44cfdSNicolas Bonnefon     // First disconnect everything to/from the old document
10932e44cfdSNicolas Bonnefon     for ( auto c: connectionList_ )
11032e44cfdSNicolas Bonnefon         disconnect( c );
11132e44cfdSNicolas Bonnefon 
112313a820fSNicolas Bonnefon     currentDocument_ = current_document;
11332e44cfdSNicolas Bonnefon 
11432e44cfdSNicolas Bonnefon     // And now connect to/from the new document
11532e44cfdSNicolas Bonnefon     for ( auto c: connectionList_ )
11632e44cfdSNicolas Bonnefon         connect( c );
117*9cacd6a9SNicolas Bonnefon 
118*9cacd6a9SNicolas Bonnefon     // And ask the doc to emit all state signals
119*9cacd6a9SNicolas Bonnefon     MuxableDocumentInterface* doc =
120*9cacd6a9SNicolas Bonnefon         dynamic_cast<MuxableDocumentInterface*>( current_document );
121*9cacd6a9SNicolas Bonnefon     if ( doc )
122*9cacd6a9SNicolas Bonnefon         doc->sendAllStateSignals();
123313a820fSNicolas Bonnefon }
124313a820fSNicolas Bonnefon 
125313a820fSNicolas Bonnefon /*
126313a820fSNicolas Bonnefon  * Private functions
127313a820fSNicolas Bonnefon  */
connect(const Connection & connection)128313a820fSNicolas Bonnefon void SignalMux::connect( const Connection& connection )
129313a820fSNicolas Bonnefon {
130313a820fSNicolas Bonnefon     if ( currentDocument_ )
131313a820fSNicolas Bonnefon     {
13227ddfd3aSNicolas Bonnefon         LOG( logDEBUG ) << "SignalMux::connect";
133313a820fSNicolas Bonnefon         if ( connection.source && ( ! connection.sink ) )
134313a820fSNicolas Bonnefon         {
135313a820fSNicolas Bonnefon             // Downstream signal
136313a820fSNicolas Bonnefon             QObject::connect( connection.source, connection.signal,
137313a820fSNicolas Bonnefon                     currentDocument_, connection.slot );
138313a820fSNicolas Bonnefon         }
139313a820fSNicolas Bonnefon         else if ( ( ! connection.source ) && connection.sink )
140313a820fSNicolas Bonnefon         {
141313a820fSNicolas Bonnefon             // Upstream signal
142313a820fSNicolas Bonnefon             QObject::connect( currentDocument_, connection.signal,
143313a820fSNicolas Bonnefon                     connection.sink, connection.slot );
144313a820fSNicolas Bonnefon         }
145313a820fSNicolas Bonnefon         else
146313a820fSNicolas Bonnefon         {
147313a820fSNicolas Bonnefon             LOG( logERROR ) << "SignalMux has an unexpected signal";
148313a820fSNicolas Bonnefon         }
149313a820fSNicolas Bonnefon     }
150313a820fSNicolas Bonnefon }
151313a820fSNicolas Bonnefon 
disconnect(const Connection & connection)152313a820fSNicolas Bonnefon void SignalMux::disconnect( const Connection& connection )
153313a820fSNicolas Bonnefon {
154313a820fSNicolas Bonnefon     if ( currentDocument_ )
155313a820fSNicolas Bonnefon     {
15627ddfd3aSNicolas Bonnefon         LOG( logDEBUG ) << "SignalMux::disconnect";
157313a820fSNicolas Bonnefon         if ( connection.source && ( ! connection.sink ) )
158313a820fSNicolas Bonnefon         {
159313a820fSNicolas Bonnefon             // Downstream signal
160313a820fSNicolas Bonnefon             QObject::disconnect( connection.source, connection.signal,
161313a820fSNicolas Bonnefon                     currentDocument_, connection.slot );
162313a820fSNicolas Bonnefon         }
163313a820fSNicolas Bonnefon         else if ( ( ! connection.source ) && connection.sink )
164313a820fSNicolas Bonnefon         {
165313a820fSNicolas Bonnefon             // Upstream signal
166313a820fSNicolas Bonnefon             QObject::disconnect( currentDocument_, connection.signal,
167313a820fSNicolas Bonnefon                     connection.sink, connection.slot );
168313a820fSNicolas Bonnefon         }
169313a820fSNicolas Bonnefon         else
170313a820fSNicolas Bonnefon         {
171313a820fSNicolas Bonnefon             LOG( logERROR ) << "SignalMux has an unexpected signal";
172313a820fSNicolas Bonnefon         }
173313a820fSNicolas Bonnefon     }
174313a820fSNicolas Bonnefon }
175