Using QLocalSocket with GUI signal readyRead is not emitted (or slot is not being called)
-
Hi all,
I'm writing a small program to inetrcept the Power Button press on a PC running Linux.
On Linux this could be done using the acpid daemon which is sending its events on the unix socket /var/run/acpid.socket.I created a small Qt program that uses QLocalSocket to connect to the acpid daemon, listen to incoming events and print them on the console. Another version of the same program (created only for debug purposes) uses a GUI to display a counter of the events intercepted from the acpid daemon (it is the same program but with a GUI).
I'm showing some code for clarity.
main.cpp
@
#ifdef NO_GUI
// CONSOLE VERSION
#include <QtCore/QCoreApplication>
#include "mainconsole.h"
#else
// GUI VERSION
#include <QtGui/QApplication>
#ifdef Q_WS_QWS
#include <QWSServer>
#endif
#include "mainwindow.h"
#endifint main(int argc, char *argv[])
{
#ifdef NO_GUI
QCoreApplication a(argc, argv);
// CONSOLE VERSION
MainConsole w;
#else
// GUI VERSION
QApplication a(argc, argv);
MainWindow w;
#ifdef Q_WS_QWS
QWSServer::setCursorVisible( false );
w.showFullScreen();
#else
w.show();
#endif
#endifreturn a.exec();
}
@mainconsole.cpp
@
#include "mainconsole.h"
#include <QtNetwork/QLocalSocket>#ifdef _WIN32
#define SOCKET_NAME "\\.\pipe\foo"
#endif#ifdef linux
#define SOCKET_NAME "/var/run/acpid.socket"
#endifMainConsole::MainConsole(QObject *parent) :
QObject(parent)
{
socket = new QLocalSocket();
connect(socket, SIGNAL(readyRead()), this, SLOT(onSocketDataReady()));
connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(onSocketError(QLocalSocket::LocalSocketError)));socket->connectToServer(SOCKET_NAME, QIODevice::ReadOnly); if (socket->waitForConnected(1000)) qDebug("Connected!");
}
void MainConsole::onSocketDataReady()
{
QDataStream in(socket);
in.setVersion(QDataStream::Qt_4_0);
QString data(socket->readAll());
qDebug() << "Data received: " << data;
if(data.contains(QString("button/power")))
qDebug("PowerButton pressed detected!\n");
}void MainConsole::onSocketError(QLocalSocket::LocalSocketError error)
{
qDebug() << "Socket Error: " << error;
}
@mainwindow.cpp
@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>#ifdef _WIN32
#define SOCKET_NAME "\\.\pipe\foo"
#endif#ifdef linux
#define SOCKET_NAME "/var/run/acpid.socket"
#endifMainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);count = 0; socket = new QLocalSocket(); connect(socket, SIGNAL(readyRead()), this, SLOT(onSocketDataReady())); connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)), this, SLOT(onSocketError(QLocalSocket::LocalSocketError))); socket->connectToServer(SOCKET_NAME, QIODevice::ReadOnly); if (socket->waitForConnected(1000)) qDebug("Connected!");
}
MainWindow::~MainWindow()
{
delete ui;
}void MainWindow::onSocketDataReady()
{
QDataStream in(socket);
in.setVersion(QDataStream::Qt_4_0);
QString data(socket->readAll());
qDebug() << "Data received: " << data;
if(data.contains(QString("button/power")))
{
count++;
ui->labelCount->setText(QString::number(count));
qDebug("PowerButton pressed detected!\n");
}
}void MainWindow::onSocketError(QLocalSocket::LocalSocketError error)
{
qDebug() << "Socket Error: " << error;
}
@All the code compiles fine, both the console version and the gui version, but when I run the application, the console version works as expected and prints out the strings received from the socket. The gui version instead, never enters in the onSocketDataReady() slot and never prints out nothing on the qDebug() nor update the label in the UI.
I can't understand where's the difference in the signal-slot calling with and without the UI, in this program.
Thanks for any help/suggestions.
Samuele. -
can you post header files for mainwindow and mainconsole please?
-
Yes, sure.
mainconsole.h
@
#ifndef MAINCONSOLE_H
#define MAINCONSOLE_H#include <QObject>
#include <QtNetwork/QLocalSocket>class MainConsole : public QObject
{
Q_OBJECT
public:
explicit MainConsole(QObject *parent = 0);
~MainConsole();void close();
private:
QLocalSocket *socket;signals:
public slots:
void onSocketDataReady();
void onSocketError(QLocalSocket::LocalSocketError);
};#endif // MAINCONSOLE_H
@mainwindow.h
@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QtNetwork/QLocalSocket>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{
Q_OBJECTpublic:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
int count;
QLocalSocket *socket;private:
Ui::MainWindow *ui;public slots:
void onSocketDataReady();
void onSocketError(QLocalSocket::LocalSocketError);
};#endif // MAINWINDOW_H
@And this is the .pro file:
TestQtAcpi.pro
@
#-------------------------------------------------Project created by QtCreator 2013-01-14T17:13:28
#-------------------------------------------------
CONFIG += gui
QT += core network
TARGET = TestQtAcpinogui {
CONFIG += console
CONFIG -= app_bundle
DEFINES += NO_GUI
SOURCES += mainconsole.cpp
HEADERS += mainconsole.h
} else {
QT += gui
SOURCES += mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
}TEMPLATE = app
SOURCES += main.cpp
@ -
you might want to give ownership of the local socket
@
socket = new QLocalSocket(this);
@ -
Sorry for the late reply.
I have tested the software also using:
@socket = new QLocalSocket(this);@but nothing has changed.
The NON-GUI version intercept correctly the signals, but the GUI version does not intercept any signal, so the slot is never being called.
On the Linux board where I test this program, I run the application with this command:
@# ./TestQtAcpi -qws@because it runs Qt in framebuffer (not inside a desktop environment). Do you think that this could interfere with the signal-slot messaging?
-
Anyway, this is not a problem caused by running the application on the framebuffer.
I've made a test also on a normal Qt installation but it has the same behaviour, the GUI version does not receive any readyRead signal from the QLocalSocket and so the slot is never being called. -
Hi samueleforconi!
I have tested your code on my system (KUbuntu 12.04.1 LTS 64 bit, Qt 4.8.4) and all works fine.
Please, tell your options for qmake which you use for build gui/nongui version. -
I have tested on Ubuntu Desktop and it works (both the GUI and the console version).
Testing on an embedded x86 PC that runs Ubuntu Server 12.04 and Qt in framebuffer mode tha GUI version won't work...I'll explain what I'm seeing as output on the console:
@
Connected!
Data received: "button/power PWRF 00000080 00000031
button/power PWRF 00000080 00000032
button/power PWRF 00000080 00000033
"
PowerButton pressed detected!Data received: "button/power PWRF 00000080 00000034
button/power PWRF 00000080 00000035
button/power PWRF 00000080 00000036
button/power PWRF 00000080 00000037
"
PowerButton pressed detected!Data received: "button/power PWRF 00000080 00000038
button/power PWRF 00000080 00000039
button/power PWRF 00000080 0000003a
"
PowerButton pressed detected!Data received: "button/power PWRF 00000080 0000003b
"
PowerButton pressed detected!
@As you can see, sometimes the slot gets executed, but it's not deterministic... sometimes I need to press the button 2, 3 or 4 times before I can see the debug output on the console... and you can count how many times I have pressed the button watching at the "Data received:" output.
I can't understand this behaviour...