I'm trying to collect QNetworkCookies in a QSet. I create the QSet QSet<QNetworkCookie> cookies
and then insert the cookies with
cookies.insert(cookie); The compiler then tells me, that there is no qHash for QNetworkCookie, so I added an inline method like you can see in the code listing below. The compiler now is happy, but the method never gets called and the set contains the same cookie multiple times. Can someone point me in the right direction?
#ifndef BROWSER_H
#define BROWSER_H
#include <QDebug>
#include <QMainWindow>
#include <QNetworkCookie>
#include <QObject>
#include <QWebEngineView>
class Browser : public QMainWindow
{
Q_OBJECT
private:
QWebEngineView *webEngine;
QSet<QNetworkCookie> cookies;
public:
explicit Browser(const QUrl &url);
protected slots:
void finishLoading(bool);
void handleCookieAdded(const QNetworkCookie &cookie);
};
inline uint qHash(const QNetworkCookie &key, uint seed)
{
uint hash = qHash(key.domain(), seed) ^ qHash(key.name(), seed);
qDebug() << "qHash " << key.domain() << " " << key.name() << " " << hash;
return hash;
}
#endif // BROWSER_H
Related
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?
I have a problem. I'm writing a small application, which will fetch an image from a website and display it in a QT GUI application.
I use QHttp to do this. The code works if I execute it in main (before GUI is shown), but when I try to implement it, so that the code will run when I click on a button, it doesn't work.
Here's some of the code:
downloader.h - The class that's responsible for creating connection and saving image
#ifndef DOWNLOADER_H
#define DOWNLOADER_H
#include <QObject>
#include <QHttp>
#include <QFile>
#include <QDebug>
#include <QDir>
class Downloader : public QObject
{
Q_OBJECT
public:
explicit Downloader(QObject *parent = 0);
void getImageFromWeb(QString host, QString append);
signals:
public slots:
void stateChanged(int state);
void responseHeaderReceived(const QHttpResponseHeader &resp);
void requestFinished(int id, bool error);
private:
QHttp *http;
};
#endif // DOWNLOADER_H
downloader.cpp - The implementation
The case switches are added for debugging
#include "downloader.h"
#include <QApplication>
Downloader::Downloader(QObject *parent) :
QObject(parent)
{
}
void Downloader::getImageFromWeb(QString host, QString append)
{
http = new QHttp(this);
connect(http, SIGNAL(stateChanged(int)), this, SLOT(stateChanged(int)));
qDebug() << "Connect 1";
connect(http, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(responseHeaderReceived(QHttpResponseHeader)));
qDebug() << "Connect 2";
connect(http, SIGNAL(requestFinished(int,bool)), this, SLOT(requestFinished(int,bool)));
qDebug() << "Connect 3";
http->setHost(host);
http->get(append);
}
void Downloader::stateChanged(int state)
{
switch(state)
{
case 0:
qDebug() << "Unconnected";
break;
case 1:
qDebug() << "Hhost Lookup";
break;
case 2:
qDebug() << "Connection";
break;
case 3:
qDebug() << "Sending";
break;
case 4:
qDebug() << "Reading";
break;
case 5:
qDebug() << "Connect";
break;
case 6:
qDebug() << "Closing";
break;
}
}
void Downloader::responseHeaderReceived(const QHttpResponseHeader &resp)
{
qDebug() << "Size" << resp.contentLength();
qDebug() << "Type" << resp.contentType();
qDebug() << "Status" << resp.statusCode();
}
void Downloader::requestFinished(int id, bool error)
{
if(error)
{
qDebug() << "ERROR!";
}
else
{
qDebug() << "OK";
QFile *file = new QFile(QDir::currentPath() + "/image.png");
if(file->open(QFile::Append))
{
file->write(http->readAll());
file->flush();
file->close();
}
delete file;
}
}
main.cpp - The code above works correctly if it is implemented like this
#include "mainwindow.h"
#include <QApplication>
#include <downloader.h>
int main(int argc, char *argv[])
{
Downloader getImage;
getImage.getImageFromWeb("servlet.dmi.dk", "/byvejr/servlet/byvejr?by=8000&tabel=dag3_9");
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Instead of this, I would like the image to be fetched when I press a button in the program, so I tried this:
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "downloader.h"
#include <QApplication>
#include <QDir>
void MainWindow::on_pushButton_clicked()
{
Downloader getImage;
getImage.getImageFromWeb("www.dmi.dk/", "/uploads/tx_dmidatastore/webservice/k/d/_/n/g/femdgn_dk.png");
}
This doesn't work. From the debugger I get:
Connect 1
Connect 2
Connect 3
When it works (when it's implemented in main.cpp) the debugger gives me something like:
Connect 1
Connect 2
Connect 3
OK
Connection
Sending
Reading
Size 16282
Type "image/png"
Status 200
Connect
OK
So I guess this tells me that the connections are made, but nothing is being executed.
Any answer/suggestion is appreciated.
Thanks in advance!
Looks like your getImage object is being descoped/destructed before it can do anything. Try creating a Downloader object as a member of MainWindow instead of inside the on_pushButton_clicked() function.
OK, I'm a total beginner but I'm missing something here. Been all over the Qt documentation/examples and everything I can dig up through Google. All similar information is slightly different in context...
I'm just starting out with Qt SIGNALS and SLOTS, I'm successful with gui examples and within a class. Now I want to connect a SIGNAL in a child class with a SLOT in a sibling class with the Connect defined in the parent main. Ultimately my aim is to receive iamges in a class handling a QTcpSocket and emit the data as char* to be handled (saved or displayed) by another class.
For now I've just created the most basic version of the arrangement in a Console app as a learning exercise. I've got a sender class...
sender.h
#ifndef SENDER_H
#define SENDER_H
#include <QObject>
class sender : public QObject
{
Q_OBJECT
public:
sender(QObject *parent = 0);
~sender();
signals:
void output(int data);
public slots:
void test(int data);
private:
};
#endif // SENDER_H
sender.cpp
#include <iostream>
#include "sender.h"
sender::sender(QObject *parent)
: QObject(parent)
{
std::cout << "Created sender" << std::endl;
int stuff = 47;
std::cout << "stuff = " << stuff << std::endl;
connect(this, SIGNAL(output(int)), this, SLOT(test(int)));
emit output(stuff);
}
void sender::test(int data)
{
std::cout << "Got to test, data = " << data << std::endl;
}
sender::~sender()
{
std::cout << "Destroying sender" << std::endl;
}
...and a receiver class...
receiver.h
#ifndef RECEIVER_H
#define RECEIVER_H
#include <QObject>
class receiver : public QObject
{
Q_OBJECT
public:
receiver(QObject *parent = 0);
~receiver();
public slots:
void input (int data);
private:
};
#endif // RECEIVER_H
receiver.cpp
#include <iostream>
#include "receiver.h"
receiver::receiver(QObject *parent)
: QObject(parent)
{
std::cout << "Created receiver" << std::endl;
}
void receiver::input(int data)
{
std::cout << "Got data as = " << data << std::endl;
}
receiver::~receiver()
{
std::cout << "Destroying receiver" << std::endl;
}
My main looks like this...
main.cpp
#include <QtCore/QCoreApplication>
#include <iostream>
#include "sender.h"
#include "receiver.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
receiver myReceiver;
sender mySender;
if (QObject::connect(&mySender, SIGNAL(output(int)),
&myReceiver, SLOT(input(int))))
{
std::cout << "Got here so connect returned true" << std::endl;
}
return a.exec();
}
I've added the cout outputs and the sender::test function to try and figure out what's happening.
For me, this compiles cleanly and runs without any warnings or errors but while the sender::test SLOT gets called the receiver::input SLOT doesn't. The test on the connect in main returns true and neither sender or receiver are destroyed prematurely. Console output is...
Created receiver
Created sender
stuff = 47
Got to test, data = 47
Got here so connect returned true
So the SIGNAL is emitted, the SIGNAL and SLOT parameters match, I've got the Q_OBJECT macros in both sender.h and receiver.h, and both inherit from and #include QObject.
What's wrong???
P.S. I'm running 4.8.3 and IDE is VS2010 with Qt plugin.
The answer is quite simple: you are sending signal before you've connected it to the receiver and after you've connected it to itself. So your output is absolutely correct.
Do all emits only after everything has been connected. Here the instantiation of sender happens before sender and receiver are connected, and that's where the emit was done.
I derived a class from QTextEdit and use it as a "logbook". I equipped it with a slot to receive log-messages.
class CLogbook : public QTextEdit
{
Q_OBJECT;
public:
void log(QString msg) {append(msg)};
public slots:
void recvLogSignal(const QString message)
{
append("hallo");
std::cout << "signal received.\n";
log(message);
}
};
another class then emits a signal like this:
// in the header
signals:
void logMessage(const QString);
// in the implementation
emit logMessage("qt is cute");
std::cout << "if you can read this the logMessage was emitted\n";
and also i connect the signal to the slot
connect(tableeditor, SIGNAL(logMessage(const QString)), logbook, SLOT(recvLogSignal(const QString)));
However the message is never shown in the "logbook". What am i missing here?
SOLVED: The connect method was called after emitting the signal :-(
It is hard to see exactly what is wrong with your implementation without a full example. Sometimes signals or slots will fail if an object goes out of scope if it isn't initialized on the heap.
Another way that it could fail is if your QApplication hasn't reached the exec() call.
I haven't experimented with using const in signal and slot calls, and I haven't seen it in any examples before, so that could be causing the problem; but it seems to work fine in the example below.
Working Example With a Derived Class of QTextEdit
Here is a simple example I put together that does some basic logging with a push button and a line edit.
Here is the header:
#ifndef WIDGET_H
#define WIDGET_H
#include <QtGui/QWidget>
//#include <QTextEdit>
#include "clogbook.h"
#include <QLineEdit>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget() {}
public slots:
void on_pushButton();
void on_lineEditReturn();
private:
CLogBook * text_edit_log;
QLineEdit * line_edit;
};
#endif // WIDGET_H
Here is the source:
#include "widget.h"
#include <QBoxLayout>
#include <QPushButton>
#include <QTimer>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
QBoxLayout * box_layout = new QBoxLayout(QBoxLayout::TopToBottom);
text_edit_log = new CLogBook;
line_edit = new QLineEdit("Type Here and press Enter.");
QPushButton * push_button = new QPushButton("Click to Add To Log");
text_edit_log->setText("My Log Book");
box_layout->addWidget(text_edit_log);
box_layout->addWidget(line_edit);
box_layout->addWidget(push_button);
this->setLayout(box_layout);
QObject::connect(push_button, SIGNAL(clicked()), this, SLOT(on_pushButton()));
QObject::connect(line_edit, SIGNAL(returnPressed()), this, SLOT(on_lineEditReturn()));
}
void Widget::on_pushButton()
{
// text_edit_log->append("Push Button Logging Test");
text_edit_log->recvLogSignal("Push button test.");
}
void Widget::on_lineEditReturn()
{
// text_edit_log->append(line_edit->text());
text_edit_log->recvLogSignal(QString("LineEdit: ") + line_edit->text() );
line_edit->clear();
}
And here is the main:
#include <QtGui/QApplication>
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
And here is the CLogBook class:
#ifndef CLOGBOOK_H
#define CLOGBOOK_H
#include <QTextEdit>
#include <iostream>
class CLogBook : public QTextEdit
{
Q_OBJECT
public:
explicit CLogBook(QWidget *parent = 0) : QTextEdit(parent) { }
void log (QString msg) { append(msg); }
public slots:
void recvLogSignal(const QString message)
{
append("hallo");
std::cout << "signal received.\n" << std::endl;
log(message);
}
};
#endif // CLOGBOOK_H
I am trying to display and get the result a message box from outside of a QObject class. I seem to be able to generate the dialog like this:
#include <iostream>
#include <QApplication>
#include <QtConcurrentRun>
#include <QMessageBox>
class DialogHandler : public QObject
{
Q_OBJECT
signals:
void MySignal();
public:
DialogHandler()
{
connect( this, SIGNAL( MySignal() ), this, SLOT(MySlot()) );
}
void EmitSignal()
{
emit MySignal();
}
public slots:
void MySlot()
{
QMessageBox* dialog = new QMessageBox;
dialog->setText("Test Text");
dialog->exec();
int result = dialog->result();
if(result)
{
std::cout << "ok" << std::endl;
}
else
{
std::cout << "invalid" << std::endl;
}
}
};
#include "main.moc" // For CMake's automoc
void MyFunction(DialogHandler* dialogHandler)
{
dialogHandler->EmitSignal();
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
DialogHandler* dialogHandler = new DialogHandler;
MyFunction(dialogHandler);
return app.exec();
}
To get the result back in MyFunction, it seems to work to do simply pass an object to fill with the result like this:
#include <iostream>
#include <QApplication>
#include <QtConcurrentRun>
#include <QMessageBox>
class DialogHandler : public QObject
{
Q_OBJECT
signals:
void MySignal(int* returnValue);
public:
DialogHandler()
{
connect( this, SIGNAL( MySignal(int*) ), this, SLOT(MySlot(int*)), Qt::BlockingQueuedConnection );
}
void EmitSignal(int* returnValue)
{
emit MySignal(returnValue);
}
public slots:
void MySlot(int* returnValue)
{
std::cout << "input: " << *returnValue << std::endl;
QMessageBox* dialog = new QMessageBox;
dialog->addButton(QMessageBox::Yes);
dialog->addButton(QMessageBox::No);
dialog->setText("Test Text");
dialog->exec();
int result = dialog->result();
if(result == QMessageBox::Yes)
{
*returnValue = 1;
}
else
{
*returnValue = 0;
}
}
};
#include "main.moc" // For CMake's automoc
void MyFunction(DialogHandler* dialogHandler)
{
int returnValue = -1;
dialogHandler->EmitSignal(&returnValue);
std::cout << "returnValue: " << returnValue << std::endl;
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
DialogHandler* dialogHandler = new DialogHandler;
QtConcurrent::run(MyFunction, dialogHandler);
std::cout << "End" << std::endl;
return app.exec();
}
Does that seem reasonable? Is there a better way to do it?
This isn't possible quite like you have it, but with a bit of work it could be done. One option, of course, would be to convert your class to a QObject, at which point you could send signals. It doesn't help for the delay during exec, however. If that is necessary, you could have a messaging class that lives in the main UI thread, but can be called from other threads. The function called from other threads would need to lock, make a semaphore, and send an event to itself with the semaphore and message to be displayed. Then, in customEvent (which would be in the UI thread), you would create the message box, exec it, and trigger the semaphore after the message box is cleared.
Of course, things get a bit more complicated if you need to send information back the other way as well. Then you'll need a complete subsystem for your program, instead of just one basic class like I describe here.