web-dev-qa-db-fra.com

Est-il possible de déconnecter toutes les connexions d'un QObject sans le supprimer

J'ai un QObject A, celui-ci est connecté à un autre QObject B. Maintenant, je veux que A se connecte à C, un troisième QObject et se déconnecte complètement de B.

Peasy facile! Le problème est que j'ai beaucoup de A chacun avec leur propre ensemble de signaux et de slots (les B/C sont plus génériques). Jusqu'à présent, j'ai fait manuellement une méthode de connexion et de déconnexion pour chaque type de classe différent. Les méthodes sont essentiellement des copies les unes des autres échangeant l'appel connect contre disconnect, allant à l'encontre de ne vous répétez pas ).

Ma question est donc la suivante: la fonction suivante est-elle possible?

void deleteAllConnections(QObject* someObject) {
    // TODO disconnect all connections owned by someObject
    // For bonus points: Is there a way of accessing the QMetaObject connected to?
}

J'ai fouillé dans la documentation QMetaObject , QObject et Signals and Slots sans succès (bien que ce ne soit souvent pas une garantie .. .).

22
Troyseph

Il y a au moins 2 façons. Tout d'abord, déconnectez tout.

disconnect(obj,0,0,0);
//or
obj->disconnect();

Seconde. Chaque connect() renvoie QMetaObject::Connection qui peut être copié ou déplacé, de sorte que vous pouvez enregistrer certaines connexions dans la liste et après un certain temps, il suffit de parcourir la liste et d'appeler disconnect() pour chaque objet. Exemple avec une connexion:

QMetaObject::Connection m_connection;
//…
m_connection = QObject::connect(…);
//…
QObject::disconnect(m_connection);

Bonus: non, Qt ne prend pas en charge une introspection aussi profonde, vous ne pouvez pas obtenir la liste de tous les emplacements connectés ou quelque chose d'autre, mais dans la plupart des cas, vous n'en avez pas du tout besoin. Une info utile, que Qt vous donne est sender(), pointeur vers l'objet qui a envoyé le signal.

Modifier

Comme doc l'a dit:

Déconnectez tout ce qui est connecté aux signaux d'un objet

Ainsi, dans l'exemple suivant, les deux fenêtres seront affichées:

QWidget *a = new QWidget;
QWidget *b = new QWidget;

a->setWindowTitle("A");
b->setWindowTitle("B");

QObject::connect(a,SIGNAL(objectNameChanged(QString)),b,SLOT(show()));
QObject::connect(b,SIGNAL(objectNameChanged(QString)),a,SLOT(show()));

//a->disconnect();

a->setObjectName("A");
b->setObjectName("B");

Mais décommentez a->disconnect(); et seules les fenêtres A seront affichées. Cela signifie que QObject::connect(b,SIGNAL(objectNameChanged(QString)),a,SLOT(show())); n'était pas déconnecté comme indiqué dans la doc. Si vous voulez résoudre ce casse-tête, vous pouvez faire a->disconnect(b);b->disconnect(a);, mais c'est bien sûr une très mauvaise approche. Vous pouvez donc utiliser la deuxième suggestion de ma réponse:

QList<QMetaObject::Connection> connections;

QWidget *a = new QWidget;
QWidget *b = new QWidget;

a->setWindowTitle("A");
b->setWindowTitle("B");

connections << QObject::connect(a,SIGNAL(objectNameChanged(QString)),b,SLOT(show()));
connections << QObject::connect(b,SIGNAL(objectNameChanged(QString)),a,SLOT(show()));

foreach (auto var, connections) {
    QObject::disconnect(var);
}

a->setObjectName("A");
b->setObjectName("B");
46
Chernobyl