2015-02-10 21 views
6

mia domanda conteneva diverse funzioni come questo:Collegamento segnali e slot a un oggetto all'interno di un QSharedPointer

void SomeClass::set_data_provider(DataProvider *data_provider) 
{ 
    connect(data_provider, SIGNAL(data_available(int)), 
     this, SLOT(data_available(int))); 
} 

per evitare di passare i puntatori prime intorno ho cambiato tutte le occorrenze di DataProvider *-QSharedPointer<DataProvider>. Quest'ultimo è quasi un rimpiazzo per il primo, tranne per il fatto che non è possibile passare un QSharedPointer a QObject::connect. Ho lavorato intorno a questo estraendo un puntatore RAW dalla QSharedPointer:

void SomeClass::set_data_provider(QSharedPointer<DataProvider> data_provider) 
{ 
    connect(data_provider.data(), SIGNAL(data_available(int)), 
     this, SLOT(data_available(int))); 
} 

Questo sembra funzionare bene ma sembra poco elegante e io sono diffidare di accesso al puntatore grezzo come questo. C'è un modo migliore per connettersi a un oggetto che viene passato in giro in un QSharedPointer?

risposta

2

È possibile creare un collegamento funzione:

template<class T> bool 
my_connect(const QSharedPointer<T> &sender, 
      const char *signal, 
      const QObject *receiver, 
      const char *method, 
      Qt::ConnectionType type = Qt::AutoConnection) 
{ 
    return QObject::connect(sender.data(), signal, receiver, method, type); 
} 

e usarlo in questo modo:

QSharedPointer<MyObject> shared(new MyObject); 
my_connect(shared, SIGNAL(my_signal()), this, SLOT(my_slot())); 

L'unico problema è che in entrambe le soluzioni tua e la mia si perde Qt Creator completamento automatico per la funzione di connessione nativa.

P.S. Per quanto riguarda me, non cambierei il tuo codice. Penso che vada bene :)

+0

Questo è interessante, non sapevo che potessi farlo. Tuttavia, non penso che migliori l'originale. È molto più ordinato usare QMetaData/qRegisterMetaType dato che questo è esattamente il motivo del meccanismo:), in più mantieni il tuo auto completo :)) –

+0

Suppongo che l'OP non abbia chiesto come inviare oggetti 'QSharedPointer' tramite lo slot del segnale meccanismo (in questo caso si dovrebbe usare 'qRegisterMetaType') ma come passare un oggetto' QSharedPointer' alla funzione 'connect'. – hank

+0

Ma "Come inviare QSharedPointer tramite lo slot del segnale" e "come passare un oggetto QSharedPointer alla funzione di connessione" ... sono praticamente la stessa cosa poiché il collegamento fa parte del meccanismo dello slot del segnale. Ma comunque, mi piace molto quello che hai fatto, è fuori dagli schemi, ma stavo solo sottolineando che non è il modo migliore (forse solo secondo me). –

1

Per completezza, ecco un'estensione della risposta di @ hank. I fornire sei connect funzioni -come:

  • connect_from_pointer prende un QSharedPointer come primo argomento e la solita QObject * come terzo argomento.
  • connect_to_pointer prende il solito QObject * come primo argomento e un QSharedPointer come terzo argomento.
  • connect_pointers utilizza QSharedPointers per entrambi i parametri.

Ci sono due versioni di ciascuno di questi: uno che accetta la sintassi SIGNAL()/SLOT() e uno che accetta le (consigliato) puntatori a funzione.

Questi sono sintatticamente atroci, ma questo è un modello per te.

template<class T> 
QMetaObject::Connection connect_from_pointer(
    const QSharedPointer<T>& sender, 
    const char *signal, 
    const QObject *receiver, 
    const char *method, 
    Qt::ConnectionType type = Qt::AutoConnection) 
{ 
    return QObject::connect(sender.data(), signal, receiver, method, type); 
} 

template <typename Func1, typename Func2> 
QMetaObject::Connection connect_from_pointer(
    const QSharedPointer<typename QtPrivate::FunctionPointer<Func1>::Object>& sender, 
    Func1 signal, 
    const typename QtPrivate::FunctionPointer<Func2>::Object *receiver, 
    Func2 slot, 
    Qt::ConnectionType type = Qt::AutoConnection) 
{ 
    return QObject::connect(sender.data(), signal, receiver, slot, type); 
} 

template<class T> 
QMetaObject::Connection connect_to_pointer(
    const QObject *sender, 
    const char *signal, 
    const QSharedPointer<T>& receiver, 
    const char *method, 
    Qt::ConnectionType type = Qt::AutoConnection) 
{ 
    return QObject::connect(sender, signal, receiver.data(), method, type); 
} 

template <typename Func1, typename Func2> 
QMetaObject::Connection connect_to_pointer(
    const typename QtPrivate::FunctionPointer<Func1>::Object *sender, 
    Func1 signal, 
    const QSharedPointer<typename QtPrivate::FunctionPointer<Func2>::Object>& receiver, 
    Func2 slot, 
    Qt::ConnectionType type = Qt::AutoConnection) 
{ 
    return QObject::connect(sender, signal, receiver.data(), slot, type); 
} 

template<class T, class U> 
QMetaObject::Connection connect_pointers(
    const QSharedPointer<T>& sender, 
    const char *signal, 
    const QSharedPointer<U>& receiver, 
    const char *method, 
    Qt::ConnectionType type = Qt::AutoConnection) 
{ 
    return QObject::connect(sender.data(), signal, receiver.data(), method, type); 
} 

template <typename Func1, typename Func2> 
QMetaObject::Connection connect_pointers(
    const QSharedPointer<typename QtPrivate::FunctionPointer<Func1>::Object>& sender, 
    Func1 signal, 
    const QSharedPointer<typename QtPrivate::FunctionPointer<Func2>::Object>& receiver, 
    Func2 slot, 
    Qt::ConnectionType type = Qt::AutoConnection) 
{ 
    return QObject::connect(sender.data(), signal, receiver.data(), slot, type); 
} 
+0

No lambda love? – iKlsR

Problemi correlati