1313a820fSNicolas Bonnefon /* 2313a820fSNicolas Bonnefon * Copyright (C) 2013 Nicolas Bonnefon and other contributors 3313a820fSNicolas Bonnefon * 4313a820fSNicolas Bonnefon * This file is part of glogg. 5313a820fSNicolas Bonnefon * 6313a820fSNicolas Bonnefon * glogg is free software: you can redistribute it and/or modify 7313a820fSNicolas Bonnefon * it under the terms of the GNU General Public License as published by 8313a820fSNicolas Bonnefon * the Free Software Foundation, either version 3 of the License, or 9313a820fSNicolas Bonnefon * (at your option) any later version. 10313a820fSNicolas Bonnefon * 11313a820fSNicolas Bonnefon * glogg is distributed in the hope that it will be useful, 12313a820fSNicolas Bonnefon * but WITHOUT ANY WARRANTY; without even the implied warranty of 13313a820fSNicolas Bonnefon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14313a820fSNicolas Bonnefon * GNU General Public License for more details. 15313a820fSNicolas Bonnefon * 16313a820fSNicolas Bonnefon * You should have received a copy of the GNU General Public License 17313a820fSNicolas Bonnefon * along with glogg. If not, see <http://www.gnu.org/licenses/>. 18313a820fSNicolas Bonnefon */ 19313a820fSNicolas Bonnefon 20313a820fSNicolas Bonnefon #include "signalmux.h" 21313a820fSNicolas Bonnefon 22313a820fSNicolas Bonnefon #include <algorithm> 23313a820fSNicolas Bonnefon #include <QObject> 24313a820fSNicolas Bonnefon 25313a820fSNicolas Bonnefon #include "log.h" 26313a820fSNicolas Bonnefon 27313a820fSNicolas Bonnefon SignalMux::SignalMux() : 28313a820fSNicolas Bonnefon connectionList_() 29313a820fSNicolas Bonnefon { 30313a820fSNicolas Bonnefon currentDocument_ = nullptr; 31313a820fSNicolas Bonnefon } 32313a820fSNicolas Bonnefon 33313a820fSNicolas Bonnefon void SignalMux::connect( QObject *sender, 34313a820fSNicolas Bonnefon const char *signal, const char *slot ) 35313a820fSNicolas Bonnefon { 36313a820fSNicolas Bonnefon Connection new_connection = { 37313a820fSNicolas Bonnefon sender, 38313a820fSNicolas Bonnefon nullptr, 39313a820fSNicolas Bonnefon signal, 40313a820fSNicolas Bonnefon slot }; 41313a820fSNicolas Bonnefon 42313a820fSNicolas Bonnefon connectionList_.push_back( new_connection ); 43313a820fSNicolas Bonnefon 44313a820fSNicolas Bonnefon connect( new_connection ); 45313a820fSNicolas Bonnefon } 46313a820fSNicolas Bonnefon 47313a820fSNicolas Bonnefon void SignalMux::disconnect( QObject *sender, 48313a820fSNicolas Bonnefon const char *signal, const char *slot ) 49313a820fSNicolas Bonnefon { 50313a820fSNicolas Bonnefon // Find any signal that match our description 51313a820fSNicolas Bonnefon auto connection = std::find_if( 52313a820fSNicolas Bonnefon connectionList_.begin(), connectionList_.end(), 53313a820fSNicolas Bonnefon [sender, signal, slot]( const Connection& c ) -> bool 54313a820fSNicolas Bonnefon { return ((QObject*)c.source == sender) && (c.sink == nullptr) && 55313a820fSNicolas Bonnefon (qstrcmp( c.signal, signal) == 0) && (qstrcmp( c.slot, slot) == 0); } ); 56313a820fSNicolas Bonnefon 57313a820fSNicolas Bonnefon if ( connection != connectionList_.end() ) 58313a820fSNicolas Bonnefon { 59313a820fSNicolas Bonnefon disconnect( *connection ); 60313a820fSNicolas Bonnefon 61313a820fSNicolas Bonnefon connectionList_.erase( connection ); 62313a820fSNicolas Bonnefon } 63313a820fSNicolas Bonnefon else 64313a820fSNicolas Bonnefon { 65313a820fSNicolas Bonnefon LOG( logERROR ) << "SignalMux disconnecting a non-existing signal"; 66313a820fSNicolas Bonnefon } 67313a820fSNicolas Bonnefon } 68313a820fSNicolas Bonnefon 69313a820fSNicolas Bonnefon // Upstream signals 70313a820fSNicolas Bonnefon void SignalMux::connect( const char* signal, 71313a820fSNicolas Bonnefon QObject* receiver, const char* slot ) 72313a820fSNicolas Bonnefon { 73313a820fSNicolas Bonnefon Connection new_connection = { 74313a820fSNicolas Bonnefon nullptr, 75313a820fSNicolas Bonnefon receiver, 76313a820fSNicolas Bonnefon signal, 77313a820fSNicolas Bonnefon slot }; 78313a820fSNicolas Bonnefon 79313a820fSNicolas Bonnefon connectionList_.push_back( new_connection ); 80313a820fSNicolas Bonnefon 81313a820fSNicolas Bonnefon connect( new_connection ); 82313a820fSNicolas Bonnefon } 83313a820fSNicolas Bonnefon 84313a820fSNicolas Bonnefon void SignalMux::disconnect( const char *signal, 85313a820fSNicolas Bonnefon QObject* receiver, const char *slot ) 86313a820fSNicolas Bonnefon { 87313a820fSNicolas Bonnefon // Find any signal that match our description 88313a820fSNicolas Bonnefon auto connection = std::find_if( 89313a820fSNicolas Bonnefon connectionList_.begin(), connectionList_.end(), 90313a820fSNicolas Bonnefon [receiver, signal, slot]( const Connection& c ) -> bool 91313a820fSNicolas Bonnefon { return ((QObject*)c.sink == receiver) && (c.source == nullptr) && 92313a820fSNicolas Bonnefon (qstrcmp( c.signal, signal) == 0) && (qstrcmp( c.slot, slot) == 0); } ); 93313a820fSNicolas Bonnefon 94313a820fSNicolas Bonnefon if ( connection != connectionList_.end() ) 95313a820fSNicolas Bonnefon { 96313a820fSNicolas Bonnefon disconnect( *connection ); 97313a820fSNicolas Bonnefon 98313a820fSNicolas Bonnefon connectionList_.erase( connection ); 99313a820fSNicolas Bonnefon } 100313a820fSNicolas Bonnefon else 101313a820fSNicolas Bonnefon { 102313a820fSNicolas Bonnefon LOG( logERROR ) << "SignalMux disconnecting a non-existing signal"; 103313a820fSNicolas Bonnefon } 104313a820fSNicolas Bonnefon } 105313a820fSNicolas Bonnefon 106313a820fSNicolas Bonnefon void SignalMux::setCurrentDocument( QObject* current_document ) 107313a820fSNicolas Bonnefon { 108*32e44cfdSNicolas Bonnefon // First disconnect everything to/from the old document 109*32e44cfdSNicolas Bonnefon for ( auto c: connectionList_ ) 110*32e44cfdSNicolas Bonnefon disconnect( c ); 111*32e44cfdSNicolas Bonnefon 112313a820fSNicolas Bonnefon currentDocument_ = current_document; 113*32e44cfdSNicolas Bonnefon 114*32e44cfdSNicolas Bonnefon // And now connect to/from the new document 115*32e44cfdSNicolas Bonnefon for ( auto c: connectionList_ ) 116*32e44cfdSNicolas Bonnefon connect( c ); 117313a820fSNicolas Bonnefon } 118313a820fSNicolas Bonnefon 119313a820fSNicolas Bonnefon /* 120313a820fSNicolas Bonnefon * Private functions 121313a820fSNicolas Bonnefon */ 122313a820fSNicolas Bonnefon void SignalMux::connect( const Connection& connection ) 123313a820fSNicolas Bonnefon { 124313a820fSNicolas Bonnefon if ( currentDocument_ ) 125313a820fSNicolas Bonnefon { 126313a820fSNicolas Bonnefon if ( connection.source && ( ! connection.sink ) ) 127313a820fSNicolas Bonnefon { 128313a820fSNicolas Bonnefon // Downstream signal 129313a820fSNicolas Bonnefon QObject::connect( connection.source, connection.signal, 130313a820fSNicolas Bonnefon currentDocument_, connection.slot ); 131313a820fSNicolas Bonnefon } 132313a820fSNicolas Bonnefon else if ( ( ! connection.source ) && connection.sink ) 133313a820fSNicolas Bonnefon { 134313a820fSNicolas Bonnefon // Upstream signal 135313a820fSNicolas Bonnefon QObject::connect( currentDocument_, connection.signal, 136313a820fSNicolas Bonnefon connection.sink, connection.slot ); 137313a820fSNicolas Bonnefon } 138313a820fSNicolas Bonnefon else 139313a820fSNicolas Bonnefon { 140313a820fSNicolas Bonnefon LOG( logERROR ) << "SignalMux has an unexpected signal"; 141313a820fSNicolas Bonnefon } 142313a820fSNicolas Bonnefon } 143313a820fSNicolas Bonnefon } 144313a820fSNicolas Bonnefon 145313a820fSNicolas Bonnefon void SignalMux::disconnect( const Connection& connection ) 146313a820fSNicolas Bonnefon { 147313a820fSNicolas Bonnefon if ( currentDocument_ ) 148313a820fSNicolas Bonnefon { 149313a820fSNicolas Bonnefon if ( connection.source && ( ! connection.sink ) ) 150313a820fSNicolas Bonnefon { 151313a820fSNicolas Bonnefon // Downstream signal 152313a820fSNicolas Bonnefon QObject::disconnect( connection.source, connection.signal, 153313a820fSNicolas Bonnefon currentDocument_, connection.slot ); 154313a820fSNicolas Bonnefon } 155313a820fSNicolas Bonnefon else if ( ( ! connection.source ) && connection.sink ) 156313a820fSNicolas Bonnefon { 157313a820fSNicolas Bonnefon // Upstream signal 158313a820fSNicolas Bonnefon QObject::disconnect( currentDocument_, connection.signal, 159313a820fSNicolas Bonnefon connection.sink, connection.slot ); 160313a820fSNicolas Bonnefon } 161313a820fSNicolas Bonnefon else 162313a820fSNicolas Bonnefon { 163313a820fSNicolas Bonnefon LOG( logERROR ) << "SignalMux has an unexpected signal"; 164313a820fSNicolas Bonnefon } 165313a820fSNicolas Bonnefon } 166313a820fSNicolas Bonnefon } 167