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