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