Bonjour,
J’émets un signal depuis une classe, et que je transmet à un composant QML via la fonction(c++) et
Code : Sélectionner tout - Visualiser dans une fenêtre à part setContextPropertyvia mon composant QML.
Code : Sélectionner tout - Visualiser dans une fenêtre à part Connections{}
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 :et
Code : Sélectionner tout - Visualiser dans une fenêtre à part QML Connections: Binding loop detected for property "target"Je vous met le code ci-dessous des classes concernées.
Code : Sélectionner tout - Visualiser dans une fenêtre à part Expression qrc:/Signin.qml:8:17 depends on non-NOTIFYable properties:
Signin.qml
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 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) } } }
request.h
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") } } }
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"
Partager