add an example to embed a server in a Qt GUI app
parent
c3643277b2
commit
233aa5910c
@ -0,0 +1,11 @@
|
||||
project(qt_app_server)
|
||||
|
||||
find_package(Qt5 CONFIG REQUIRED Core Gui Widgets)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
file(GLOB SRCS *.cpp *.h)
|
||||
|
||||
add_executable(qt_app_server ${SRCS})
|
||||
|
||||
target_link_libraries(qt_app_server Qt5::Core Qt5::Gui Qt5::Widgets ${EXAMPLE_LIBS})
|
@ -0,0 +1,56 @@
|
||||
#include <thread>
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include "examples/qt_app_server/main_window.h"
|
||||
|
||||
#include "webcc/logger.h"
|
||||
#include "webcc/response_builder.h"
|
||||
#include "webcc/server.h"
|
||||
#include "webcc/view.h"
|
||||
|
||||
class ApiView : public webcc::View {
|
||||
public:
|
||||
explicit ApiView(Context* context) : context_(context) {
|
||||
}
|
||||
|
||||
webcc::ResponsePtr Handle(webcc::RequestPtr request) override {
|
||||
if (request->method() == "GET") {
|
||||
emit context_->SomeApiSignal("A GET request has been handled");
|
||||
return webcc::ResponseBuilder{}.OK().Body("Hello, World!")();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
private:
|
||||
Context* context_;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
QApplication app{ argc, argv };
|
||||
|
||||
WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
|
||||
|
||||
Context context;
|
||||
|
||||
// Create a server and bind view.
|
||||
webcc::Server server{ boost::asio::ip::tcp::v4(), 8000 };
|
||||
server.Route("/", std::make_shared<ApiView>(&context));
|
||||
|
||||
// Run the server in a thread to avoid blocking the GUI.
|
||||
std::thread server_thread{ [&server]() { server.Run(); } };
|
||||
|
||||
// Now show our Qt main window and execute the application loop.
|
||||
MainWindow main_window{ &context };
|
||||
main_window.resize(400, 300);
|
||||
main_window.showNormal();
|
||||
|
||||
int code = app.exec();
|
||||
|
||||
// Stop the server and wait for it to finish.
|
||||
server.Stop();
|
||||
server_thread.join();
|
||||
|
||||
return code;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
#include "examples/qt_app_server/main_window.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
MainWindow::MainWindow(Context* context, QWidget* parent)
|
||||
: QMainWindow(parent) {
|
||||
setWindowTitle("Qt App Server");
|
||||
|
||||
#if 1
|
||||
connect(context, &Context::SomeApiSignal, this, &MainWindow::OnSomeApiSignal);
|
||||
#else
|
||||
// NOTE: Seems not necessary to use QueuedConnection (because we are using
|
||||
// std::thread instead of QThread?).
|
||||
connect(context, &Context::SomeApiSignal, this, &MainWindow::OnSomeApiSignal,
|
||||
Qt::QueuedConnection);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::OnSomeApiSignal(const QString& text) {
|
||||
qDebug() << text;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
#ifndef MAIN_WINDOW_H_
|
||||
#define MAIN_WINDOW_H_
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
// Some global QObject with public signals for ApiView to inform the handling
|
||||
// of client requests.
|
||||
// "Context" is a bad name, you should change it.
|
||||
class Context : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Context(QObject* parent = nullptr) : QObject(parent) {
|
||||
}
|
||||
|
||||
// Public signals emitted from ApiView:
|
||||
signals:
|
||||
void SomeApiSignal(const QString& text);
|
||||
// Add other signals here...
|
||||
};
|
||||
|
||||
class MainWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(Context* context, QWidget* parent = nullptr);
|
||||
|
||||
private:
|
||||
// You should encapsulate the required information as the signal parameters.
|
||||
// I use QString just for demostrating how to transfer data from ApiView.
|
||||
void OnSomeApiSignal(const QString& text);
|
||||
};
|
||||
|
||||
#endif // MAIN_WINDOW_H_
|
Loading…
Reference in New Issue