Q_PROPERTY not working properly in linux distro - qt

i’m developing a clock application and I need to do it using Q_PROPERTY. The idea is to make all the clock control logic using C++ and deploy it in a QML GUI.
I got this working on a windows machine but when I run it on a linux distro in a development board I get sometimes undefined text (which are the exposed properties from C++).
The header file is:
#ifndef QCPPCLOCK_H
#define QCPPCLOCK_H
#include <QObject>
#include <QDebug>
#include <QString>
#include <QTime>
#ifdef __linux__
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#endif
class QcppClock : public QObject
{
Q_OBJECT
Q_PROPERTY(QString hours READ hours WRITE setHours NOTIFY hoursChanged)
Q_PROPERTY(QString minutes READ minutes WRITE setMinutes NOTIFY minutesChanged)
private:
QString actualHours;
QString actualMinutes;
QObject* rootObject;
QTime actualTime;
qint8 alarmHour;
qint8 alarmMinutes;
QString timeFormat;
bool alarmSet;
#ifdef __linux__
struct tm* ptm;
struct timeval tv;
#endif
public:
explicit QcppClock(QObject *parent = 0);
QString hours();
void setHours(QString);
QString minutes();
void setMinutes(QString);
public slots:
void qcppClock_vUpdateTextTime_slot(void);
signals:
void qcppClock_vTriggerAlarm_signal(void);
void hoursChanged(void);
void minutesChanged(void);
};
#endif // QCPPCLOCK_H
The .cpp file:
#include "qcppclock.h"
#include <QTimer>
#include <QtCore/qmath.h>
QcppClock::QcppClock(QObject *parent) :
QObject(parent)
{
QTimer* timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(qcppClock_vUpdateTextTime_slot()));
rootObject = parent;
actualTime = QTime::currentTime();
/* Initialize the format to 24 hours */
timeFormat = "24hours";
timer->start(1000);
#ifdef __linux__
gettimeofday (&tv, NULL);
ptm = localtime (&tv.tv_sec);
int hour = ptm->tm_hour;
//setHours(hour);
//actualHours = QString::number(hour);
int minutes = ptm->tm_min;
//setMinutes(minutes);
//actualMinutes = QString::number(minutes);
int seconds = ptm->tm_sec;
(void)actualTime.setHMS(hour , minutes, seconds);
#endif
}
QString QcppClock::hours()
{
return actualHours;
}
void QcppClock::setHours(QString newHours)
{
actualHours = newHours;
#ifdef __linux__
tv.tv_sec += 3600 * actualHours.toInt();
settimeofday(&tv, NULL);
#else
(void)actualTime.setHMS(actualHours.toInt() , actualMinutes.toInt(), actualTime.second());
#endif
emit hoursChanged();
}
QString QcppClock::minutes()
{
return actualMinutes;
}
void QcppClock::setMinutes(QString newMinutes)
{
actualMinutes = newMinutes;
#ifdef __linux__
tv.tv_sec += 60 * actualMinutes.toInt();
settimeofday(&tv, NULL);
#else
(void)actualTime.setHMS(actualHours.toInt() , actualMinutes.toInt(), actualTime.second());
#endif
emit minutesChanged();
}
void QcppClock::qcppClock_vUpdateTextTime_slot(void)
{
actualTime = actualTime.addSecs(1);
actualMinutes = QString::number(actualTime.minute());
emit minutesChanged();
actualHours = QString::number(actualTime.hour());
emit hoursChanged();
QString::number(actualTime.minute());
}
The main file which instantiates the clockctrl object is:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "qcpp_Clock/qcppclock.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
QcppClock qcpp_Clock;
QQmlContext* context = engine.rootContext();
context->setContextProperty("clockCtrl", &qcpp_Clock);
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
return app.exec();
}
And the QML file using the exposed properties is:
import QtQuick 2.2
import QtQuick.Window 2.1
Window {
visible: true
width: 800
height: 480
MouseArea {
anchors.fill: parent
onClicked: {
Qt.quit();
}
}
Text {
property string prHours: clockCtrl.hours
property string prMinutes: clockCtrl.minutes
text: {
console.log(clockCtrl, clockCtrl.hours, clockCtrl.minutes);
return (prHours + " : " + prMinutes)
}
anchors.centerIn: parent
}
}
As you can see it’s a short and easy code, the problem is in QML when I try to make reference to the C++ exposed properties, i added a couple of consoles in order to see the result in the log and It works like a charm in windows, I never get these “undefined text” but in the development board with linux distro I get sometimes:
qml: QcppClock(0×7e8eeca8) 1 49
qml: QcppClock(0×7e8eeca8) undefined undefined
qml: QcppClock(0×7e8eeca8) 1 49
The first debug is the address of the c++ exposed object in C++, then, the Q_PROPERTY “hour” and the Q_PROPERTY “minutes”.
Thank you in advance.
Ramsés

