Bonjour,

J’émets un signal depuis une classe, et que je transmet à un composant QML via la fonction (c++) et via mon composant QML.

Cette classe est créée sur l'event d'un bouton. (je vois bien les actions liées a cette classe).
Par contre, pour récupérer le signal émis par la classe , c'est la que ça coince.
QML ne voit pas le signal.
En debug, je vois passer des warnings :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
 QML Connections: Binding loop detected for property "target"
et
Code : Sélectionner tout - Visualiser dans une fenêtre à part
Expression qrc:/Signin.qml:8:17 depends on non-NOTIFYable properties:
Je vous met le code ci-dessous des classes concernées.

Signin.qml
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 
import QtQuick 2.10
import QtQuick.Controls 2.3
 
Item {
    id: test
 
    Connections{
        target: http
        onLogin: console.log("test")
    }
 
    TextInput {
        id: login
        x: 280
        y: 183
        width: 100
        height: 23
        text: qsTr("Login ")
        font.pixelSize: 12
    }
 
    TextInput {
        id: password
        x: 280
        y: 219
        width: 100
        height: 20
        text: qsTr("Password")
        echoMode: TextInput.Password
        font.pixelSize: 12
    }
 
    Button {
        id: send
        x: 280
        y: 257
        width: 61
        height: 25
        text: qsTr("Connect")
        onClicked:{
            http.start_request("myurl", "443", "/login", 11, "POST", "username=" + login.text + "&password=" + password.text)
        }
    }
}
Main.qml
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 
import QtQuick 2.7
import QtQuick.Window 2.2
import QtQuick.Controls 2.3
import QtQuick.Layouts 1.3
 
Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Doze Chat ")
 
    Index {
        id: chat
        visible: false
    }
 
    SwipeView {
        id: swipeView
        anchors.fill: parent
        currentIndex: tabBar.currentIndex
 
        Signin {
            id: signin
        }
 
        Signup {
            id: signup
        }
}
 
    TabBar {
            id: tabBar
            x: 274
            y: 123
            currentIndex: swipeView.currentIndex
 
            TabButton {
                text: qsTr("Login")
            }
            TabButton {
                text: qsTr("Register")
            }
    }
 
}
request.h
Code qt : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
 
#ifndef REQUEST_H
#define REQUEST_H
 
#include <QString>
#include "hash_password.h"
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl/error.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <QObject>
 
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
 
using tcp = boost::asio::ip::tcp;
namespace ssl = boost::asio::ssl;
namespace http = boost::beast::http;
namespace pt = boost::property_tree;
 
class request : public QObject, public std::enable_shared_from_this<request>
{
    Q_OBJECT
 
signals:
    void login();
 
public:
    explicit request(boost::asio::io_context& ioc, boost::asio::ssl::context& ctx);
    void run(char const* host, char const* port, char const* target, int version, QString method, QString body = NULL);
    Q_INVOKABLE void start_request( QString host, QString port, QString target, int version, QString method, QString body = NULL);
    std::string respond;
    QString GetmessageError;
 
private:
    hash_password hashed_password;
    tcp::resolver resolver;
    boost::asio::ssl::stream<tcp::socket> stream;
    boost::beast::flat_buffer buffer;
    boost::beast::http::request<http::string_body> req;
    boost::beast::http::response<http::string_body> res;
 
    void on_resolve(boost::system::error_code ec, boost::asio::ip::tcp::resolver::results_type results);
    void on_connect(boost::system::error_code ec);
    void on_handshake(boost::system::error_code ec);
    void on_write(boost::system::error_code ec, std::size_t bytes_transferred);
    void on_read(boost::system::error_code ec, std::size_t bytes_transferred);
    void on_shutdown(boost::system::error_code ec);
    void fail(boost::system::error_code ec, char const* what);
 
    //json_parser Jsonresponse;
    std::string GetApiResponse(std::stringstream Jsonres, pt::ptree root);
 
};
 
#endif // REQUEST_H

request.cpp
Code qt : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
 
#include "request.h"
#include <iostream>
#include <boost/beast/http/verb.hpp>
#include <boost/utility/string_view.hpp>
 
//#include <boost/property_tree/ptree.hpp>
//#include <boost/property_tree/json_parser.hpp>
 
request::request(boost::asio::io_context& ioc, ssl::context& ctx) : resolver(ioc) , stream(ioc, ctx)
{
 
}
 
void request::fail(boost::system::error_code ec, char const* what)
{
    std::cerr << what << ": " << ec.message() << "\n";
}
 
