I Wrote before but the details was not explained.
I explain step by step what I do;
Witty installation Guide Ubuntu
I did in order what ever said in this page.
sudo apt-get install gcc g++ libboost-all-dev cmake make
sudo apt-get install libssl-dev libfcgi-dev
sudo apt-get install libpq-dev libmysqlclient-dev firebird-dev
sudo apt-get install libpng12-dev libgraphicsmagick1-dev libhpdf-dev libpng12-dev libpango1.0-dev mesa-common-dev
sudo apt-get install asciidoc libqt4-dev
sudo apt-get install doxygen graphviz
wget -c http://kent.dl.sourceforge.net/sourceforge/witty/wt-3.3.4.tar.gz
tar xvxf wt-3.3.4.tar.gz
cd wt-3.3.4
mkdir build
cd build
cmake ..
make
make -C examples
and Test helloqt.wt test
./helloqt.wt --http-port 10000 --http-addr 0.0.0.0 --docroot .
Every things work fine
and then I changed someline for Qt events loop working
// Needed when using WQApplication with Qt eventloop = true
#include <QApplication>
Dictionary::Dictionary(const WEnvironment& env)
: WQApplication(env , true )
{
/*
* Note: do not create any Qt objects from here. Initialize your
* application from within the virtual create() method.
*/
}
.
.
.
int main(int argc, char **argv)
{
// Needed for Qt's eventloop threads to work
QApplication app(argc, argv);
return WRun(argc, argv, &createApplication);
}
still result is fine everything OK. eventloops( signal/slot working )
and I clean everything with
make clean
add line to cmakefiles.txt QtNetwork
.
.
.
IF(ENABLE_QT4)
FIND_PACKAGE(Qt4 REQUIRED QtCore QtGui QtNetwork)
IF(QT_FOUND)
INCLUDE(${QT_USE_FILE})
ENDIF(QT_FOUND)
ENDIF(ENABLE_QT4)
.
.
.
and also add to wtwithqt examples cmakelist.txt ${QT_QTNETWORK_LIBRARY}
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtNetwork )
SET(QT_USE_QTNETWORK true)
INCLUDE(${QT_USE_FILE})
to below
IF(COMMAND cmake_policy)
CMAKE_POLICY(SET CMP0003 NEW)
ENDIF(COMMAND cmake_policy)
SET(BUILD_WTWITHQT true)
IF (NOT MULTI_THREADED_BUILD)
SET(BUILD_WTWITHQT false)
ENDIF (NOT MULTI_THREADED_BUILD)
IF (NOT QT_FOUND)
SET(BUILD_WTWITHQT false)
ENDIF (NOT QT_FOUND)
IF (NOT BUILD_WTWITHQT)
MESSAGE(STATUS "** Not building wtwithqt example.")
MESSAGE(STATUS " wtwithqt example requires a Qt4 installation.")
ELSE (NOT BUILD_WTWITHQT)
MESSAGE("\n\n " + ${QT_QTCORE_LIBRARY} + " \n" + ${QT_QTGUI_LIBRARY} + "\n" + ${QT_QTNETWORK_LIBRARY} + "\n" + ${QT_LIBRARIES} + "\n\n" )
FIND_PACKAGE(Qt4 COMPONENTS QtCore QtGui QtNetwork )
SET(QT_USE_QTNETWORK true)
INCLUDE(${QT_USE_FILE})
SUBDIRS(lib)
ADD_DEFINITIONS(-DWT_NO_SLOT_MACROS)
QT4_GENERATE_MOC(${CMAKE_CURRENT_SOURCE_DIR}/QtObject.h
${CMAKE_CURRENT_BINARY_DIR}/moccedQtObject.C)
WT_ADD_EXAMPLE(helloqt.wt
hello.C
QtObject.C
${CMAKE_CURRENT_BINARY_DIR}/moccedQtObject.C
)
TARGET_LINK_LIBRARIES(helloqt.wt
wtwithqt
${QT_QTCORE_LIBRARY}
${QT_QTGUI_LIBRARY}
${QT_QTNETWORK_LIBRARY}
${QT_LIBRARIES}
)
#
# If you have Wt installed somehwere, you should use the
# installed Wt header files for your own Wt projects.
# e.g. INCLUDE_DIRECTORIES(/usr/local/wt/include)
# instead of the following:
#
INCLUDE_DIRECTORIES(
${WT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/lib
${QT_QTCORE_INCLUDE_DIR}
${QT_QTNETWORK_INCLUDE_DIR}
${QT_INCLUDE_DIR}
)
ENDIF (NOT BUILD_WTWITHQT)
and add to QTcpSocket to function below
QtObject.h
// This may look like C code, but it's really -- C++ --
#ifndef QTOBJECT_H_
#define QTOBJECT_H_
#include <QThread>
#include <QTcpSocket>
class Dictionary;
/*! \class QtObject
* \brief A simple Qt object with sample signal and slot.
*
* This simple object class demonstrates that the Qt signal/slot
* mechanism may be used alonglisde Wt's signal/slot mechanism.
*/
class QtObject : public QObject
{
Q_OBJECT;
public:
QtObject(Dictionary *wt_, QObject *parent = 0);
void passGreet(const QString&);
QTcpSocket* socket;
signals:
void greet(const QString&);
public slots:
void doGreet(const QString&);
void Connected();
private:
Dictionary *wt_;
};
#endif // QTOBJECT_H_
QtObject.C file
#include "HelloApplication.h"
#include "QtObject.h"
#include <QHostAddress>
QtObject::QtObject(Dictionary *wt, QObject *parent)
: QObject(parent),
wt_(wt)
{
socket = new QTcpSocket();
QHostAddress adr;
adr.setAddress("192.168.0.2");
socket->connectToHost(adr,17776);
QObject::connect(socket,SIGNAL(connected()),this,SLOT(Connected()));
}
void QtObject::passGreet(const QString& name)
{
emit greet(name);
}
void QtObject::doGreet(const QString& name)
{
wt_->doGreet(name);
}
void QtObject::Connected(){
std::cout << "\n\nCONNNECTED\n\n";
emit greet(QString("QString"));
}
From this time
cml#cml-All-Series:~/wt-3.3.4/build$ make clean
cml#cml-All-Series:~/wt-3.3.4/build$ cmake ..
cml#cml-All-Series:~/wt-3.3.4/build$ make -j8
cml#cml-All-Series:~/wt-3.3.4/build$ make -C examples/wtwithqt
cml#cml-All-Series:~/wt-3.3.4/build/examples/wtwithqt$ ./helloqt.wt charts.wt --http-port 10000 --http-addr 0.0.0.0 --docroot .
[2015-Aug-22 10:34:04.692004] 3116 - [info] "WServer/wthttp: initializing built-in wthttpd"
[2015-Aug-22 10:34:04.693292] 3116 - [info] "wthttp: started server: http://0.0.0.0:10000"
when click on browser 0.0.0.0:10000
page is incoming and
socket emitting Connected() signals and Connected() SLOT Work
print screen to std::cout << "\n\nCONNNECTED\n\n";
and application
crashed. Segmentation fault and Core Dumped
I can not find what is wrong?
I Debug Qt Creator
WWebWidget.C file stopped there
bool WWebWidget::canOptimizeUpdates()
{
-> return WApplication::instance()->session()->renderer().preLearning();
}
Qt Creator Debugger says ->
The inferior stopped because it received a signal from the Operating System.
Signal name :
SIGSEGV
Signal meaning :
Segmentation fault
There talking about the solution
in my code I delete WText object after there is no fail seg fault...
this is not solution for me but I can use it
Wt::WApplication* app = Wt::WApplication::instance();
app->enableUpdates(true);
Wt::WApplication::UpdateLock uilock(app);
if( uilock ){
button->setText("Test"); //Here is Editable Widget
app->trigerUpdate();
app->enableUpdates(false);
}
For a big work you lock application and
control if locked change any thing
ServerPUSH.c
Related
I was able to build the CuteLogger library on macOS with
git clone git#github.com:dept2/CuteLogger.git
debug
mkdir x64d
cd x64d
cmake .. -DCMAKE_TOOLCHAIN_FILE=~/vcpk/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Debug
cmake --build . --config Debug
release
mkdir x64
cd x64
cmake .. -DCMAKE_TOOLCHAIN_FILE=~/vcpk/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
That led to
x64d/libCuteLogger.dylib ~40M
x64/libCuteLogger.dylib ~33M
which I included in another project, the one which comes in the cutelogger README
#include <QCoreApplication>
#include <Logger.h>
#include <ConsoleAppender.h>
int main(int argc, char* argv[])
{
QCoreApplication app(argc, argv);
ConsoleAppender* consoleAppender = new ConsoleAppender;
consoleAppender->setFormat("[%{type:-7}] <%{Function}> %{message}\n");
cuteLogger->registerAppender(consoleAppender);
LOG_INFO("Starting the application");
int result = app.exec();
if (result)
LOG_WARNING() << "Something went wrong." << "Result code is" << result;
return result;
}
And I build this with qmake
QT -= gui
CONFIG(debug, debug|release) {
d = d
} else {
}
INCLUDEPATH += ../include
LIBS += -L$$PWD/../x64$$d -lCuteLogger
SOURCES += \
main.cpp
mySetOfExtraFiles.files += $$PWD/../x64$$d/libCuteLogger.dylib
mySetOfExtraFiles.path = Contents/Frameworks
QMAKE_BUNDLE_DATA += mySetOfExtraFiles
But running it gives
objc[23564]: Class QMacAutoReleasePoolTracker is implemented in both /Users/user/QtProjects/Cutelogger/x64d/libCuteLogger.dylib (0x1122ae5a0)
and /Users/user/QtProjects/CuteLoggerProject/_x64d/CuteLoggeProject.app/Contents/MacOS/CuteLoggeProject (0x10f0ec0f0). One of the two will be used. Which one is undefined.
objc[23564]: Class QT_ROOT_LEVEL_POOL__THESE_OBJECTS_WILL_BE_RELEASED_WHEN_QAPP_GOES_OUT_OF_SCOPE is implemented in both /Users/user/QtProjects/Cutelogger/x64d/libCuteLogger.dylib (0x1122ae618)
and /Users/user/QtProjects/CuteLoggerProject/_x64d/CuteLoggeProject.app/Contents/MacOS/CuteLoggeProject (0x10f0ec168). One of the two will be used. Which one is undefined.
objc[23564]: Class KeyValueObserver is implemented in both /Users/user/QtProjects/Cutelogger/x64d/libCuteLogger.dylib (0x1122ae640)
and /Users/user/QtProjects/CuteLoggerProject/_x64d/CuteLoggeProject.app/Contents/MacOS/CuteLoggeProject (0x10f0ec190). One of the two will be used. Which one is undefined.
objc[23564]: Class RunLoopModeTracker is implemented in both /Users/user/QtProjects/Cutelogger/x64d/libCuteLogger.dylib (0x1122ae690)
and /Users/user/QtProjects/CuteLoggerProject/_x64d/CuteLoggeProject.app/Contents/MacOS/CuteLoggeProject (0x10f0ec1e0). One of the two will be used. Which one is undefined.
So, what is that Class ... is implemented in both ...?
I am trying to run a simple example to set up EGL context in a docker container. However, I keep getting this error message :
Detected 0 devices
terminate called after throwing an instance of 'std::runtime_error'
what(): EGL error 0x300c at eglGetDisplay
Aborted
Basically, eglQueryDevicesEXT returns 0, and eglGetPlatformDisplayEXT returns error code 0x300c (EGL_BAD_PARAMETER) .
I have tried on :
Ubuntu 16.04 docker on a Macbook Pro
Ubuntu 16.04 docker on a Ubuntu 16.04 server with Nvidia GPU
On these docker environments, I installed openGL and ELG using apt-get install libgl1-mesa-dev and apt-get install libegl1-mesa-dev. CMake can find the components GL::GL and EGL::EGL.
I have tried link to libEGL.so both manually and using find_package in CMake.
This is driving me crazy! I can't figure out why EGL can't detect devices? How can I resolve this error?
Here is my full code. I have also tried EGLDisplay eglDpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); which gives me the same error. Thanks!
#include <EGL/egl.h>
#include <EGL/eglext.h>
void assertEGLError(const std::string& msg) {
EGLint error = eglGetError();
if (error != EGL_SUCCESS) {
std::stringstream s;
s << "EGL error 0x" << std::hex << error << " at " << msg;
throw std::runtime_error(s.str());
}
}
int main(int argc, char *argv[])
{
// 1. Initialize EGL
// EGLDisplay eglDpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
int deviceID = 0; // TODO hardcode
EGLDisplay eglDpy;
EGLConfig config;
EGLContext context;
EGLint num_config;
static const int MAX_DEVICES = 16;
EGLDeviceEXT eglDevs[MAX_DEVICES];
EGLint numDevices;
PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT =
(PFNEGLQUERYDEVICESEXTPROC)eglGetProcAddress("eglQueryDevicesEXT");
eglQueryDevicesEXT(MAX_DEVICES, eglDevs, &numDevices);
printf("Detected %d devices\n", numDevices);
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =
(PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
// Choose device by deviceID
eglDpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, eglDevs[deviceID], nullptr);
assertEGLError("eglGetDisplay");
return 0;
}
OMG I finally solved this problem. Turned out I was linking to the wrong library on the server.
I found the answer in this post: https://forums.developer.nvidia.com/t/problem-with-opengl-visualization-without-an-x-server/73204/15
The key is to link to the libraries in /usr/lib/nvidia-410/, not the system default /usr/local/lib/x86_64-linux-gnu/libEGL.so
The new CMake that works:
target_link_libraries(sandbox PRIVATE /usr/lib/nvidia-410/libEGL.so)
target_link_libraries(sandbox PRIVATE /usr/lib/nvidia-410/libGLX.so)
target_link_libraries(sandbox PRIVATE /usr/lib/nvidia-410/libOpenGL.so)
Previously I used CMake's findOpenGL to search for link libraries, which does not work
find_package(OpenGL REQUIRED COMPONENTS OpenGL EGL GLX)
include_directories(${OPENGL_INCLUDE_DIRS})
if(OPENGL_FOUND)
message("Found OpenGL in the current environment!")
else()
message("Error: No OpenGL found.")
endif()
message("OpenGL include dirs" )
message("${OPENGL_INCLUDE_DIR}")
message("EGL include dirs" )
message("${OPENGL_EGL_INCLUDE_DIRS}")
if (OpenGL_EGL_FOUND)
message("EGL Found!")
else()
message("EGL Not Found!")
endif()
message(${OPENGL_egl_LIBRARY})
message(${OPENGL_glx_LIBRARY})
message(${OPENGL_opengl_LIBRARY}
Note again this does not work !!
/usr/local/lib/x86_64-linux-gnu/libEGL.so
/usr/local/lib/x86_64-linux-gnu/libGLX.so
/usr/local/lib/x86_64-linux-gnu/libOpenGL.so
I've been using PyQt for years now and had to recode a project in C++ using CLion. I have managed (after awhile) to get the code building on my MacBookPro, but when I move the project to Windows 10, all hell broke loose! I've reloaded mingw with the x86 version and gotten everything to work except MOC and AUTOUIC. The only lines I changed in the CMakeLists.txt file between Oses were the ones that pointed to the Qt install. As I said, I'm new to all this in C++ and may have some 'mistakes' in my makefile, but it works on OSX but not in Windows!
I am able to compile ui and resources files manually and get the build to compile, but I don't know how to resolve this issue.
Any help and guidance would be greatly appreciated!
====================[ Build | crapsStarter | Debug ]============================
C:\Users\a.fireheart.CLion2019.3\system\cygwin_cmake\bin\cmake.exe
--build /cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/cmake-build-debug
--target crapsStarter -- -j 6 [ 14%] Automatic MOC for target crapsStarter
AutoMoc subprocess error
------------------------ The moc process failed to compile "/cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/craps.h"
into
"/cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/cmake-build-debug/crapsStarter_autogen/EWIEGA46WW/moc_craps.cpp".
Command
------- C:/Qt/5.14.1/winrt_x64_msvc2017/bin/moc.exe -I/cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/cmake-build-debug
-I/cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter -I/cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/cmake-build-debug/crapsStarter_autogen/include
-IC:/Qt/5.14.1/winrt_x64_msvc2017/include -IC:/Qt/5.14.1/winrt_x64_msvc2017/include/QtCore -IC:/Qt/5.14.1/winrt_x64_msvc2017/./mkspecs/winrt-x64-msvc2017 -IC:/Qt/5.14.1/winrt_x64_msvc2017/include/QtGui -IC:/Qt/5.14.1/winrt_x64_msvc2017/include/QtANGLE -IC:/Qt/5.14.1/winrt_x64_msvc2017/include/QtWidgets -I/usr/lib/gcc/x86_64-pc-cygwin/9.2.0/include/c++ -I/usr/lib/gcc/x86_64-pc-cygwin/9.2.0/include/c++/x86_64-pc-cygwin -I/usr/lib/gcc/x86_64-pc-cygwin/9.2.0/include/c++/backward -I/usr/lib/gcc/x86_64-pc-cygwin/9.2.0/include -I/usr/include -I/usr/include/w32api -DQT_CORE_LIB -DQT_GUI_LIB -DQT_WIDGETS_LIB --include /cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/cmake-build-debug/crapsStarter_autogen/moc_predefs.h
-o /cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/cmake-build-debug/crapsStarter_autogen/EWIEGA46WW/moc_craps.cpp
/cygdrive/c/Users/a.fireheart/CLionProjects/crapsStarter/craps.h
Output
make[3]: * [CMakeFiles/crapsStarter_autogen.dir/build.make:58:
CMakeFiles/crapsStarter_autogen] Error 1 make[2]:
[CMakeFiles/Makefile2:104: CMakeFiles/crapsStarter_autogen.dir/all]
Error 2 make[1]: [CMakeFiles/Makefile2:84:
CMakeFiles/crapsStarter.dir/rule] Error 2 make: * [Makefile:118:
crapsStarter] Error 2
***************** My CMakeLists.txt file content *******************************
cmake_minimum_required(VERSION 3.15)
project(crapsStarter)
set(CMAKE_CXX_STANDARD 17)
#set(RESOURCES crapsResources.qrc)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
#set(CMAKE_AUTOUIC ON)
include_directories(cmake-build-debug/crapsStarter_autogen/include)
# Tell cmake where Qt is located
set(Qt5_DIR "C:/Qt/5.14.1/winrt_x64_msvc2017/lib/cmake/Qt5")
set(QT_INCLUDES "C:/Qt/5.14.1/winrt_x64_msvc2017/include")
MESSAGE("QT_INCLUDES: ${QT_INCLUDES}")
# Include a library search using find_package()
# via REQUIRED, specify that libraries are required
set(Qt5 NEED)
find_package(Qt5 COMPONENTS Core Gui Widgets REQUIRED)
set(SOURCE_FILES craps.cpp die.cpp crapsGame.cpp crapsResources.cpp)
add_executable(crapsStarter ${SOURCE_FILES})
# specify which libraries to connect
target_link_libraries(${PROJECT_NAME} Qt5::Core)
target_link_libraries(${PROJECT_NAME} Qt5::Gui)
target_link_libraries(${PROJECT_NAME} Qt5::Widgets)
craps.h
//
// Created by Arana Fireheart on 2/2/20.
//
#ifndef CRAPSSTARTER_CRAPS_H
#define CRAPSSTARTER_CRAPS_H
#include "ui_CrapsMainWindow.h"
#include "die.h"
#include <QMainWindow>
class CrapsMainWindow : public QMainWindow, private Ui::CrapsMainWindow {
Q_OBJECT
public:
CrapsMainWindow(QMainWindow *parent = nullptr);
void printStringRep();
void updateUI();
private:
Die die1, die2;
bool firstRoll = true;
int winsCount = 0;
public Q_SLOTS:
void rollButtonClickedHandler();
};
#include "moc_craps.cpp"
#endif //CRAPSSTARTER_CRAPS_H
craps.cpp
#include <iostream>
#include <stdio.h>
//#include <QApplication>
//#include <QWidget>
//#include <QGridLayout>
//#include <QPushButton>
//#include <QLabel>
//#include <QPixmap>
#include "die.h"
#include "craps.h"
#include "ui_CrapsMainWindow.h"
CrapsMainWindow :: CrapsMainWindow(QMainWindow *parent) {
// Build a GUI window with two dice.
setupUi(this);
Die die1, die2;
bool firstRoll = true;
int winsCount = 0;
QObject::connect(rollButton, SIGNAL(clicked()), this, SLOT(rollButtonClickedHandler()));
}
void CrapsMainWindow::printStringRep() {
// String representation for Craps.
char buffer[25];
int length = sprintf(buffer, "Die1: %i\nDie2: %i\n", die1.getValue(), die2.getValue());
printf("%s", buffer);
}
void CrapsMainWindow::updateUI() {
// printf("Inside updateUI()\n");
std::string die1ImageName = ":/dieImages/" + std::to_string(die1.getValue());
std::string die2ImageName = ":/dieImages/" + std::to_string(die2.getValue());
die1UI->setPixmap(QPixmap(QString::fromStdString(die1ImageName)));
die2UI->setPixmap(QPixmap(QString::fromStdString(die2ImageName)));
currentBankValueUI->setText(QString::fromStdString("100"));
}
// Player asked for another roll of the dice.
void CrapsMainWindow::rollButtonClickedHandler() {
//void Craps::rollButtonClickedHandler() {
printf("Roll button clicked\n");
die1.roll();
die2.roll();
printStringRep();
updateUI();
}
I'm working on a very basic C++ application using Qt5.6 with CMake. Git Repo Here.
My problem? My main.cpp can #include Qt classes like <QtCore/QObject>, but my defined classes cannot.
error: QtCore/QObject: No such file or directory
I have downloaded the latest version of Qt with Qt Creator here.
Could this be an improperly set up Qt environment? I don't understand how main.cpp can access Qt but my defined classes cannot.
CMakeLists.txt
cmake_minimum_required(VERSION 2.8.11)
project(testproject)
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)
############ OpenCV PACKAGE #########
set(BUILD_SHARED_LIBS ON)
set(OpenCV_FIND_QUIETLY FALSE)
find_package( OpenCV REQUIRED)
include_directories( ${OpenCV_INCLUDE_DIRS} )
# Find the QtWidgets library
find_package(Qt5Widgets)
qt5_wrap_cpp(tcp_hdr_moc ${PROJECT_SOURCE_DIR}/TcpServer.h)
# Tell CMake to create the helloworld executable
add_executable(helloworld WIN32 main.cpp
TcpServer.h TcpServer.cpp
)
# Use the Widgets module from Qt 5.
target_link_libraries(helloworld Qt5::Widgets
${OpenCV_LIBS}
${PROJECT_SOURCE_DIR}/TcpServer.cpp
${PROJECT_SOURCE_DIR}/TcpServer.h
)
main.cpp
#include <iostream>
#include <QtWidgets/QApplication>
#include <QtCore/QObject>
//#include "TcpServer.h"
using namespace std;
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QString test = "Hello";
QObject test2;
int i = 0;
// TcpServer server;
}
User defined class: TcpServer.cpp
#include "TcpServer.h"
#include <QtNetwork/QTcpSocket>
#include <QtCore/QByteArray>
#include <QtCore/QtDebug>
#include <QtCore/QString>
#include <opencv2/core.hpp>
#include <opencv2/opencv.hpp>
TcpServer::TcpServer(QObject *parent) :
QObject(parent)
{
server = new QTcpServer(this);
// whenever a user connects, it will emit signal
connect(server, SIGNAL(newConnection()),
this, SLOT(newConnection()));
if (!server->listen(QHostAddress::Any, 9999))
qDebug() << "Server could not start";
else
qDebug() << "Server started!";
vCapture = new VideoCapture(0);
}
void TcpServer::newConnection()
{
QTcpSocket *socket = server->nextPendingConnection();
QByteArray ContentType = ("HTTP/1.0 200 OK\r\n" \
"Cache-Control: no-cache\r\n" \
"Cache-Control: private\r\n" \
"Content-Type: multipart/x-mixed-replace;boundary=--boundary\r\n");
socket->write(ContentType);
std::vector<uchar> buff;
Mat img; //OpenCV Material
while (1) {
// Image to Byte Array via OPENCV Method
buff.clear();buff.empty();
vCapture->read(img); //Read from webcam
//TODO set the compression parameters.
imencode(".jpg", img, buff);
std::string content(buff.begin(), buff.end());
QByteArray CurrentImg(QByteArray::fromStdString(content));
QByteArray BoundaryString = ("--boundary\r\n" \
"Content-Type: image/jpeg\r\n" \
"Content-Length: ");
BoundaryString.append(QString::number(CurrentImg.length()));
BoundaryString.append("\r\n\r\n");
socket->write(BoundaryString);
socket->write(CurrentImg); // Write The Encoded Image
socket->flush();
}
}
User Defined Class Header which throws the error: TcpServer.h
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include <QtCore/QObject>
#include <QtNetwork/QTcpServer>
#include "opencv2/videoio.hpp"
using namespace cv;
class TcpServer : public QObject
{
Q_OBJECT
public:
explicit TcpServer(QObject *parent = 0);
void newConnection();
private:
QTcpServer* server;
VideoCapture* vCapture;
};
#endif
For reference I am working on these two related stack overflow questions.
How to Create a HTTP MJPEG Streaming Server With QTcp-Server Sockets?
Error while using QTcpSocket.
Add find_package(Qt5Core) in addition to find_package(Qt5Widgets) and add the following lines:
include_directories(${Qt5Widgets_INCLUDE_DIRS})
include_directories(${Qt5Core_INCLUDE_DIRS})
And do not forget to add Qt5::Core to the target_link_libraries.
BTW, I see you are using QtNetwork; you will have to make the same steps for that module too. And for every other module you will use.
I have programmed Qt a couple of times already and I really like the signals and slots feature. But now, I guess I'm having a problem when a signal is emitted from one thread, the corresponding slot from another thread is not fired. The connection was made in the main program.
This is also my first time to use Qt for ROS which uses CMake. The signal fired by the QThread triggered their corresponding slots but the emitted signal of my class UserInput did not trigger the slot in tflistener where it supposed to. I have tried everything I can. Any help? The code is provided below.
Main.cpp
#include <QCoreApplication>
#include <QThread>
#include "userinput.h"
#include "tfcompleter.h"
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
QThread *thread1 = new QThread();
QThread *thread2 = new QThread();
UserInput *input1 = new UserInput();
TfCompleter *completer = new TfCompleter();
QObject::connect(input1, SIGNAL(togglePause2()), completer, SLOT(toggle()));
QObject::connect(thread1, SIGNAL(started()), completer, SLOT(startCounting()));
QObject::connect(thread2, SIGNAL(started()), input1, SLOT(start()));
completer->moveToThread(thread1);
input1->moveToThread(thread2);
thread1->start();
thread2->start();
app.exec();
return 0;
}
What I want to do is.. There are two seperate threads. One thread is for the user input. When the user enters [space], the thread emits a signal to toggle the boolean member field of the other thread. The other thread 's task is to just continue its process if the user wants it to run, otherwise, the user does not want it to run. I wanted to grant the user to toggle the processing anytime that he wants, that's why I decided to bring them into seperate threads.
The following codes are the tflistener and userinput.
tfcompleter.h
#ifndef TFCOMPLETER_H
#define TFCOMPLETER_H
#include <QObject>
#include <QtCore>
class TfCompleter : public QObject
{
Q_OBJECT
private:
bool isCount;
public Q_SLOTS:
void toggle();
void startCounting();
};
#endif
tflistener.cpp
#include "tfcompleter.h"
#include <iostream>
void TfCompleter::startCounting()
{
static uint i = 0;
while(true)
{
if(isCount)
std::cout << i++ << std::endl;
}
}
void TfCompleter::toggle()
{
// isCount = ~isCount;
std::cout << "isCount " << std::endl;
}
UserInput.h
#ifndef USERINPUT_H
#define USERINPUT_H
#include <QObject>
#include <QtCore>
class UserInput : public QObject
{
Q_OBJECT
public Q_SLOTS:
void start(); // Waits for the keypress from the user and emits the corresponding signal.
public:
Q_SIGNALS:
void togglePause2();
};
#endif
UserInput.cpp
#include "userinput.h"
#include <iostream>
#include <cstdio>
// Implementation of getch
#include <termios.h>
#include <unistd.h>
/* reads from keypress, doesn't echo */
int getch(void)
{
struct termios oldattr, newattr;
int ch;
tcgetattr( STDIN_FILENO, &oldattr );
newattr = oldattr;
newattr.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
return ch;
}
void UserInput::start()
{
char c = 0;
while (true)
{
c = getch();
if (c == ' ')
{
Q_EMIT togglePause2();
std::cout << "SPACE" << std::endl;
}
c = 0;
}
}
Here is the CMakeLists.txt. I just placed it here also since I don't know maybe the CMake has also a factor here.
CMakeLists.txt
##############################################################################
# CMake
##############################################################################
cmake_minimum_required(VERSION 2.4.6)
##############################################################################
# Ros Initialisation
##############################################################################
include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake)
rosbuild_init()
set(CMAKE_AUTOMOC ON)
#set the default path for built executables to the "bin" directory
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
#set the default path for built libraries to the "lib" directory
set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
# Set the build type. Options are:
# Coverage : w/ debug symbols, w/o optimization, w/ code-coverage
# Debug : w/ debug symbols, w/o optimization
# Release : w/o debug symbols, w/ optimization
# RelWithDebInfo : w/ debug symbols, w/ optimization
# MinSizeRel : w/o debug symbols, w/ optimization, stripped binaries
#set(ROS_BUILD_TYPE Debug)
##############################################################################
# Qt Environment
##############################################################################
# Could use this, but qt-ros would need an updated deb, instead we'll move to catkin
# rosbuild_include(qt_build qt-ros)
rosbuild_find_ros_package(qt_build)
include(${qt_build_PACKAGE_PATH}/qt-ros.cmake)
rosbuild_prepare_qt4(QtCore) # Add the appropriate components to the component list here
ADD_DEFINITIONS(-DQT_NO_KEYWORDS)
##############################################################################
# Sections
##############################################################################
#file(GLOB QT_FORMS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ui/*.ui)
#file(GLOB QT_RESOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} resources/*.qrc)
file(GLOB_RECURSE QT_MOC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} FOLLOW_SYMLINKS include/rgbdslam_client/*.hpp)
#QT4_ADD_RESOURCES(QT_RESOURCES_CPP ${QT_RESOURCES})
#QT4_WRAP_UI(QT_FORMS_HPP ${QT_FORMS})
QT4_WRAP_CPP(QT_MOC_HPP ${QT_MOC})
##############################################################################
# Sources
##############################################################################
file(GLOB_RECURSE QT_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} FOLLOW_SYMLINKS src/*.cpp)
##############################################################################
# Binaries
##############################################################################
rosbuild_add_executable(rgbdslam_client ${QT_SOURCES} ${QT_MOC_HPP})
#rosbuild_add_executable(rgbdslam_client ${QT_SOURCES} ${QT_RESOURCES_CPP} ${QT_FORMS_HPP} ${QT_MOC_HPP})
target_link_libraries(rgbdslam_client ${QT_LIBRARIES})
It is hard to find bug from your posted code. I just want to point out one issue:
You are first making the connection and then moving the objects to new threads. Since they were created in same thread they had same Thread Affinity. So by default the connection type will be direct, which means, the slot will be executed from the same thread from which signal is emitted.
But after moving to new threads, thread affinity for both objects gets changed. Although you did not say how you could find out it is not working, I recommend to look at this matter. If you expect the slot to be executed in different thread, and tested that way, then you may not get desired output and think it is not working.
When signal and slot are meant to be executed in different thread, it is better to connect them after moving the corresponding objects to new threads. Qt::AutoConnection will by default use Qt::QueuedConnection when objects are in different thread.