xref: /glogg/src/signalmux.cpp (revision 32e44cfdc623782d0ed539a56e61636702f974ba)
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 
27313a820fSNicolas Bonnefon SignalMux::SignalMux() :
28313a820fSNicolas Bonnefon     connectionList_()
29313a820fSNicolas Bonnefon {
30313a820fSNicolas Bonnefon     currentDocument_ = nullptr;
31313a820fSNicolas Bonnefon }
32313a820fSNicolas Bonnefon 
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 
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
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 
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 
106313a820fSNicolas Bonnefon void SignalMux::setCurrentDocument( QObject* current_document )
107313a820fSNicolas Bonnefon {
108*32e44cfdSNicolas Bonnefon     // First disconnect everything to/from the old document
109*32e44cfdSNicolas Bonnefon     for ( auto c: connectionList_ )
110*32e44cfdSNicolas Bonnefon         disconnect( c );
111*32e44cfdSNicolas Bonnefon 
112313a820fSNicolas Bonnefon     currentDocument_ = current_document;
113*32e44cfdSNicolas Bonnefon 
114*32e44cfdSNicolas Bonnefon     // And now connect to/from the new document
115*32e44cfdSNicolas Bonnefon     for ( auto c: connectionList_ )
116*32e44cfdSNicolas Bonnefon         connect( c );
117313a820fSNicolas Bonnefon }
118313a820fSNicolas Bonnefon 
119313a820fSNicolas Bonnefon /*
120313a820fSNicolas Bonnefon  * Private functions
121313a820fSNicolas Bonnefon  */
122313a820fSNicolas Bonnefon void SignalMux::connect( const Connection& connection )
123313a820fSNicolas Bonnefon {
124313a820fSNicolas Bonnefon     if ( currentDocument_ )
125313a820fSNicolas Bonnefon     {
126313a820fSNicolas Bonnefon         if ( connection.source && ( ! connection.sink ) )
127313a820fSNicolas Bonnefon         {
128313a820fSNicolas Bonnefon             // Downstream signal
129313a820fSNicolas Bonnefon             QObject::connect( connection.source, connection.signal,
130313a820fSNicolas Bonnefon                     currentDocument_, connection.slot );
131313a820fSNicolas Bonnefon         }
132313a820fSNicolas Bonnefon         else if ( ( ! connection.source ) && connection.sink )
133313a820fSNicolas Bonnefon         {
134313a820fSNicolas Bonnefon             // Upstream signal
135313a820fSNicolas Bonnefon             QObject::connect( currentDocument_, connection.signal,
136313a820fSNicolas Bonnefon                     connection.sink, connection.slot );
137313a820fSNicolas Bonnefon         }
138313a820fSNicolas Bonnefon         else
139313a820fSNicolas Bonnefon         {
140313a820fSNicolas Bonnefon             LOG( logERROR ) << "SignalMux has an unexpected signal";
141313a820fSNicolas Bonnefon         }
142313a820fSNicolas Bonnefon     }
143313a820fSNicolas Bonnefon }
144313a820fSNicolas Bonnefon 
145313a820fSNicolas Bonnefon void SignalMux::disconnect( const Connection& connection )
146313a820fSNicolas Bonnefon {
147313a820fSNicolas Bonnefon     if ( currentDocument_ )
148313a820fSNicolas Bonnefon     {
149313a820fSNicolas Bonnefon         if ( connection.source && ( ! connection.sink ) )
150313a820fSNicolas Bonnefon         {
151313a820fSNicolas Bonnefon             // Downstream signal
152313a820fSNicolas Bonnefon             QObject::disconnect( connection.source, connection.signal,
153313a820fSNicolas Bonnefon                     currentDocument_, connection.slot );
154313a820fSNicolas Bonnefon         }
155313a820fSNicolas Bonnefon         else if ( ( ! connection.source ) && connection.sink )
156313a820fSNicolas Bonnefon         {
157313a820fSNicolas Bonnefon             // Upstream signal
158313a820fSNicolas Bonnefon             QObject::disconnect( currentDocument_, connection.signal,
159313a820fSNicolas Bonnefon                     connection.sink, connection.slot );
160313a820fSNicolas Bonnefon         }
161313a820fSNicolas Bonnefon         else
162313a820fSNicolas Bonnefon         {
163313a820fSNicolas Bonnefon             LOG( logERROR ) << "SignalMux has an unexpected signal";
164313a820fSNicolas Bonnefon         }
165313a820fSNicolas Bonnefon     }
166313a820fSNicolas Bonnefon }
167