Monitoring file integrity - c++

I would like to write a simple application that tells me when a file has been modified.
Does the <QFileSystemWatcher> class only monitor changes when the program is running?
If so, are there any other classes that I can use for file integrity monitoring?

You could run md5sum, etc. with QProcess initially and then for the changed signals and compare.
The alternative is to read all the file in or mmap and create your hash with QCryptoGraphicHash.
Either way, you would do this initially and then in the signal handlers, a.k.a. slots once the connection is properly made in your QObject subclass.
#include <QObject>
#include <QFileSystemWatcher>
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent = Q_NULLPTR)
: QObject(parent)
{
// ...
connect(m_fileSystemWatcher, SIGNAL(fileChanged(const QString&)), SLOT(checkIntegrity(const QString&)));
// ...
}
public slots:
void checkIntegrity(const QString &path)
{
// 1a. Use QProcess with an application like md5sum/sha1sum
// OR
// 1b. Use QFile with readAll() QCryptoGraphicsHash
// 2. Compare with the previous
// 3. Set the current to the new
}
private:
QFileSystemWatcher m_fileSystemWatcher;
};
Disclaimer: This is obviously not in any way tested, whatsoever, but I hope it demonstrates the concept.

Related

Qt C++ - How to pass data from a worker thread to main thread?

I am trying to perform interthread communication in Qt (C++). I have a worker thread which does some calculations and I want the workerthread to return its results to the main thread when done. I therefor use a connect, I know thanks to debugging, that the signal is successfully being emit but that it is the slot that isn t being executed and I don t understand why.
The relevant pieces of code:
webcamClass::webcamClass(QObject *parent) : QObject(parent)
{
workerThread = new QThread(this);
workerClassObj = new workerClass();
//connect for image
connect(workerClassObj, SIGNAL(mySignal(QPixmap)), this, SLOT(mySlot(QPixmap)));
//connect(&workerClassObj, workerClass::mySignal(QPixmap), this, webcamClass::mySlot(QPixmap));
connect( workerThread, SIGNAL(started()), workerClassObj, SLOT(getImage()) );
workerClassObj->moveToThread(workerThread);
}
void webcamClass:: foo()
{
workerThread->start();
}
void workerClass::getImage()
{
qint64 successFailWrite;
QImage img;
QPixmap pixmap;
... do some stuff with pixmap...
qDebug()<<"going to emit result";
emit mySignal(pixmap);
qDebug()<<"emitted";
}
void webcamClass::mySlot(QPixmap p)
{qDebug()<<"this message should be displayed"; }
The corresponding header files:
class workerClass : public QObject
{
Q_OBJECT
private:
public:
explicit workerClass(QObject *parent = nullptr);
signals:
void mySignal(QPixmap);
};
webcamClass::webcamClass(QObject *parent) : QObject(parent)
{
Q_OBJECT
public:
explicit webcamClass(QObject *parent = nullptr);
public slots:
void mySlot(QPixmap p);
private:
QThread *workerThread;
workerClass *workerClassObj;
};
The code above just outputs:
going to emit result
emitted
but unfortunately doesn t output this message should be displayed.
webcamClass belongs to the parent thread, while workerClass belngs to -you guessed it- the worker thread.
Could someone explain how to setup my connect so that mySlot() gets triggered?
Thanks!
In the code you pasted in pastebin.com/UpPfrNEt you have a getVideoFrame method that uses while (1). If this method is called, it runs all the time and blocks the event loop from handling signals. You can solve it in many ways, I think the best practice will be to replace the while(1) with something else.
If possible, I highly encourage you to use the new Signal Slot syntax:
connect( SOURCEINSTANCE, &CLASS::SIGNAL, TARGETINSTANCE, &CLASS::SLOT );
In your case, that could be:
connect( workerClassObj, &workerClass::mySignal, this, &webcamClass::mySlot );
Specificallyfor your case, if you want to pass Signals and Slots between threads, you have to be careful. First, check the connection type for the connect call, its acutally the last parameter.
connect( workerClassObj, &workerClass::mySignal, this, &webcamClass::mySlot, Qt::QueuedConnection );
For a detailed explanation look here:
http://doc.qt.io/qt-5/signalsandslots.html
If you want to pass custom types, you have to declare them as metatypes first.
Add e.G. this in your constructor:
qRegisterMetaType("MyDataType");
Please make sure, that your custom datatype has a default constructor and be aware that afaik, references cannot be passed across threads.

