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 if ( connection.source && ( ! connection.sink ) ) 127 { 128 // Downstream signal 129 QObject::connect( connection.source, connection.signal, 130 currentDocument_, connection.slot ); 131 } 132 else if ( ( ! connection.source ) && connection.sink ) 133 { 134 // Upstream signal 135 QObject::connect( currentDocument_, connection.signal, 136 connection.sink, connection.slot ); 137 } 138 else 139 { 140 LOG( logERROR ) << "SignalMux has an unexpected signal"; 141 } 142 } 143 } 144 145 void SignalMux::disconnect( const Connection& connection ) 146 { 147 if ( currentDocument_ ) 148 { 149 if ( connection.source && ( ! connection.sink ) ) 150 { 151 // Downstream signal 152 QObject::disconnect( connection.source, connection.signal, 153 currentDocument_, connection.slot ); 154 } 155 else if ( ( ! connection.source ) && connection.sink ) 156 { 157 // Upstream signal 158 QObject::disconnect( currentDocument_, connection.signal, 159 connection.sink, connection.slot ); 160 } 161 else 162 { 163 LOG( logERROR ) << "SignalMux has an unexpected signal"; 164 } 165 } 166 } 167