I am trying to temporarily remove this connection:
connect(clipBoard, SIGNAL(dataChanged()), this, SLOT(copiage())); (line 20)
I have tried all I could but it always end up with a crash. I really have no clue about what causes this. It always crash at the moment I try to deactivate the connection (line 93) just before the line:
clipBoard->setText(messageRecu); (line 94)
The idea is that I don't want the connection when it is the program itself that changes the clipboard.
Anyone can help me on why it crashes?
Here is the .h:
#ifndef FENCLIENT_H
#define FENCLIENT_H
#include <QtWidgets>
#include <QtNetwork>
#include <QClipboard>
#include "ui_fenclient.h"
class FenClient : public QWidget, private Ui::FenClient
{
Q_OBJECT
public:
FenClient();
private slots:
void on_boutonConnexion_clicked();
void on_boutonEnvoyer_clicked();
void on_message_returnPressed();
void donneesRecues();
void connecte();
void deconnecte();
void erreurSocket(QAbstractSocket::SocketError erreur);
void copiage();
private:
QTcpSocket *socket; // Représente le serveur
quint16 tailleMessage;
QClipboard *clipBoard;
};
#endif // FENCLIENT_H
Here is the .cpp
#include "fenclient.h"
using namespace std;
#include<iostream>
#include <ostream>//sinon cout marche pas
FenClient::FenClient()
{
setupUi(this);
socket = new QTcpSocket(this);
connect(socket, SIGNAL(readyRead()), this, SLOT(donneesRecues()));
connect(socket, SIGNAL(connected()), this, SLOT(connecte()));
connect(socket, SIGNAL(disconnected()), this, SLOT(deconnecte()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(erreurSocket(QAbstractSocket::SocketError)));
tailleMessage = 0;
QClipboard *clipBoard = QGuiApplication::clipboard();//Ca a été long mais il me faut ca...pas tout compris
connect(clipBoard, SIGNAL(dataChanged()), this, SLOT(copiage()));
}
// Tentative de connexion au serveur
void FenClient::on_boutonConnexion_clicked()
{
// On annonce sur la fenêtre qu'on est en train de se connecter
listeMessages->append(tr("<em>Tentative de connexion en cours...</em>"));
boutonConnexion->setEnabled(false);
socket->abort(); // On désactive les connexions précédentes s'il y en a
socket->connectToHost(serveurIP->text(), serveurPort->value()); // On se connecte au serveur demandé
}
// Envoi d'un message au serveur
void FenClient::on_boutonEnvoyer_clicked()
{
QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
// On prépare le paquet à envoyer
QString messageAEnvoyer = message->text();//on enlève tr("<strong>") + pseudo->text() +tr("</strong> : ") +
out << (quint16) 0;
out << messageAEnvoyer;
out.device()->seek(0);
out << (quint16) (paquet.size() - sizeof(quint16));
socket->write(paquet); // On envoie le paquet
message->clear(); // On vide la zone d'écriture du message
message->setFocus(); // Et on remet le curseur à l'intérieur
}
// Appuyer sur la touche Entrée a le même effet que cliquer sur le bouton "Envoyer"
void FenClient::on_message_returnPressed()
{
on_boutonEnvoyer_clicked();
}
// On a reçu un paquet (ou un sous-paquet)
void FenClient::donneesRecues()
{
/* Même principe que lorsque le serveur reçoit un paquet :
On essaie de récupérer la taille du message
Une fois qu'on l'a, on attend d'avoir reçu le message entier (en se basant sur la taille annoncée tailleMessage)
*/
QDataStream in(socket);
if (tailleMessage == 0)
{
if (socket->bytesAvailable() < (int)sizeof(quint16))
return;
in >> tailleMessage;
}
if (socket->bytesAvailable() < tailleMessage)
return;
// Si on arrive jusqu'à cette ligne, on peut récupérer le message entier
QString messageRecu;
in >> messageRecu;
// On affiche le message sur la zone de Chat
listeMessages->append(messageRecu);
//clipBoard->disconnect();
//const QSignalBlocker blocker(clipBoard);
//on met dans le clipBoard
cout << "Avant " << endl;
bool oldState = clipBoard->blockSignals(true);
clipBoard->setText(messageRecu);
clipBoard->blockSignals(oldState);
cout << "Après " << endl;
//connect(clipBoard, SIGNAL(dataChanged()), this, SLOT(copiage()));
// On remet la taille du message à 0 pour pouvoir recevoir de futurs messages
tailleMessage = 0;
}
// Ce slot est appelé lorsque la connexion au serveur a réussi
void FenClient::connecte()
{
listeMessages->append(tr("<em>Connexion réussie !</em>"));
boutonConnexion->setEnabled(true);
}
// Ce slot est appelé lorsqu'on est déconnecté du serveur
void FenClient::deconnecte()
{
listeMessages->append(tr("<em>Déconnecté du serveur</em>"));
}
// Ce slot est appelé lorsqu'on que le presse-papiers change
void FenClient::copiage()
{ cout << "Copiage= " << endl;
/* QString textCopie;
textCopie = clipBoard->text();
QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
// On prépare le paquet à envoyer
QString messageAEnvoyer = textCopie;
out << (quint16) 0;
out << messageAEnvoyer;
out.device()->seek(0);
out << (quint16) (paquet.size() - sizeof(quint16));
socket->write(paquet); // On envoie le paquet
//message->clear(); // On vide la zone d'écriture du message
//message->setFocus(); // Et on remet le curseur à l'intérieur */
}
// Ce slot est appelé lorsqu'il y a une erreur
void FenClient::erreurSocket(QAbstractSocket::SocketError erreur)
{
switch(erreur) // On affiche un message différent selon l'erreur qu'on nous indique
{
case QAbstractSocket::HostNotFoundError:
listeMessages->append(tr("<em>ERREUR : le serveur n'a pas pu être trouvé. Vérifiez l'IP et le port.</em>"));
break;
case QAbstractSocket::ConnectionRefusedError:
listeMessages->append(tr("<em>ERREUR : le serveur a refusé la connexion. Vérifiez si le programme \"serveur\" a bien été lancé. Vérifiez aussi l'IP et le port.</em>"));
break;
case QAbstractSocket::RemoteHostClosedError:
listeMessages->append(tr("<em>ERREUR : le serveur a coupé la connexion.</em>"));
break;
default:
listeMessages->append(tr("<em>ERREUR : ") + socket->errorString() + tr("</em>"));
}
boutonConnexion->setEnabled(true);
}
In your constructor definition, you have written:
You should have written instead:
Since
clipBoard
is a field member of yourFenClient
class, why do you try to declare another local variable with the same name of an already existing one (which will likely remains uninitialized) ?Actually, this is probably the reason why your
clipBoard::blockSignals()
failed.You have shadowed your
clipBoard
field member. In other words, it was never initialized.Dereferencing a uninitialized pointer leads to undefined behaviour. Anything can happen, in your case you got a crash.
I have not read your whole code so it may contain other issues.
Note:
In order to remove a connection, you better have to use the
QObject::disconnect()
method.It allows you to be more accurate/specific (about which connections to remove, ...).
QObject::blockSignals()
does not give you this granularity since it blocks all connections.Other thing, you should stop to use the old macros
SIGNAL()
andSLOT()
and use the new signal-slot syntax instead.So in your case, the connection would be something like:
And the symmetric disconnection:
Note that
QObject::disconnect()
really removes the connection so if you want to get it back, you'll need to recreate it by callingQObject::connect()
again.