Using Qthread to run a function

I want to run a function of a class as a thread continuously,till the object of the class is destroyed.
client.h
class client:public QWidget
{
Q_OBJECT
public:
//some declarations
client();
void setclientui();
//some ui elements
void receiveme(); //i want this function to be run as a thread
//It has to be run continuously to receive
//messages from socket and when a message is
//received ,it must display it in the gui.
public slots:
int prework();
void sendme();
};
Note:receiveme() uses recv() of tcp sockets which gets blocked until message is received.
client.cpp
void receiveme(){
while(1){
if(recv(sockfd,receivebuf,1024,0)<0)
{
qDebug()<<errno;
break;
}
receivebuf[20]='\0';
qDebug()<<receivebuf;
outputbox->append(a);
}}
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
Dialog* newdialog;//join a new chat
QString ipp,portt;
QTabWidget *wdg;
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void receivesocketaddress();
void on_actionJoin_a_chat_triggered();
};
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
wdg=new QTabWidget;
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionJoin_a_chat_triggered()
{
newdialog=new Dialog();
newdialog->setWindowTitle("Join a chat");
newdialog->setModal(true);
qDebug()<< QObject::connect(newdialog->conne,SIGNAL(clicked()),this,SLOT(receivesocketaddress()));
newdialog->exec();
}
void MainWindow::receivesocketaddress()
{
client *aclient=new client;
aclient->iptoconnect=newdialog->ip->text().toLocal8Bit().data();
aclient->porti=newdialog->port->text().toLocal8Bit().data();
if(aclient->prework()==0)//ie connected
{
newdialog->close();
wdg->addTab(aclient,tr("new chat"));
setCentralWidget(wdg);
//here the ui is shown.Now the aclient->receiveme() should
//running
}
else
{
newdialog->displayerror();
layout->addWidget(error,3,0,2,2);
qDebug()<<"cud not connect";
}
}
If aclient->prework()==0 then a gui is displayed but how can i run aclient->receiveme() at this time as a thread so that it is continuously running and reading messages from socket.If a message is received,it should be displayed in the gui.
Without thread the gui would freeze.I tried to use QThread::movetothread() but i receive the following error
QThread::cannot move object with parent
and to use subclass method, client class must inherit QThread but since it is already inheriting QWidget,the following error is thrown
call to QObject is ambiguous
How can i use QThread here?
Widgets can run only within GUI thread, so you need to implement client as QObject subclass and communicate with UI via signal/slot connection. Qt wont allow you to do outputbox->append(a) in non UI thread (Supposing that outputbox is some QWidget here);
You probably don't even need to use threads here - Qt provides it's own socket classes with event (signal/slot) based API;
If you still need to use recv() in different thread, you need to subclass QThread (one approach) or QObject (another approach); In both cases you need to have signal like messageReceived(QByteArray) that will be connected to slot in your UI object that will handle message; So receiveme() slot might looks like:
void client::receiveme()
{
while(1){
if(recv(sockfd,receivebuf,1024,0)<0)
{
qDebug()<<errno;
break;
}
receivebuf[20]='\0';
QByteArray msg(receivebuf);
emit messageReceived(msg);
}
}
This article might help

Qt pass variables between forms

