xref: /glogg/src/signalmux.cpp (revision 84af0c9b75fb9369ab66df476dd881cd6d30efcf)
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     // And ask the doc to emit all state signals
119     MuxableDocumentInterface* doc =
120         dynamic_cast<MuxableDocumentInterface*>( current_document );
121     if ( doc )
122         doc->sendAllStateSignals();
123 }
124 
125 /*
126  * Private functions
127  */
128 void SignalMux::connect( const Connection& connection )
129 {
130     if ( currentDocument_ )
131     {
132         LOG( logDEBUG ) << "SignalMux::connect";
133         if ( connection.source && ( ! connection.sink ) )
134         {
135             // Downstream signal
136             QObject::connect( connection.source, connection.signal,
137                     currentDocument_, connection.slot );
138         }
139         else if ( ( ! connection.source ) && connection.sink )
140         {
141             // Upstream signal
142             QObject::connect( currentDocument_, connection.signal,
143                     connection.sink, connection.slot );
144         }
145         else
146         {
147             LOG( logERROR ) << "SignalMux has an unexpected signal";
148         }
149     }
150 }
151 
152 void SignalMux::disconnect( const Connection& connection )
153 {
154     if ( currentDocument_ )
155     {
156         LOG( logDEBUG ) << "SignalMux::disconnect";
157         if ( connection.source && ( ! connection.sink ) )
158         {
159             // Downstream signal
160             QObject::disconnect( connection.source, connection.signal,
161                     currentDocument_, connection.slot );
162         }
163         else if ( ( ! connection.source ) && connection.sink )
164         {
165             // Upstream signal
166             QObject::disconnect( currentDocument_, connection.signal,
167                     connection.sink, connection.slot );
168         }
169         else
170         {
171             LOG( logERROR ) << "SignalMux has an unexpected signal";
172         }
173     }
174 }
175