I have a lot of existing code using Qt, and more specifically Qt signals and slots to time specific actions.
Now I need to use this code within a new application which is not a Qt application (and cannot be - I am writing a plugin to visual studio). Anyway - how can I get the existing code to actually intercept the signals and activate the relevant slots?
Do I need to somehow create a dummy Qt application? If so - how do I cause it to process the signals without becoming a blocking loop to the rest of my code?
It seems that if you write something like this, the "Test" message is still printed even though there is no event loop, so this could be a clue:
#include <QObject>
#include <QCoreApplication>
#include <QDebug>
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent) : QObject(parent) {}
void testMethod() { emit testSignal(); }
signals:
void testSignal();
public slots:
void testSlot() { qDebug() << "Test"; }
};
#include "main.moc"
int main(int argc, char **argv)
{
// QCoreApplication coreApplication(argc, argv);
MyClass myObject(0);
QObject::connect(&myObject, SIGNAL(testSignal()), &myObject, SLOT(testSlot()));
myObject.testMethod();
// return coreApplication.exec();
return 0;
}
This way, you would still need Qt, but you could avoid having a "blocking" event loop. However, it might be simpler to just rearrange the code from the signal-slot layering to direct calls, depending on how many direct calls you would need to do for a signal emitted.
This is a common problem when using ASIO and Qt together. The solution I have found is to make a Broker object, and run the Qt and ASIO loops on their own threads. The Broker is the target for emit calls to the ASIO message queue, and the emitter to the Qt message queue. Take care of the syncronisation/data copying in the Broker.
Related
I was wondering how I can run a function when closing the terminal (I'm on Linux) of my Qt Console Application. I have a 'static' class which holds all the variables I need (I know I can use singleton but I like this way better) and it has a function called destroy, this will delete all pointers).
So this is my .cpp of the 'static' class:
#include "engine.h"
logging* engine::m_logging;
tcp_listener* engine::m_tcp_listener;
void engine::initialize()
{
engine::m_logging = new logging();
engine::m_logging->write_line("Initializing Fullmoon Messenger server...");
engine::m_tcp_listener = new tcp_listener();
engine::m_tcp_listener->start("127.0.0.1", 30000);
}
void engine::destroy()
{
delete engine::m_logging;
}
logging* engine::get_logging()
{
return engine::m_logging;
}
And this is my main.cpp:
#include <QCoreApplication>
#include "engine.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
engine::initialize();
return a.exec();
}
How can I call engine::destroy when closing the application? I assume there's a signal for it.
You need to handle the POSIX signal SIGHUP for this.
(Note: POSIX signals are something completely different than Qt signals, so they're not handled with "slots". Don't confuse them.)
Note that your options for what to do in a POSIX signal handler are very limited. The man page signal(7) lists the functions which are safe to be called. In the comments to this answer, Kuba Ober pointed out that you should to stick to the official documentation for handling POSIX signals in Qt applications. But since the process as explained in the documentation is quite complicated, I wrapped it in a reusable class PosixSignalProxy, converting POSIX signals to Qt signals.
If you use this proxy class you just have to write:
PosixSignalProxy<SIGHUP> sighupProxy;
QObject::connect(&sighupProxy, &PosixSignalProxyBase::receivedSignal, []{
engine::destroy();
});
The class is found at the bottom of this post.
Note that only one instance of a PosixSignalProxy can be created for each POSIX signal type. If you need to do multiple things when receiving a signal, you can however connect to the Qt signal multiple times.
Also, you might be interested in similar signals for different external reasons for quitting your application, such as killing it or hitting Ctrl+C in the terminal window.
SIGHUP (as in the example above): when the terminal window was closed (and the parent process was destroyed)
SIGINT: when the user hits Ctrl+C - Note that when you handle this signal you need to quit at the end of the handler since your process is responsible of finally quitting itself. You overwrite this default behavior and have the option not to only cleanup stuff but also to ignore the user's wish to quit the application.
SIGTERM: when the process is killed with e.g. kill (not to be confused with SIGKILL which is a more aggressive way to kill a process; you can't handle that one)
Here is the class definition:
posixsignalproxy.h
#ifndef POSIXSIGNALPROXY_H
#define POSIXSIGNALPROXY_H
#include <QObject>
class QSocketNotifier;
typedef void (*PosixSignalHandlerType) (int);
// Helper base class (no template) - Do not use this class directly.
class PosixSignalProxyBase : public QObject
{
Q_OBJECT
public:
PosixSignalProxyBase(
QObject *parent,
int (&sockets)[2],
int posixSignalNumber,
PosixSignalHandlerType posixSignalHandler,
int posixSignalFlags);
~PosixSignalProxyBase();
signals:
/**
* Qt signal which is emitted right after receiving and handling the POSIX
* signal. In the Qt signal handler (slot) you are allowed to do anything.
*/
void receivedSignal();
protected:
static void staticSignalHandler(int (&sockets)[2]);
private slots:
void handleSignal();
private:
int (&sockets)[2];
QSocketNotifier *notifier;
};
// Actual proxy class, defining its own static proxy signal handler function and sockets.
template <int signum>
class PosixSignalProxy : public PosixSignalProxyBase
{
public:
PosixSignalProxy(QObject *parent = nullptr, int posixSignalFlags = 0) :
PosixSignalProxyBase(parent, mySockets, signum, &posixSignalHandler, posixSignalFlags)
{}
PosixSignalProxy(int posixSignalFlags) :
PosixSignalProxy(nullptr, posixSignalFlags)
{}
static void posixSignalHandler(int) {
PosixSignalProxyBase::staticSignalHandler(mySockets);
}
private:
static int mySockets[2];
};
template <int signum>
int PosixSignalProxy<signum>::mySockets[2];
#endif // POSIXSIGNALPROXY_H
posixsignalproxy.cpp
#include "posixsignalproxy.h"
#include <QSocketNotifier>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <signal.h>
PosixSignalProxyBase::PosixSignalProxyBase(QObject *parent, int (&sockets)[2], int posixSignalNumber, PosixSignalHandlerType posixSignalHandler, int posixSignalFlags) :
QObject(parent),
sockets(sockets)
{
if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sockets))
qFatal("PosixSignalProxy: Couldn't create socket pair");
notifier = new QSocketNotifier(sockets[1], QSocketNotifier::Read, this);
connect(notifier, SIGNAL(activated(int)), this, SLOT(handleSignal()));
struct sigaction sa;
sa.sa_handler = posixSignalHandler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = posixSignalFlags;
if (sigaction(posixSignalNumber, &sa, 0) > 0)
qFatal("PosixSignalProxy: Couldn't register POSIX signal handler");
}
PosixSignalProxyBase::~PosixSignalProxyBase()
{
delete notifier;
}
void PosixSignalProxyBase::staticSignalHandler(int (&sockets)[2])
{
char tmp = 1;
::write(sockets[0], &tmp, sizeof(tmp));
}
void PosixSignalProxyBase::handleSignal()
{
notifier->setEnabled(false);
char tmp;
::read(sockets[1], &tmp, sizeof(tmp));
// Here, we're allowed to do Qt stuff.
emit receivedSignal();
notifier->setEnabled(true);
}
You're looking for QCoreApplication::aboutToQuit if you want to use a signal.
Better idea IMO is for engine not to have static functions but to manage its resources properly in its destructor. You can make it a singleton if you want.
I try to create something like a window pool. You can use these windows everywhere in your program to display graphics and plot diagrams etc. The widgets working well but the main problem at the moment is the frustrated tries, to create the pool. One non QObject-Object should represent a QMainWindow to cut the bindings to Qt.
I cannot create a widget -> I tried invokeMethode, connect and QTimer but nothing works. Sometimes the methods donĀ“t get called or I am not in the gui thread... Any idea?
Edit 2 - new version:
header:
#pragma once
#include <QMainWindow>
#include <QTimer>
class MyWindow : QObject
{
Q_OBJECT
public:
MyWindow();
};
class QWindowPool : public QObject
{
Q_OBJECT
public:
QWindowPool();
public slots:
void createWindow();
};
class QWindow : public QMainWindow
{
Q_OBJECT
};
cpp:
#include
#include <QApplication>
#include <QTimer>
#include <QtConcurrent/qtconcurrentrun.h>
#include <iostream>
#include <future>
static QWindowPool *pool = new QWindowPool();
QWindowPool::QWindowPool() {
// check if app is running
if (!QApplication::instance()) {
bool appOnline = false;
QtConcurrent::run([&appOnline](){
int c = 0;
new QApplication(c, NULL);
appOnline = true;
qApp->exec();
});
while (!appOnline) {}
}
moveToThread(QApplication::instance()->thread());
}
void QWindowPool::createWindow() {
printf("window created\n");
new QWindow();
}
MyWindow::MyWindow() {
QTimer::singleShot(0, pool, SLOT(createWindow()));
}
int main()
{
MyWindow mw;
std::thread t1([](){
MyWindow mw;
std::thread t2([](){
MyWindow mw;
});
t2.join();
});
t1.join();
std::cin.ignore();
return 0;
}
Now the code do what is should. I can create widgets in different threads. But there are two scenarios, where I would stack at:
Someone (anyone who would like to use this library) creates before me QApplication and never calls qApp->exec
Someone want to create an own UI with Widget but does not work in my qt::concurrent gui thread. He would probably not get along with this.
What I want is in the final application:
The user should get the possibility to write anywhere in his code and in any thread:
MyWindow mw(dataToDisplay)
and the window should be created and showed to him.
Qt will only let you create widgets from the main GUI thread, this is explicitly mentioned in the docs (emphasis mine):
As mentioned, each program has one thread when it is started. This
thread is called the "main thread" (also known as the "GUI thread" in
Qt applications). The Qt GUI must run in this thread. All widgets and
several related classes, for example QPixmap, don't work in secondary
threads. A secondary thread is commonly referred to as a "worker
thread" because it is used to offload processing work from the main
thread.
In my project, I have made a GUI program that will occasionally send commands to a cli program. I do it like this:
system("folder\\program.exe -d folder\\inputFile.dat folder\\outputPath");
Obviously without those names but you get the idea. This works fine, except when my GUI program sends these commands, a command prompt window opens and does whatever the cli program is supposed to do. It looks very bad and unclean.
Is there any way I could "hide" the cli program window but still have it silently do what it needs to do?
Thanks for your time :)
EDIT: I tried olive's technique which was to use QDesktopServices and QUrl to call the program:
QDesktopServices::openUrl(QUrl("folder\\program.exe -d folder\\inputFile.dat folder\\outputPath"));
The console window isn't showing up, however, the program wasn't called at all. Are there any changes that need to be made to the path when using olive's technique rather than my original system() command?
I cannot determine whether you need a cross platform solution or not. On windows execution using start generally hides the command window.
system("start program.exe -d inputFile.dat outputPath");
I solved this problem like so:
QProcess::execute("start program.exe -d inputFile.dat outputPath");
The problem is, I can only do this once. Everytime I try to call it again, it will not work. The thing that makes this hidden is "start." Taking it out allows the console to be seen, it's just blank.
It seems like I need a way to "end" the program or whatever before running it again. (I say or whatever because I have no clue what/why adding "start" to the path does)
QDesktopServices::openUrl() is usually used if you wish to open a document (eg PDF document, web page) in a viewing or editing program and you're not sure which programs have been installed. This function lets the operating system choose for you from the list of default programs with respect to the file types.
Although you can also use the function to open executable files (eg console programs), an alternative to that would be using QProcess. If you don't need to communicate with the console program or wait for it to complete, you can just launch it in a fire-and-forget fashion using one of the two QProcess::startDetached() static functions
QProcess::startDetached
Sorry for misleading with QDesktopService::URL, later i understood that it wont accept parameter.
So implemented by improving error handling, if process not started/exited badly or waitfor the process to finish the task..I think this is useful
In QProcess, execute is blocking thread, but start is resuming the thread.
Current code is using start() API, but more or less featurewise like execute..
Code is copied from SO and modified little for the current requirements.
> Mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QProcess>
#include <QShortcut>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
cameraControl = new QProcess(this);
}
MainWindow::~MainWindow()
{
delete ui;
cameraControl->close();
delete cameraControl;
}
void MainWindow::on_pushButton_clicked()
{
// connect the camera control finished signal to the slot that will read the exit code and
// place the std output string from the process into a label on the form
connect(cameraControl, SIGNAL(finished(int , QProcess::ExitStatus )),
this, SLOT(on_cameraControlExit(int , QProcess::ExitStatus )));
// Disable the ui button do we don't get double presses
ui->pushButton->setDisabled(true);
// setup the gphoto2 arguments list
QStringList args;
args.append("d:\\text.txt");
// start the camera control
cameraControl->start("notepad",args);
// // wait for the process to finish or 30 seconds whichever comes first
cameraControl->waitForFinished(30000);
}
void MainWindow::on_cameraControlExit(int exitCode, QProcess::ExitStatus exitStatus)
{
qDebug() << cameraControl->errorString();
qDebug() << cameraControl->readAllStandardError();
qDebug() << cameraControl->readAllStandardOutput();
ui->pushButton->setEnabled(true);
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QString>
#include <QProcess>
#include <QObject>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void reply2();
private slots:
void on_pushButton_clicked();
void on_cameraControlExit(int exitCode, QProcess::ExitStatus exitStatus);
private:
Ui::MainWindow *ui;
QProcess* cameraControl;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
in your Qt program,there is a .pro file.You can add this line into the file:
config+=console
I'm new to development with Qt and our design uses the has-a relationship in a couple of places. In some of these cases the container should expose the signal of the internal object, and then I've currently written a private slot for each such signal, where I in practice re-emit the signal again. Is there some short-cut available in Qt that aids in exposing the signal of the internal object on the container?
You don't have to create a slot for reemiting the signal, you could connect a signal with another signal. This way you will avoid the slot definition.
So in your container you would have something like this:
connect(object, SIGNAL(signal1()), this, SIGNAL(signal1()));
Of course you have to redefine the signal on your container.
For more details check the signal slot documentation
From the documentation:
You can connect as many signals as you want to a single slot, and a signal can be connected to as many slots as you need. It is even possible to connect a signal directly to another signal. (This will emit the second signal immediately whenever the first is emitted.)
The following is legal:
connect(sender, SIGNAL(originalSignal()), SIGNAL(newSignal()));
The re-emitting of Signals also allows re-emitting multiple signals.
testclass.h:
#include <QObject>
#include <QDebug>
class TestClass : public QObject
{
Q_OBJECT
public:
explicit TestClass(QObject *parent = 0)
{
connect(this, SIGNAL(signal1()), this, SIGNAL(signal2()));
connect(this, SIGNAL(signal1()), this, SIGNAL(signal2()));
connect(this, SIGNAL(signal2()), this, SLOT(slot()));
}
void emitSignal1()
{
emit signal1();
}
signals:
void signal1();
void signal2();
public slots:
void slot()
{
qDebug() << "SLOT HAS BEEN CALLED";
}
};
main.cpp:
#include <QCoreApplication>
#include "testclass.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
TestClass instance;
instance.emitSignal1();
return a.exec();
}
The result is that the slot is called twice in this case.
If it is internal structure of your class, why won't you make it friend class. Then you can inside your internal structure call directly emit parentObj->signal()
NOTE: THE CODE PROVIDED JUST GIVES THE IDEA OF THE STRUCTURE OF THE APPLICATION
I have a Qt application, interfacing with external hardware. The structure is such that the class for interfacing with the hardware inherits from QObject and is composed with the main GUI thread class. Let's say the class is test.h, here is its sample code:
#ifndef TEST_H
#define TEST_H
#include <QLineEdit>
#include <QString>
#include <QTimer>
#include "ui_test.h"
#define TIMEOUT 100
class TestObj;
class TestApp:public QWidget, public Ui::mTestForm
{
Q_OBJECT
public:
TestApp(QWidget* parent=0);
QTimer* mTimer;
bool mWindowClosed;
TestObj* mObj;
public slots:
void UpdateText();
void Exit();
};
class TestObj:public QObject
{
Q_OBJECT
public:
TestObj();
void RandomTest();
};
#endif
Code for test.cpp is
#include "test.h"
TestApp::TestApp(QWidget* parent):QWidget(parent)
{
setupUi(this);
mObj = new TestObj();
mWindowClosed=false;
mLineEdit->setText("Hello");
mTimer=new QTimer();
mTimer->singleShot(1000,this,SLOT(UpdateText()));
connect(mExitButton,SIGNAL(clicked()),this, SLOT(Exit()));
}
void TestApp::UpdateText()
{
if(mWindowClosed)
{
//QApplication::processEvents();
return;
}
else
{
//QApplication::processEvents();
mObj->RandomTest();
mLineEdit->setText("Hi");
mTimer->singleShot(100,this,SLOT(UpdateText()));
}
}
void TestApp::Exit()
{
mWindowClosed=true;
}
Now consider that TestObj class is the one used to interface with the hardware. This class sends three possible commands (in actual code, the above is just a sample structure) with different timeouts to the hardware, thus we have a timer which is used when sending commands (implemented as functions) to the hardware. Each of these has a processEvents entry to identify any changes to variables in the meanwhile.
The problem is this module is responsible for a steady rise in memory during program execution.
When I comment out the UpdateText() function in the TestApp constructor, the app works fine.
My guess is that most likely there is queuing of signal slots due to which the memory increase, because there are lots of GUI events taking place. And since the class isn't implemented as a separate thread and clubbed with the main GUI thread. There is continuous update of the main thread.
Can someone suggest a way out? I don't have the authority to change the design otherwise I would have implemented the interface class as a thread. So if a solution can be suggested with the current design as is, it would be beneficial.
Creating a regular timer, setting its interval to 100 and connecting its timout signal to the
UpdateText function will avoid events piling up.
P.S: You don't need a QTimer object for singleShot, you can call QTimer::singleShot directly.
Wild guess:
Try changing this:
mTimer->singleShot(100,this,SLOT(UpdateText()));
to this:
if (!slotSet)
{
mTimer->singleShot(100,this,SLOT(UpdateText()));
slotSet = true;
}