I want to pass a string from a form that is opened by the first form to the first form.
I am new to C++.
Here is my code.
Form1.h // main form
#include "dialog.h"
namespace Ui {
class Form1;
}
class Form1 : public QMainWindow
{
Q_OBJECT
public:
explicit Form1(QWidget *parent = 0);
~Form1();
void refresh(QString str_local);
private slots:
void on_pushButton_clicked();
private:
Ui::Form1 *ui;
Dialog *dialog1;
};
// form1.cpp
void Form1::on_pushButton_clicked()
{
dialog1= new Dialog; //Create new form with other class
dialog1->show();
QObject::connect(dialog1, SIGNAL(change(str_remote)), this, SLOT(refresh(str_local))); //Connect when is emit signal cambia in the child form and pass the string to local function
}
void Form1::refresh(QString str_local)
{
qDebug() << "Back to main" << str_local;
ui->label->setText(str_local);
}
// dialog.h the second form that should pass the value to main form
...
class Dialog : public QDialog
{
Q_OBJECT
signals:
void change(QString s);
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private slots:
void on_pushButton_clicked();
private:
Ui::Dialog *ui;
};
// dialog.cpp
...
void Dialog::on_pushButton_clicked()
{
QString name;
name = ui->lineEdit->text();
emit change(name);
this->close();
}
I get the error:
No such signal Dialog::change(str_remote) in ../Format/form1.cpp:22 .
You have some strange code in here:
QObject::connect(dialog1, SIGNAL(change(str_remote)), this, SLOT(refresh(str_local)));
Since your class already inherits QObject indirectly, you can simply drop the scope specifier.
You probably aim for using the new compilation-time syntax signal-slot mechanism.
You have not marked your slot as slot in the header file.
You are trying to use the old signal/slot syntax with variable names for the signal and slot as opposed to the types.
Your signal is not using the good practice of const T& (i.e. constant reference).
You are specifying this explicitly, whereas it can be dropped. This is just admittedly personal taste.
You do not follow the Qt signal/slot naming convention, e.g. your signal is a verb rather adjective. It is also too generic, rather than "fooChanged" as the good practice goes.
There are other issues in your code as well, but this time I only focused on that one line. I would use this line with modern Qt and C++ programming principles in mind:
connect(dialog1, &Dialog::changed, (=)[const auto &myString] {
ui->label->setText(myString);
});
However, since this requires CONFIG += c++14, if your compiler does not support that (e.g. VS2010), you can go for this:
connect(dialog1, SIGNAL(change(const QString&)), this, SLOT(refresh(const QString&)));

Create Thread in QDialog and emit signals to QDialog in Qt