Related

How to get 2D array from UART to QList<QString> Qt and set text on QML

I receive a 2D array from UART that sent from Arduino.
I can show it in debug, but I can not save it in a QList variant to set text for matrix of rectangle in QML.
I want to show text on QML each rectangle.
How I can do?
This is Arduino code. I send 2d array 17x17
void setup(){
pinMode(LED_BUILTIN,OUTPUT);
analogWrite(LED_BUILTIN,255);
Serial.begin(115200);
void loop(){
double data[17][17];
if(Serial.available()){
delay(100);
for(int i=0; i<17; i++){
for(int j=0; j<17; j++){
data[i][j] = i+j+0.01;
sendData(data[i][j]);
delay(10);
}
}
}
return;
}
void sendData(double data){
Serial.print((data));
}
This is readSerial function:
void serial::readSerial(){
serialData = arduino.readAll();
qDebug()<< serialData <<"\n";
}
QML file:
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 17*square_size
height: 17*square_size
title: qsTr("Hello World")
property int square_size: 30
Grid {
id: grid
columns: 17
Repeater{
id: rpt
model: 17*17
Rectangle{
width: square_size
height: square_size
border.color: "black"
border.width: 1
Text {
anchors.centerIn: parent
text: Serial.model_data[index]
}
}
}
}
}
serial.h:
#include <QQmlApplicationEngine>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QtDebug>
class serial: public QObject
{
Q_OBJECT
Q_PROPERTY(QList<QString> text READ text NOTIFY textChanged)
public:
explicit serial(QQmlApplicationEngine *engine, QObject *parent = nullptr);
~serial();
void setupSerial();
Q_INVOKABLE QList<QString> text(){
return m_text;
}
private slots:
void readSerial();
private:
QQmlApplicationEngine* m_engine;
/* Varian of Arduino*/
QSerialPort arduino;
bool arduino_is_avaiable;
QString portName;
QByteArray serialData;
/*Varian of text*/
QList<QString> m_text;
signals:
void textChanged();
public slots:
};
#endif // SERIAL_H
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "serial.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
serial myserial(&engine);
engine.rootContext()->setContextProperty("Serial", &myserial);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
I think you are missing the property on the Serial class to read the data: text: Serial.model_data[index]. The fastest solution to get something on screen would be to add that property and fill it as follows:
Serial.h (I left some parts out)
class Serial : public QObject
{
Q_OBJECT
Q_PROPERTY(QVariantList model_data READ model_data NOTIFY modelDataChanged)
public:
explicit Serial(QObject *parent = nullptr);
QVariantList model_data() const { return model_data_; }
signals:
void modelDataChanged();
private slots:
void readSerial();
private:
QVariantList model_data_;
};
The readSerial() function would look like this:
void Serial::readSerial()
{
QByteArray serialData = QByteArray(17 * 17 * 8, 0); //shortcut for testing
double *arr = reinterpret_cast<double*>(serialData.data());
model_data_.clear();
for(int i=0;i<17*17;i++)
{
model_data_.append(arr[i]);
}
emit modelDataChanged();
}
What happens is that the QVariant list is filled with the doubles, which have been reinterpreted from byte to doubles. Note that this has to be done every time the serialData changes.
However, this might not be ideal in case you want to go any further with this. When changing dimensions, this setup will fail, both on arduino sending side, arduino reading side and on qml side. You should consider sending the dimensions of the array, reading those back and acting on it. One idea might be QAbstractListModel, which already has the notion of rows/columns; another, simpler idea might be to add properties to the Serial class stating the dimensions (which where read in readSerial())

Qt: QObject::connect: No such slot QObject::processPendingDatagrams() [duplicate]

