xref: /glogg/src/signalmux.cpp (revision 313a820ff17bfd02bca88e04703027110d330191) !
1*313a820fSNicolas Bonnefon /*
2*313a820fSNicolas Bonnefon  * Copyright (C) 2013 Nicolas Bonnefon and other contributors
3*313a820fSNicolas Bonnefon  *
4*313a820fSNicolas Bonnefon  * This file is part of glogg.
5*313a820fSNicolas Bonnefon  *
6*313a820fSNicolas Bonnefon  * glogg is free software: you can redistribute it and/or modify
7*313a820fSNicolas Bonnefon  * it under the terms of the GNU General Public License as published by
8*313a820fSNicolas Bonnefon  * the Free Software Foundation, either version 3 of the License, or
9*313a820fSNicolas Bonnefon  * (at your option) any later version.
10*313a820fSNicolas Bonnefon  *
11*313a820fSNicolas Bonnefon  * glogg is distributed in the hope that it will be useful,
12*313a820fSNicolas Bonnefon  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*313a820fSNicolas Bonnefon  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*313a820fSNicolas Bonnefon  * GNU General Public License for more details.
15*313a820fSNicolas Bonnefon  *
16*313a820fSNicolas Bonnefon  * You should have received a copy of the GNU General Public License
17*313a820fSNicolas Bonnefon  * along with glogg.  If not, see <http://www.gnu.org/licenses/>.
18*313a820fSNicolas Bonnefon  */
19*313a820fSNicolas Bonnefon 
20*313a820fSNicolas Bonnefon #include "signalmux.h"
21*313a820fSNicolas Bonnefon 
22*313a820fSNicolas Bonnefon #include <algorithm>
23*313a820fSNicolas Bonnefon #include <QObject>
24*313a820fSNicolas Bonnefon 
25*313a820fSNicolas Bonnefon #include "log.h"
26*313a820fSNicolas Bonnefon 
27*313a820fSNicolas Bonnefon SignalMux::SignalMux() :
28*313a820fSNicolas Bonnefon     connectionList_()
29*313a820fSNicolas Bonnefon {
30*313a820fSNicolas Bonnefon     currentDocument_ = nullptr;
31*313a820fSNicolas Bonnefon }
32*313a820fSNicolas Bonnefon 
33*313a820fSNicolas Bonnefon void SignalMux::connect( QObject *sender,
34*313a820fSNicolas Bonnefon         const char *signal, const char *slot )
35*313a820fSNicolas Bonnefon {
36*313a820fSNicolas Bonnefon     Connection new_connection = {
37*313a820fSNicolas Bonnefon             sender,
38*313a820fSNicolas Bonnefon             nullptr,
39*313a820fSNicolas Bonnefon             signal,
40*313a820fSNicolas Bonnefon             slot };
41*313a820fSNicolas Bonnefon 
42*313a820fSNicolas Bonnefon     connectionList_.push_back( new_connection );
43*313a820fSNicolas Bonnefon 
44*313a820fSNicolas Bonnefon     connect( new_connection );
45*313a820fSNicolas Bonnefon }
46*313a820fSNicolas Bonnefon 
47*313a820fSNicolas Bonnefon void SignalMux::disconnect( QObject *sender,
48*313a820fSNicolas Bonnefon         const char *signal, const char *slot )
49*313a820fSNicolas Bonnefon {
50*313a820fSNicolas Bonnefon     // Find any signal that match our description
51*313a820fSNicolas Bonnefon     auto connection = std::find_if(
52*313a820fSNicolas Bonnefon             connectionList_.begin(), connectionList_.end(),
53*313a820fSNicolas Bonnefon             [sender, signal, slot]( const Connection& c ) -> bool
54*313a820fSNicolas Bonnefon             { return ((QObject*)c.source == sender) && (c.sink == nullptr) &&
55*313a820fSNicolas Bonnefon                 (qstrcmp( c.signal, signal) == 0) && (qstrcmp( c.slot, slot) == 0); } );
56*313a820fSNicolas Bonnefon 
57*313a820fSNicolas Bonnefon     if ( connection != connectionList_.end() )
58*313a820fSNicolas Bonnefon     {
59*313a820fSNicolas Bonnefon         disconnect( *connection );
60*313a820fSNicolas Bonnefon 
61*313a820fSNicolas Bonnefon         connectionList_.erase( connection );
62*313a820fSNicolas Bonnefon     }
63*313a820fSNicolas Bonnefon     else
64*313a820fSNicolas Bonnefon     {
65*313a820fSNicolas Bonnefon         LOG( logERROR ) << "SignalMux disconnecting a non-existing signal";
66*313a820fSNicolas Bonnefon     }
67*313a820fSNicolas Bonnefon }
68*313a820fSNicolas Bonnefon 
69*313a820fSNicolas Bonnefon // Upstream signals
70*313a820fSNicolas Bonnefon void SignalMux::connect( const char* signal,
71*313a820fSNicolas Bonnefon         QObject* receiver, const char* slot )
72*313a820fSNicolas Bonnefon {
73*313a820fSNicolas Bonnefon     Connection new_connection = {
74*313a820fSNicolas Bonnefon             nullptr,
75*313a820fSNicolas Bonnefon             receiver,
76*313a820fSNicolas Bonnefon             signal,
77*313a820fSNicolas Bonnefon             slot };
78*313a820fSNicolas Bonnefon 
79*313a820fSNicolas Bonnefon     connectionList_.push_back( new_connection );
80*313a820fSNicolas Bonnefon 
81*313a820fSNicolas Bonnefon     connect( new_connection );
82*313a820fSNicolas Bonnefon }
83*313a820fSNicolas Bonnefon 
84*313a820fSNicolas Bonnefon void SignalMux::disconnect( const char *signal,
85*313a820fSNicolas Bonnefon         QObject* receiver, const char *slot )
86*313a820fSNicolas Bonnefon {
87*313a820fSNicolas Bonnefon     // Find any signal that match our description
88*313a820fSNicolas Bonnefon     auto connection = std::find_if(
89*313a820fSNicolas Bonnefon             connectionList_.begin(), connectionList_.end(),
90*313a820fSNicolas Bonnefon             [receiver, signal, slot]( const Connection& c ) -> bool
91*313a820fSNicolas Bonnefon             { return ((QObject*)c.sink == receiver) && (c.source == nullptr) &&
92*313a820fSNicolas Bonnefon                 (qstrcmp( c.signal, signal) == 0) && (qstrcmp( c.slot, slot) == 0); } );
93*313a820fSNicolas Bonnefon 
94*313a820fSNicolas Bonnefon     if ( connection != connectionList_.end() )
95*313a820fSNicolas Bonnefon     {
96*313a820fSNicolas Bonnefon         disconnect( *connection );
97*313a820fSNicolas Bonnefon 
98*313a820fSNicolas Bonnefon         connectionList_.erase( connection );
99*313a820fSNicolas Bonnefon     }
100*313a820fSNicolas Bonnefon     else
101*313a820fSNicolas Bonnefon     {
102*313a820fSNicolas Bonnefon         LOG( logERROR ) << "SignalMux disconnecting a non-existing signal";
103*313a820fSNicolas Bonnefon     }
104*313a820fSNicolas Bonnefon }
105*313a820fSNicolas Bonnefon 
106*313a820fSNicolas Bonnefon void SignalMux::setCurrentDocument( QObject* current_document )
107*313a820fSNicolas Bonnefon {
108*313a820fSNicolas Bonnefon     currentDocument_ = current_document;
109*313a820fSNicolas Bonnefon }
110*313a820fSNicolas Bonnefon 
111*313a820fSNicolas Bonnefon /*
112*313a820fSNicolas Bonnefon  * Private functions
113*313a820fSNicolas Bonnefon  */
114*313a820fSNicolas Bonnefon void SignalMux::connect( const Connection& connection )
115*313a820fSNicolas Bonnefon {
116*313a820fSNicolas Bonnefon     if ( currentDocument_ )
117*313a820fSNicolas Bonnefon     {
118*313a820fSNicolas Bonnefon         if ( connection.source && ( ! connection.sink ) )
119*313a820fSNicolas Bonnefon         {
120*313a820fSNicolas Bonnefon             // Downstream signal
121*313a820fSNicolas Bonnefon             QObject::connect( connection.source, connection.signal,
122*313a820fSNicolas Bonnefon                     currentDocument_, connection.slot );
123*313a820fSNicolas Bonnefon         }
124*313a820fSNicolas Bonnefon         else if ( ( ! connection.source ) && connection.sink )
125*313a820fSNicolas Bonnefon         {
126*313a820fSNicolas Bonnefon             // Upstream signal
127*313a820fSNicolas Bonnefon             QObject::connect( currentDocument_, connection.signal,
128*313a820fSNicolas Bonnefon                     connection.sink, connection.slot );
129*313a820fSNicolas Bonnefon         }
130*313a820fSNicolas Bonnefon         else
131*313a820fSNicolas Bonnefon         {
132*313a820fSNicolas Bonnefon             LOG( logERROR ) << "SignalMux has an unexpected signal";
133*313a820fSNicolas Bonnefon         }
134*313a820fSNicolas Bonnefon     }
135*313a820fSNicolas Bonnefon }
136*313a820fSNicolas Bonnefon 
137*313a820fSNicolas Bonnefon void SignalMux::disconnect( const Connection& connection )
138*313a820fSNicolas Bonnefon {
139*313a820fSNicolas Bonnefon     if ( currentDocument_ )
140*313a820fSNicolas Bonnefon     {
141*313a820fSNicolas Bonnefon         if ( connection.source && ( ! connection.sink ) )
142*313a820fSNicolas Bonnefon         {
143*313a820fSNicolas Bonnefon             // Downstream signal
144*313a820fSNicolas Bonnefon             QObject::disconnect( connection.source, connection.signal,
145*313a820fSNicolas Bonnefon                     currentDocument_, connection.slot );
146*313a820fSNicolas Bonnefon         }
147*313a820fSNicolas Bonnefon         else if ( ( ! connection.source ) && connection.sink )
148*313a820fSNicolas Bonnefon         {
149*313a820fSNicolas Bonnefon             // Upstream signal
150*313a820fSNicolas Bonnefon             QObject::disconnect( currentDocument_, connection.signal,
151*313a820fSNicolas Bonnefon                     connection.sink, connection.slot );
152*313a820fSNicolas Bonnefon         }
153*313a820fSNicolas Bonnefon         else
154*313a820fSNicolas Bonnefon         {
155*313a820fSNicolas Bonnefon             LOG( logERROR ) << "SignalMux has an unexpected signal";
156*313a820fSNicolas Bonnefon         }
157*313a820fSNicolas Bonnefon     }
158*313a820fSNicolas Bonnefon }
159