I created an application that has a mainwindow and from this window creates a QDialog. This QDialog should create a RenderThread that emits received images from the camera or in the example emits text. When i debug this it seems that the connection is never made as adding a breakpoint in the slot CameraWindow::debugSomething does not get caught. Whats wrong ?
I followed this example: http://qt-project.org/doc/qt-4.8/threads-mandelbrot.html but it seems that i've done something wrong.
qtDEVC::qtDEVC(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
connect (ui.pushButton_startCam, SIGNAL( clicked() ),this,SLOT( startCam() ) );
/**Threading*/
CameraWindow camWindow = new CameraWindow(this);
}
int qtDEVC::startCam()
{
camWindow.show();
camWindow.startCaptureThread();
}
CameraWindow Class:
CameraWindow::CameraWindow(QWidget *parent)
: QDialog(parent)
{
ui.setupUi(this);
connect(&thread, SIGNAL(sendText(std::string)),
this, SLOT(debugSomething(std::string)));
}
void CameraWindow::debugSomething(std::string something){
QString somethings(something.c_str());
qDebug()<<somethings;
}
int CameraWindow::startCaptureThread(){
RenderThread *thread = new RenderThread(this, guid, CLEYE_COLOR_RAW, CLEYE_VGA, 50);
thread->StartCapture(); //starts thread in low priority and sets _running to true
}
CameraWindow header
class CameraWindow : public QDialog
{
Q_OBJECT
public:
CameraWindow(QWidget *parent = 0);
~CameraWindow();
Ui::CameraWindow ui;
public slots:
int startCaptureThread();
void debugSomething(QString);
private:
RenderThread thread;
};
RenderThread Class
void RenderThread::run()
{
// image capturing loop
while(_running)
{
qDebug()<<("render while()"); //is printed with qdebug correctly
if (restart)
break;
if (abort)
return;
qDebug("it"); //is also printed with qdebug correctly
emit sendText(text);
}
RenderThread header
class RenderThread : public QThread
{
Q_OBJECT
public:
RenderThread(QObject *parent, GUID cameraGUID, CLEyeCameraColorMode mode, CLEyeCameraResolution resolution, float fps);
RenderThread();
~RenderThread();
bool StartCapture();
signals:
void sendText(QString &text);
protected:
void run();
private:
QMutex mutex;
QWaitCondition condition;
//some more private variables for construction
};
I think that this creation seems somehow wrong: RenderThread *thread = new RenderThread(this);
The first thing that's worrying about the question is the word "RenderThread". Note that Qt only allows rendering on the main thread. You can create separate threads for calculations of image data, but whenever you use a painter and draw objects, that must happen on the main thread. However, If you're just going to capture the image and pass that to the main thread, via signals and slots, then that should be ok.
Secondly, whilst you've not shown all your code, I'm assuming from the function called RenderThread::run() and from the Qt example that you may have inherited from QThread here. If this is the case, please note that this is not how to use QThread. Instead, you should have your class inherit from QObject and move that to a QThread. You can read about how to use QThread properly here.
I know it's a Qt example that you've followed, but even the guys at Qt think it's a bad idea. Here's an article of how to really use QThreads.
With that in mind, here's an outline of how I would use QThread for this: -
class CameraWindow : public QDialog
{
private:
CameraObject* m_pCamObject;
};
class CameraObject : public QObject
{
Q_OBJECT
public:
private slots:
startCaptureThread();
private:
};
int CameraWindow::startCaptureThread()
{
m_pCamObject = new CameraObject;
QThread* pThread = new QThread;
this->moveToThread(pThread); // CameraObject will run on the new thread
connect(pThread, SIGNAL(started()), m_pCamObject, SLOT(startCaptureThread()));
connect(pThread, SIGNAL(finished()), pThread, SLOT(deleteLater()); // clear up when
finished
pThread->start();
}
Note that here is a CameraObject, separated from the CameraWindow. The QThread is just a controller of the thread and keeps a clean separation from the CameraObject.
Another reason for handling threads this way is that you can move multiple QObject instances to the new thread, rather than always creating a new thread per object. If you've more threads than CPU cores, you're unlikely to gain by creating yet another thread.
In the constructor of CameraWindow class, you are connecting a RenderThread's signal but it is not the same object which is started in startCaptureThread. Change your startCaptureThread like this:
int CameraWindow::startCaptureThread()
{
thread.StartCapture(); //starts thread in low priority and sets _running to true
}
In this method, the thread member of CameraWindow is started.
P.S.: post the headers too, we can't see the members from this code.
In the mentioned example, CameraWindow class holds a RenderThread thread variable, not a RenderThread *thread.
You are connecting a pointer address in your connect call:
connect(&thread, SIGNAL(sendText(std::string)),
this, SLOT(debugSomething(std::string)));
Try to use a good address:
connect(thread, SIGNAL(sendText(std::string)),
this, SLOT(debugSomething(std::string)));
This is not a tested answer.

Transfer data between forms in Qt

I have a school project where I am using Qt to drive my GUI interface. I need to know the best way or the easiest way to transfer a vector of class objects between the different .cpp files for the different forms. I was thinking of including the .h files and making a setPointer and getPointer that points to the vector, but is there a better way?
Thanks for the help
Let's assume that, you are using two forms. formA and formB.
Create a signal and slot in forma.cpp
public slots:
void receiveData(QVectorobjects);
signals:
void sendData(QVector);
Do the same for formb.cpp.
Now connect formA and formB like this.
connect(formA, SIGNAL(sendData(QVector<MyClass>)), formB, SLOT((receiveData(QVector<MyClass>)));
connect(formA, SIGNAL(receiveData(QVector<MyClass>)), formB, SLOT((MyClass(QVector<MyClass>)));
Now formA will share data (set of objects) when you write emit sendData(QVector() << objA << objB); and formB will catch it!
Enjoy the magic of signal and slot. :)
You should use custom signals and slots.
Your main window can connect signal and slot between each form.
In this way, you forms are independent of each other (i.e. doesn't need a pointer).
First of all, Qt container classes are implicitly shared, that means you can pass them by value, and only a shallow copy will occur. If you attempt to modify the container, then a new copy will be created. So there is no need to use pointers in that particular case.
Then, use signals and slot to do the actual data transfer - the common pattern is for the parent widget to manage its child widgets, and it is that parent class that the actual passing of data usually takes place.
The best way to transfer data between Qt-classes is to use signal/slot system.
Pay an attention, that if you want to transfer data with type differ from standard C++ and Qt, you should register it's type with qRegisterMetaType
Depending upon your usage, there can be at least two ways.
First is to create a public variable in your class (form) to which you can assign the current value of the vector (pointer) so that you can access it in that class.
Another option is to create a singleton class in the application and store the vector pointer inside that class. This will allow access to this class throughout the application.
Based on your requirement, if you want the vector to stay alive for the application life, you should opt the second option, otherwise opt the first option.
What about extern keyword? But Qt's signal slot is safe.
Use QVector or QList or any number of Qt's container classes. You can pass an iterator to your forms, or a reference (QList::operator[]) to the form so that you're not copying the data.
If you want to pass the whole vector, pass it as a reference. For example:
//pass the whole vector as for read-write
void doStuffOnMany(QList<MyClass>& listref) {} //declaration
...
QList<MyClass> mylist; //usage
doStuffOnMany(mylist);
//read-only
void doStuffOnMany(const QList<MyClass>& listref) {}
//pass one portion of the vector for read-write
void doStuffOnOne(MyClass& classref) {} //declaration
...
QList<MyClass> mylist; //usage
doStuffOnOne(mylist[0]);
Also, the Qt container classes are implicitly shared, so you don't even necessarily have to pass a reference to the vector if you need good performance.
I ended up using the extern keyword. I looked in to custom signals and slots and I think that it would be the better way to go, but given time and the fact that this is for school I went with the fast and dirty way for now.
Here is a simple explanation:
Take two forms:
Dialog windows
Dashboard and Sensor
on Dashboard:
#ifndef DASHBOARD_H
#define DASHBOARD_H
#include "sensor.h"
#include <QDialog>
namespace Ui {
class dashboard;
}
class dashboard : public QDialog
{
Q_OBJECT
public:
explicit dashboard(QWidget *parent = 0);
QTimer *timer;
~dashboard();
public slots:
void MyTimerSlot();
private slots:
void on_pushButton_clicked();
private:
Ui::dashboard *ui;
double mTotal;
sensor *snsr;
};
#include "dashboard.h"
#include "ui_dashboard.h"
#include <QDebug>
#include <QTimer>
#include <QMessageBox>
dashboard::dashboard(QWidget *parent) :
QDialog(parent),
ui(new Ui::dashboard)
{
ui->setupUi(this);
this->setWindowTitle(QString("dashboard"));
// create a timer
timer = new QTimer(this);
// setup signal and slot
connect(timer, SIGNAL(timeout()),
this, SLOT(MyTimerSlot()));
timer->stop();
mTotal = 0;
snsr = new sensor(this);
// msecx
}
dashboard::~dashboard()
{
delete ui;
}
void dashboard::on_pushButton_clicked()
{
snsr->show();
}
void dashboard::MyTimerSlot()
{
mTotal += 1;
snsr->setValue(mTotal);
ui->sensorlabel->setText(QString::number(mTotal));
}
Now on Sensor: sensor.h
#ifndef SENSOR_H
#define SENSOR_H
#include <QTimer>
#include <QDialog>
namespace Ui {
class sensor;
}
class sensor : public QDialog
{
Q_OBJECT
public:
explicit sensor(QWidget *parent = 0);
~sensor();
public slots:
void setValue(double value);
signals:
void changeLabel();
void valueChanged(double newValue);
private:
Ui::sensor *ui;
double mTotal;
};
#endif // SENSOR_H
sensor.cpp
#include "sensor.h"
#include "ui_sensor.h"
#include "dashboard.h"
sensor::sensor(QWidget *parent) :
QDialog(parent),
ui(new Ui::sensor)
{
ui->setupUi(this);
this->setWindowTitle(QString("sensor"));
connect(this, SIGNAL(valueChanged(double)), this, SLOT(changeLabel()));
}
void sensor::changeLabel()
{
ui->sensorlabel->setText(QString::number(mTotal));
}
void sensor::setValue(double value)
{
if (value != mTotal) {
mTotal = value;
emit changeLabel();
}
}
sensor::~sensor()
{
delete ui;
}