This question already has answers here:
When should Q_OBJECT be used?
(4 answers)
QT "No such slot" Error [duplicate]
(1 answer)
Closed 6 years ago.
I have written an UDP programme with Qt, and when I connect this:
connect(socket,SIGNAL(readyRead()),this,SLOT(processPendingDatagrams()));
the complier tells me that
no such slot
the error click here
and I want to know how to fix it, thank you!
P.S.
Here are my files:
files
Here are my codes:
enter code here
udptest.cpp:
#include "udptest.h"
#include <QObject>
#include <QUdpSocket>
#include <QtNetwork>
UDPtest::UDPtest()
{
socket = new QUdpSocket();
port = 2016;
socket->bind(port,QUdpSocket::ShareAddress
| QUdpSocket::ReuseAddressHint);
connect(socket,SIGNAL(readyRead()),this,SLOT(processPendingDatagrams()));
}
QString UDPtest::getIP()
{
QList<QHostAddress> list = QNetworkInterface::allAddresses();
foreach (QHostAddress address, list)
{
if(address.protocol() == QAbstractSocket::IPv4Protocol)
return address.toString();
}
return 0;
}
void UDPtest::sendMessage(QString message)
{
QByteArray data;
QDataStream out(&data,QIODevice::WriteOnly);
QString localHostName = QHostInfo::localHostName();
QString address = getIP();
out <<"123"<< localHostName << address << message;
socket->writeDatagram(data,data.length(),QHostAddress::Broadcast, port);
}
void UDPtest::processPendingDatagrams()
{qDebug()<<"receive";
while(socket->hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize(socket->pendingDatagramSize());
socket->readDatagram(datagram.data(),datagram.size());
QDataStream in(&datagram,QIODevice::ReadOnly);
QString userName,localHostName,ipAddress,message;
QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
in >>userName >>localHostName >>ipAddress >>message;
QString msg=time+userName+localHostName+ipAddress+message;
msger=msg;
qDebug()<<msg;
}
}
QString UDPtest:: messager()
{
return msger;
}
main.cpp:
#include"udptest.h"
#include<QDebug>
#include <QtCore/QCoreApplication>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug()<<"123";
UDPtest test;
test.sendMessage("aha");
return a.exec();
}
udptest.h:
#ifndef UDPTEST_H
#define UDPTEST_H
#include <QObject>
#include <QUdpSocket>
#include <QtCore/QCoreApplication>
#include <QtNetwork>
class UDPtest:public QObject
{
public:
UDPtest();
QString messager();
void sendMessage(QString);
private slots:
void processPendingDatagrams();
private:
QString msger;
QUdpSocket *socket;
qint16 port;
QString getIP();
};
#endif // UDPTEST_H
QudptestConsole.pro:
QT += core
QT -= gui
QT += network
CONFIG += c++11
TARGET = QudptestConsole
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp \
udptest.cpp
HEADERS += \
udptest.h
You have forgotten Q_OBJECT macro in UDPtest class
class UDPtest: public QObject
{
Q_OBJECT
public:
UDPtest();
.....
}

Windows Task Manager shows process memory keeps growing