void request::run(char const* host, char const* port, char const* target, int version, QString method, QString body)
{
    // Set SNI Hostname (many hosts need this to handshake successfully)
    if(! SSL_set_tlsext_host_name(stream.native_handle(), host))
    {
        boost::system::error_code ec{static_cast<int>(::ERR_get_error()), boost::asio::error::get_ssl_category()};
        std::cerr << ec.message() << "\n";
        respond = "test" ;
        return;
    }
 
    // Set up an HTTP GET request message
    http::verb method_verb;
    boost::string_view method_strview ;
    method_strview = method.toStdString();
    method_verb = boost::beast::http::string_to_verb(method_strview);
    req.version(version);
    req.method(method_verb);
    req.target(target);
    req.set(http::field::host, host);
    req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
    req.set(http::field::content_type, "application/x-www-form-urlencoded");
    req.body() = body.toStdString() ;
    req.prepare_payload();
 
    // Look up the domain name
    resolver.async_resolve(host, port, std::bind(&request::on_resolve, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
 }
 
void request::on_resolve(boost::system::error_code ec, tcp::resolver::results_type results)
{
    if(ec){
        //return fail(ec, "resolve");
        respond = "test" ;
    }
    // Make the connection on the IP address we get from a lookup
    boost::asio::async_connect(stream.next_layer(), results.begin(), results.end(), std::bind( &request::on_connect, shared_from_this(), std::placeholders::_1));
}
 
void request::on_connect(boost::system::error_code ec)
{
    if(ec){
        //return fail(ec, "connect");
         respond = ec.message();
        }
 
    // Perform the SSL handshake
    stream.async_handshake(ssl::stream_base::client, std::bind(&request::on_handshake, shared_from_this(), std::placeholders::_1));
}
 
void request::on_handshake(boost::system::error_code ec)
{
    if(ec){
        return fail(ec, "handshake");
    }
 
    // Send the HTTP request to the remote host
    http::async_write(stream, req, std::bind(&request::on_write, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
}
 
void request::on_write(boost::system::error_code ec, std::size_t bytes_transferred)
{
    boost::ignore_unused(bytes_transferred);
 
    if(ec)
        return fail(ec, "write");
 
    // Receive the HTTP response
    http::async_read(stream, buffer, res, std::bind(&request::on_read, shared_from_this(), std::placeholders::_1, std::placeholders::_2));
}
 
void request::on_read(boost::system::error_code ec, std::size_t bytes_transferred)
{
    boost::ignore_unused(bytes_transferred);
 
    if(ec)
        return fail(ec, "read");
 
    switch(res.result_int())
    {
    case 200: {
        emit login(); //Le signal est la !
        std::cout<<res.result_int()<<std::endl;
              }
        break;
 
    }
 
    // Gracefully close the stream
    stream.async_shutdown(std::bind(&request::on_shutdown, shared_from_this(), std::placeholders::_1));
}
 
void request::on_shutdown(boost::system::error_code ec)
{
    if(ec == boost::asio::error::eof)
    {
        ec.assign(0, ec.category());
    }
    if(ec)
      return fail(ec, "shutdown");
 
    // If we get here then the connection is closed gracefully
}
 
void request::start_request(QString host, QString port, QString target, int version, QString method, QString body)
{
    boost::asio::io_context ioc;
    ssl::context ctx{ssl::context::sslv23_client};
 
    const char* std_host = host.toStdString().c_str();
    const char* std_port = port.toStdString().c_str();
    const char* std_target = target.toStdString().c_str();
    const char* std_method = method.toStdString().c_str();
    const char* std_body = body.toStdString().c_str();
 
    std::make_shared<request>(ioc, ctx)->run(std_host, std_port, std_target, version, std_method, std_body );
    ioc.run();
}
 
std::string request::GetApiResponse(std::stringstream Jsonres, pt::ptree root)
{
    pt::read_json(Jsonres, root);
    std::cout<<root.get<std::string>("user.permission")<<std::endl;
    return root.get<std::string>("user.permission");
}

main.cpp
Code qt : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
 
#include <QGuiApplication>
#include <QQmlApplicationEngine>
 
#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
 
#include "tcp_client.h"
#include "message.h"
#include "observer.h"
#include "request.h"
 
#include <QDebug>
#include <QObject>
#include <QQuickItem>
#include <QQmlContext>
 
struct testmessage : public observer
{
    virtual void update(message data)
    {
        switch (data.m_type)
        {
        case  message::NEW_MSG:
        {
            std::string chaine = "[" + data.m_login + "]: ";
            chaine += data.m_message;
            std::cout <<"test"<< chaine << std::endl;
        }
            break;
        case message::PERSON_CONNECTED:  std::cout << "Nouvelle personne!" << std::endl;
            break;
        case message::PERSON_LEAVED: std::cout << "Une personne nous quitte" << std::endl;
            break;
            //default:
        }
    }
};
 
boost::asio::io_service io_service;
 
int main(int argc, char *argv[])
{
    //test connexion
 
    QGuiApplication app(argc, argv);
 
    QQmlApplicationEngine engine;
 
    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string("192.168.226.132"), 4000);
    std::string login = "allo";
 
    boost::asio::io_context ioc;
    boost::asio::ssl::context ctx{ssl::context::sslv23_client};
    tcp_client c(io_service, endpoint, login);
    request request(ioc, ctx);
 
 
    engine.rootContext()->setContextProperty("tcp_client", &c);
    engine.rootContext()->setContextProperty("http", &request);
 
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
 
    return app.exec();
}

En sachant que j'ai crée une simple application QML, avec un bouton qui appelle une classe c++. cette classe émet un signal. Ce signal est bien reçu par QML.
La je comprends plus rien.
PS : Je vois bien le std::cout du switch concerné qui m'affiche "200"