I observed that through task mgr, the memory increases in steps of 4kB and 8kB, though not necessarily in this order.
Possible duplicate: Windows Task Manager shows process memory keeps growing even though there are no memory leaks
I am not sure whether this's occurring because I did not release the QTimer object, timer2. Please advise me how to stop this memory increase, and whether my guess of why it's occurring, is correct.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtCore>
#include <QDebug>
#include <QDateTime>
#include <QFileInfo>
#include <QString>
#include <opencv/cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#define TIMER2_VALUE 3000
#define UPDATED_IMAGE_STORAGE_PATH "E:\\QT1\\timeStampDateMod2\\TimeStampDateMod2\\updatedRefImg.JPG"
#define UPDATED_IMAGE_BACKUP_PATH "E:\\QT1\\timeStampDateMod2\\TimeStampDateMod2\\backUp\\updatedRefImg[%1].JPG"
using namespace std;
using namespace cv;
typedef struct
{
QDateTime dateTimeMod1;
QDateTime dateTimeMod2;
}tTimeMods;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QTimer *timer2;
tTimeMods findTimeModifiedStruct();
QDateTime findTimeModified();
void compareTimeMods(tTimeMods timeTypeFunction, QDateTime dateTimeMod2);
QString appendWithImageName(tTimeMods timeTypeFunction);
void shiftToRepository(QString pathString);
void updatedImgToRepository(QString pathString);
public slots:
void timerSlot2();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
tTimeMods timeTypeFunction, timeTypeMain;
QDateTime dateTimeMod2;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
timeTypeMain = findTimeModifiedStruct();
timer2 = new QTimer(this);
connect(timer2, SIGNAL(timeout()), this, SLOT(timerSlot2()));
timer2->start(TIMER2_VALUE);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::timerSlot2()
{
dateTimeMod2 = findTimeModified();
compareTimeMods(timeTypeMain, dateTimeMod2);
//delete timer2;
}
//tTimeMods findTimeModifiedStruct()
tTimeMods MainWindow::findTimeModifiedStruct()
{
QString myFileName = UPDATED_IMAGE_STORAGE_PATH;
QFileInfo info(myFileName);
/*find last date modified*/
timeTypeFunction.dateTimeMod1 = info.lastModified();
timeTypeFunction.dateTimeMod2 = info.lastModified();
qDebug()<< "dateTimeMod1: " << timeTypeFunction.dateTimeMod1.toString() << endl << "dateTimeMod2: "<< timeTypeFunction.dateTimeMod2.toString();
return(timeTypeFunction);
}
QDateTime MainWindow::findTimeModified()
{
QString myFileName = UPDATED_IMAGE_STORAGE_PATH;
QFileInfo info(myFileName);
QDateTime dateTimeMod2 = info.lastModified();
qDebug()<< "dateTimeMod2: "<< dateTimeMod2.toString();
return(dateTimeMod2);
}
void MainWindow::compareTimeMods(tTimeMods timeTypeFunction, QDateTime dateTimeMod2)
{
if(dateTimeMod2 >= timeTypeFunction.dateTimeMod1)
{
timeTypeFunction.dateTimeMod1 = dateTimeMod2;
QString pathString = appendWithImageName(timeTypeFunction);
shiftToRepository(pathString);
}
}
QString MainWindow::appendWithImageName(tTimeMods timeTypeFunction)
{
/*appending just the timeMod with the path & image name*/
QString path = QString(UPDATED_IMAGE_BACKUP_PATH).arg(timeTypeFunction.dateTimeMod1.toString());
qDebug()<< "path: " << path;
return path;
}
void MainWindow::shiftToRepository(QString pathString)
{
updatedImgToRepository(pathString);
}
void MainWindow::updatedImgToRepository(QString pathString)
{
pathString.replace(":","-");
pathString.replace(1,1,":");
qDebug()<<"pathString now: "<<pathString;
/*convert QString into char* */
QByteArray pathByteArray = pathString.toLocal8Bit();
const char *path = pathByteArray.data();
IplImage *InputImg = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
InputImg = cvLoadImage(UPDATED_IMAGE_STORAGE_PATH ,CV_LOAD_IMAGE_UNCHANGED);
/*save the image*/
cvSaveImage(path,InputImg);
cvReleaseImage(&InputImg);
}
I'm not familiar with OpenCV, but it seems that these two lines cause you memory leak:
IplImage *InputImg = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
InputImg = cvLoadImage(UPDATED_IMAGE_STORAGE_PATH ,CV_LOAD_IMAGE_UNCHANGED);
In the first line you are creating an object, but in the second you are assigning another object to the pointer without releasing the previous one, so the previous one gets leaked.
Is creating an image even needed, while you are going to load it?

reading data from linux input on embedded board

i compiled the following code for arm9 board. whenever i press any key the event should be detected.
keypress.ccp:
#include "keypress.h"
#include <QApplication>
#include <QKeyEvent>
KeyPress::KeyPress(QWidget *parent) :
QWidget(parent)
{
myLabel = new QLabel("LABEL");
mainLayout = new QVBoxLayout;
mainLayout->addWidget(myLabel);
setLayout(mainLayout);
}
void KeyPress::keyPressEvent(QKeyEvent *event)
{
if(event->key() == Qt::Key_A)
{
myLabel->setText("You pressed A");
}
}
void KeyPress::keyReleaseEvent(QKeyEvent *event)
{
if(event->key())
{
qDebug()<<"key released";
}
if(event->key() == Qt::Key_A)
{
myLabel->setText("You released A");
}
}
keypress.h:
#ifndef KEYPRESS_H
#define KEYPRESS_H
#include <QWidget>
#include <QtGui>
class KeyPress : public QWidget
{
Q_OBJECT
public:
KeyPress(QWidget *parent = 0);
protected:
void keyPressEvent(QKeyEvent *);
void keyReleaseEvent(QKeyEvent *);
private:
QLabel *myLabel;
QVBoxLayout *mainLayout;
};
#endif // KEYPRESS_H
main.cpp
#include <QtGui>
#include "keypress.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qDebug()<<"test";
KeyPress *keyPress = new KeyPress();
keyPress->show();
return a.exec();
}
using external key pad.
qt configuration:
/configure -embedded arm -xplatform qws/linux-arm-gnueabi-g++ -little-endian -qt-gfx-linuxfb -qt-gfx-qvfb -qt-kbd-tty -qt-kbd-qvfb -qt-kbd-linuxinput -qt-mouse-linuxinput -qt-mouse-qvfb -qt-mouse-pc -declarative -confirm-license
on board: export QWS_KEYBOARD="LinuxInput:/dev/input/event0"
when i run cat /dev/input/event0 | hexdump i am able to recieve keycodes for the key pressed. but when i run the the executable keypad is not responding. am i missing something? if so what else i should do to make the keypad work??

Declaring a signal in Qt script prototype

I tried declaring a signal in a prototype and then connecting it is script funcition for some reason it does not work as I hoped. My code is as follows. Could some one help me in this.
What I expected was, once I called p.setText('New String') in the script code, since setText emits the textChanged signal it should invoke the slot which is catchSignal(text) already connected in the script code.
Prototype header
#ifndef SCRIPTACTION_H
#define SCRIPTACTION_H
#include <QObject>
#include <QtScript>
class ScriptAction : public QObject , public QScriptable
{
Q_OBJECT
public:
ScriptAction(QObject *parent = 0);
signals:
void textChanged(const QString changedString);
};
#endif // SCRIPTACTION_H
Class
#include "scriptaction.h"
#include <QAction>
Q_DECLARE_METATYPE(QAction*)
ScriptAction::ScriptAction(QObject *parent) : QObject(parent)
{
}
Main Class
#include <QApplication>
#include <QDebug>
#include <QAction>
#include "scriptaction.h"
#include <QPushButton>
Q_DECLARE_METATYPE(QAction*)
QScriptValue qAction_Constructor(QScriptContext *ctx, QScriptEngine *eng)
{
qDebug() << "QAction is called";
if(ctx->isCalledAsConstructor())
{
QObject *parent = ctx->argument(0).toQObject();
QAction *action = new QAction("Test",parent);
return eng->newQObject(action, QScriptEngine::ScriptOwnership);
} else {
return QString("invalid call. Use new Constructor");
}
}
int main(int argc, char *argv[])
{
QApplication app(argc,argv);
QScriptEngine engine;
//Evaluating a simaple expresssion
qDebug() << engine.evaluate("1+2").toNumber();
QPushButton button;
QScriptValue buttonScript= engine.newQObject(&button);
engine.globalObject().setProperty("button", buttonScript);
engine.evaluate("button.text ='Hello Text'; button.show()");
//QAction Prototype
ScriptAction qsAction ;
QScriptValue script_proto = engine.newQObject(&qsAction);
engine.setDefaultPrototype(qMetaTypeId<QAction*>(), script_proto);
QScriptValue ctor = engine.newFunction(qAction_Constructor , script_proto);
QScriptValue metaObject = engine.newQMetaObject(&QObject::staticMetaObject, ctor);
engine.globalObject().setProperty("QSAction" , metaObject);
engine.evaluate("var p = new QSAction(button);p.textChanged.connect(catchSignal);");
engine.evaluate("function catchSignal(text) { print ('PROTOTYPE SIGNAL IS CALLED ',text); } p.setText('New String'); " );
return app.exec();
}
I got rid of the issue, and now I see the signal is being triggered and slot is called properly.
All I did was moving the code to a separate script file and start using the QScriptDebugger to see its output. Then I figured there was an error and the code is edited to work.
Anyone who wants an example prototype class, this will hopefully be a good guideline.

Resources