I am newbie, I am trying to emit signal from a header file and catch it in my main class. for this have written this header file :-
KeyBoard.h:-
#ifndef KEYBOARD_H
#define KEYBOARD_H
#include <QObject>
#include <QDebug>
class KeyBoard : public QObject{
Q_OBJECT
public:
KeyBoard();
int keyboard_update(QByteArray recieved_key);
signals:
void keyboard_respoense(QString message);
private:
int level;
int sub_level;
};
#endif
and
KeyBoard.cpp:-
#include "KeyBoard.h"
KeyBoard::KeyBoard()
{
level = 0;
sub_level = 0;
}
int KeyBoard::keyboard_update(QByteArray recieved_key)
{
qDebug() << "recieved key == " << recieved_key;
qDebug() << "button == " << recieved_key.at(8);
emit keyboard_respoense("PRESS ENTER TO SELECT TRAIN");
return 1;
}
In my main class, I am catching my signal like this:-
keyboard = new KeyBoard;
connect(keyboard,SIGNAL(keyboard_respoense(QString message)),this,SLOT(send_to_MBU(QString message)));
but when I call keyboard_update function using this line:-
keyboard->keyboard_update(raw_data_MBU_qb);
It enters in keyboard_update() function but never emits the signal, or may be it emits the signal but I am not able to catch it. So, please tell me what exactly I am missing here.
In connect function, no need to mention parameter names. just declare on argument type. Connect like this:-
connect(keyboard,SIGNAL(keyboard_respoense(QString)),this,SLOT(send_to_MBU(QString)));
To let compiler help you, please update to C++11 or more modern and write
connect(keyboard, &Keyboard::Keyboard_respoense, this, &SnakeCaseClass:send_to_MBU);
Related
I want to connect a signal which is created by a C++ QObject to a function in a QML item. The signal is the "activated" signal from a QSystemTrayIcon and its argument is ActivationReason (an enum value).
Unfortunately it seems I can't connect a signal with this signature to a slot which seems to only be able to receive QVariant.
In the QML file
function trayIconClicked(reason) { ... }
In the C++ code
QObject::connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), rootObject, SLOT(trayIconClicked(QVariant)));
And this is what I get
QObject::connect: Incompatible sender/receiver arguments
QSystemTrayIcon::activated(QSystemTrayIcon::ActivationReason) --> ApplicationWindow_QMLTYPE_11_QML_60::trayIconClicked(QVariant)
If I completely drop the argument on the slot side, the event calls the function. But then I have no idea what ActivationReason triggred it.
A full working version of the code above is here, except that I can't hand in the reason parameter https://github.com/sturmf/qt_samples/tree/master/trayicon
I now subclassed the QSystemTrayicon and added a slot which emits another signal without the parameter.
#ifndef TRAYICON_H
#define TRAYICON_H
#include <iostream>
#include <QObject>
#include <QSystemTrayIcon>
class TrayIcon : public QSystemTrayIcon
{
Q_OBJECT
public:
explicit TrayIcon(QObject *parent = 0) : QSystemTrayIcon(parent){}
signals:
void triggered();
public slots:
void trayIconActivated(QSystemTrayIcon::ActivationReason reason) {
std::cout << "activated" << std::endl;
if (reason == QSystemTrayIcon::Trigger) {
std::cout << "tiggered" << std::endl;
emit triggered();
}
}
};
#endif // TRAYICON_H
In Qt5 you can connect to an anonymous function, by the way.
QObject::connect(trayIcon
, SIGNAL(activated(QSystemTrayIcon::ActivationReason))
, [=](QSystemTrayIcon::ActivationReason r){
rootObject->trayIconClicked(r);
});
I am trying to subclass QEditLine so that I can define a new SIGNAL that sends an object identifier. At the moment, I connect a parent signal to a slot in the new class and from that slot I emits a proper new signal with the additional object identifier.
I cannot understand one thing. The problem is I don't know how to define a new signal function itself. I don't know what I should put there. I mean I know its arguments but I don't know what it shpould do as a function. I am doing this for the first time and it may looks very silly ;p but I really stuck there >.<.
Can anybody please provide some clues. It is probably a very easy problem.
Thanks
// myqeditline.h
#ifndef MYQEDITLINE_H
#define MYQEDITLINE_H
#include <QWidget>
#include <QLineEdit>
#include <QString>
class MyQEditLine : public QLineEdit
{
Q_OBJECT
public:
explicit MyQEditLine(const QString& n, QWidget *parent = 0);
protected:
QString name;
signals:
void textChanged(QString textCHanged, QString sender);
protected slots:
public slots:
void myTextChanged(QString textChanged);
};
#endif // MYQEDITLINE_H
// myqeditline.cpp
#include "myqeditline.h"
MyQEditLine::MyQEditLine(const QString &n, QWidget *parent)
: QLineEdit(parent),name(n) {
connect(this,SIGNAL(textChanged(QString)),this,SLOT(myTextChanged(QString)));
}
void MyQEditLine::myTextChanged(QString textChanged) {
emit textChanged(QString textChanged, QString name);
}
I just realised that the answer to my question is on this Qt Project website, in section regarding "Signals", in 4th paragraph. It says: "Signals are automatically generated by the moc and must not be implemented in the .cpp file. They can never have return types (i.e. use void)."
Updated-2
I have interesting combination of warnings & errors.
Firstly, when debugging, i get warnings:
can't find linker symbol for virtual table for `QFile' value
found `WebCore::JSDocument::JSDocument(JSC::Structure*, WebCore::JSDOMGlobalObject*, WTF::PassRefPtr<WebCore::Document>)' instead
RTTI symbol not found for class 'WebCore::JSHTMLDocument'
RTTI symbol not found for class 'WebCore::JSHTMLDocument'
RTTI symbol not found for class 'WebCore::JSHTMLDocument'
secondly, i have runtime error:
QIODevice::open: File access not specified
and momently
*** glibc detected *** <path>: double free or corruption (out): 0x081f9d00 ***
Here's the minimal code that causes that errors (i've minimized it):
Files
In result folder created folder "resources" and in it file "vk.cookie" (everything without quotes).
Bug.pro
QT += core gui webkit network xml
TARGET = Bug
TEMPLATE = app
SOURCES += main.cpp \
api_vk.cpp \
printer.cpp
HEADERS += \
api_vk.h \
printer.h
main.cpp
#include <QtGui/QApplication>
#include "api_vk.h"
#include "printer.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
API_VK *apivk = new API_VK;
apivk->authorise();
Printer *printer = new Printer;
QObject::connect(apivk, SIGNAL(authorisationSucceed()), printer, SLOT(printOK()));
QObject::connect(apivk, SIGNAL(authorisationFailed(QString,QString)), printer, SLOT(printFail()));
return a.exec(); }
api_vk.h
#ifndef API_VK_H
#define API_VK_H
#include <QObject>
#include <QTimer>
#include <QUrl>
#include <QtNetwork/QNetworkCookieJar>
class QWebView;
class QString;
class QNetworkReply;
class QXmlInputSource;
class QTimer;
class QNetworkCookie;
class API_VK : public QObject
{
Q_OBJECT
public:
explicit API_VK(QObject *parent = 0);
signals:
void authorisationFailed(QString error, QString error_description);
void authorisationSucceed();
public slots:
void authorise();
protected:
void readCookies();
void writeCookies();
protected slots:
void newAuthoriseRequest();
void processUrl(QUrl url);
private:
static const QString app_id;
static QString access_token;
static qint32 expires_in;
QWebView *messagesPage;
QList<QNetworkCookie> cookies;
QNetworkCookieJar jar;
static bool authorised;
};
#endif
api_vk.cpp
#include "api_vk.h"
#include <QtGui>
#include <QWebView>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkCookie>
#include <QtNetwork/QNetworkCookieJar>
#include <QString>
#include <QStringList>
#include <QFile>
#include <QTextStream>
#include <QTimer>
#include <QUrl>
#include <QtXml>
#include <QVariant>
#include <QDateTime>
#include <QDebug>
bool API_VK::authorised = false;
const QString API_VK::app_id = "2783286";
QString API_VK::access_token = "";
int API_VK::expires_in = 0;
// defining class methods
API_VK::API_VK(QObject *parent) :
QObject(parent)
{
}
void API_VK::authorise() {
newAuthoriseRequest(); // 1. going here
}
void API_VK::newAuthoriseRequest() {
// gets new access_token
// 2. going here
messagesPage = new QWebView;
readCookies();
jar.setCookiesFromUrl(cookies, QUrl("http://vk.com"));
messagesPage->page()->networkAccessManager()->setCookieJar(&jar);
QUrl url("http://oauth.vk.com/authorize");
url.addQueryItem("client_id", app_id);
url.addQueryItem("scope", "messages");
url.addQueryItem("redirect_uri","http://api.vk.com/blank.html");
url.addQueryItem("display","page");
url.addQueryItem("response_type","token");
messagesPage->load(QNetworkRequest(url));
connect(messagesPage, SIGNAL(urlChanged(QUrl)), this, SLOT(processUrl(QUrl)));
messagesPage->show();
}
void API_VK::processUrl(QUrl url) { // 3. going here
/* firstly we're here when oath.vk.com redirects us to api.vk.com/login...
* in this case we're exiting at 4.
* secondly, user logs in, and api.vk.com/login redirects us back to oath.vk.com,
* where we get access_token, etc
* and when debugging, we start receiving warnings about "can't find linker symbol" secondly, not firstly
*/
// if (!url.hasQueryItem("access_token"))
// return;
/* I commented previous part because most of you doesn't have VK accounts so you can't go
* to the next part of code */
access_token = url.queryItemValue("access_token");
expires_in = url.queryItemValue("expires_in").toInt();
emit authorisationSucceed();
authorised = true;
cookies = messagesPage->page()->networkAccessManager()->cookieJar()->cookiesForUrl(QUrl("http://vk.com"));
messagesPage->deleteLater();
writeCookies();
}
void API_VK::readCookies() {
QFile file("./resouces/vk.cookie");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return;
}
QTextStream in(&file);
QByteArray name, value;
while (!in.atEnd()) {
in >> name >> value;
cookies.append(QNetworkCookie(name, value));
}
}
void API_VK::writeCookies() {
QFile file("./resouces/vk.cookie"); // note: this file exists
if (!file.open(QIODevice::Truncate | QIODevice::Text)) { // 5. at this line i receive runtime errors
return;
}
QTextStream out(&file);
for (QList<QNetworkCookie>::const_iterator i = cookies.begin(); i != cookies.end(); ++i) {
out << (*i).name() << ' ' << (*i).value() << '\n';
}
}
printer.h
#ifndef PRINTER_H
#define PRINTER_H
#include <QObject>
#include <QDebug>
struct Printer: public QObject {
Q_OBJECT
public slots:
void printOK() { qDebug() << "OK"; }
void printFail() { qDebug() << "Fail"; }
};
#endif // PRINTER_H
printer.cpp
#include "printer.h"
Here's the full output with memory dump: http://pastebin.com/btVNe4nd
At 5 QtCreator says that app received signal from OS (signal: SIGABRT) and decompiles
Disassembler (__kernel_vsyscall)
0x132414 <+0x0000> int $0x80
0x132416 <+0x0002> ret
And valgrind says:
Analysis of memory <path>
QMetaObject::connectSlotsByName: No matching signal for on_cancelButton_clicked()
"sni-qt/23102" WARN 20:28:53.697 void StatusNotifierItemFactory::connectToSnw() Invalid interface to SNW_SERVICE
** Analysis finished **
** Unknown error **
And one more thing. When I added qDebug() output after each line of code in writeCookies() and launched the program in Run (not debug) mode, it have printed all this output. So, the problem is in some Qt class destructor. (code with qDebug output)
So, why I receive that errors?
Your problem is in the line
messagesPage->page()->networkAccessManager()->setCookieJar(&jar);
The documentation for setCookieJar() states:
Note: QNetworkAccessManager takes ownership of the cookieJar object.
That means that when the QNetworkAccessManager gets destroyed, it will execute the following code:
delete cookieJar;
Note that when this happens:
The stack-allocated jar you passed to setCookieJar is long gone. The network manager was likely corrupting things by accessing a destroyed cookie jar -- it got destroyed as soon as newAuthoriseRequest() had exited. Remember that network manager can run some of its functionality in a separate thread.
A deletion is attempted on an object that was not allocated directly on the heap via new.
Simply change the declaration to
QPointer<QNetworkCookieJar> jar;
and allocate a new cookie jar whenever you create a new QWebView.
The use of QPointer will protect you from trying to use a dangling pointer to a cookie jar that got deleted by QWebView's network access manager. If, by mistake, you try to use it, the pointer will be already reset to zero, and you'll get an instant segfault at the line where you try to dereference the pointer. That's easy to debug.
Your major mistake was stopping to further minimize your self-contained example. If you kept at it, you'd have found the problem in the next 10-15 minutes tops.
This is a minimal example that reproduces your problem:
#include <QtGui/QApplication>
#include <QtWebKit/QWebView>
#include <QtNetwork/QNetworkCookieJar>
#include <QtCore/QList>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QWebView * view = new QWebView();
QNetworkCookieJar jar;
QList<QNetworkCookie> cookies;
jar.setCookiesFromUrl(cookies, QUrl("http://google.com"));
view->page()->networkAccessManager()->setCookieJar(&jar);
view->load(QUrl("http://www.google.com"));
view->show();
view->connect(view, SIGNAL(loadFinished(bool)), SLOT(deleteLater()));
a.exec();
}
Homework: read up on QPointer, QScopedPointer, QSharedPointer and QWeakPointer. They are very useful, and in most cases you'll find that use of naked pointers as class members in your code is a bug waiting to happen, with exception of child QObjects (such as QWidgets) whose lifetime matches the lifetime of their parent (i.e. they die only when the parent dies).
Class with the information that should trigger the the search then display of the other classes after connecting using signal and slots:
#include "recruitsearch.h"
#include "ui_recruitsearch.h"
#include <cctype>
#include <QtGui>
#include <string>
#include <QtCore>
using namespace std;
RecruitSearch::RecruitSearch(QWidget *parent) :
QDialog(parent),
ui(new Ui::RecruitSearch)
{
ui->setupUi(this);
}
RecruitSearch::~RecruitSearch()
{
delete ui;
}
void RecruitSearch::on_pushButton_clicked()
{
//if(EmployerSearch::ui->buttonBox->clicked();
if(ui->rfrId->text().isEmpty() || ui->rfrId->text().isNull() || (is_Digit(ui->rfrId->text().toStdString())==false) ){
QMessageBox::warning(this,"Error", "Please enter a valid RFR id(digits only)");
}
else{
accepted();
this->close();
}
}
int RecruitSearch:: getRfrId(){
return ui->rfrId->text().toInt();
}
bool RecruitSearch::is_Digit( string input){
for (int i = 0; i < input.length(); i++) {
if (!std::isdigit(input[i]))
return false;
}
return true;
}
Class with the display. How would I connect the two slots and use the id from the a first form to search a linkedlist then display results using another form:
#include "rfrform.h"
#include "ui_rfrform.h"
#include <cctype>
#include <string>
#include <QString>
#include <QtGui>
#include <QtCore>
#include <iostream>
using namespace std;
RfrForm::RfrForm(QWidget *parent) :
QDialog(parent),
ui(new Ui::RfrForm)
{
ui->setupUi(this);
}
RfrForm::~RfrForm()
{
delete ui;
}
void RfrForm::setEmpName(string name){
QString qstr=QString::fromStdString(name);
ui->EmployerName->setText(qstr);
}
void RfrForm::setAOE(string aoe){
QString qstr=QString::fromStdString(aoe);
ui->AOE->setText(qstr);
}
void RfrForm::setEmpId(int id){
QString qstr=QString::number(id);
ui->EmpId->setText(qstr);
}// end of setId
void RfrForm::setNumOfPos(int num){
QString qstr=QString::number(num);
ui->numOfPos->setText(qstr);
}
void RfrForm::setGender(string gen){
QString qstr=QString::fromStdString(gen);
ui->gender->setText(qstr);
}
void RfrForm::setMaxRecruits(int max){
QString qstr=QString::number(max);
ui->MaxRecruits->setText(qstr);
}
void RfrForm::display(RFR *temp){
this->show();
}
Think of signals and slots in Qt as simply callbacks. For instance, a standard signal/slot may look as follows:
....
QAction* act = new QAction(this);
connect(act, SIGNAL(triggered()), this, SLOT(handleAct()));
....
Note that the first parameter is a pointer to the object which will emit the signal (thus, the signal method, triggered in this case, must be associated with our sender, in this case QAction) and the second parameter is the signal function signature. Similarly, the last two arguments are the pointer for the slot (i.e. the event handler, in this case, the current class) and the function signature for some handler function.
This is for some class which looks like this (note the Q_OBJECT macro)
class TestMe
{
Q_OBJECT
public:
...
protected slots:
void handleAct();
};
Where the handleAct() method is some arbitrary function you design. Now, to answer your question more specifically, we will need more detail on exactly which type of QWidget you are using (i.e. so we know which signals it emits). In any case, the basic idea is to catch a particular type of symbol from a particular element, and then handle the information accordingly.
Sometimes, to do a type of information transfer you are looking for, you may need to hold particular pointers to objects as class members so you can easily get a the information in the corresponding QWidget (generally a text() method or similar).
It is also important to notice, however, that you can override QWidget types and created custom signals and slots. So if you have a custom signal which returns an id and a signal which takes an id value as input, you can connect these signals and slots (look into the emit functionality)
If you provide some more specific information about the QWidget you are using, we may be able to provide you a more specific solution.
I have subclassed QComboBox to customize it for special needs. The subclass is used to promote QComboBoxes in a ui file from QtDesigner. Everything works except that when I put a break point in a slot, the program does not stop at the breakpoint. I do however know that it is being called from the result it generates. I checked other slots in my program and they work fine with breakpoints. Doing a clean and rebuild all did not fix it. What could be causing this and is there anything I can do about it? The slot in question is the only one in the subclass and is called "do_indexChanged()". You can find the slot on line 37 of the class header below and the signal-slot connection on line 10 of the class source file.
CLASS HEADER:
#ifndef WVQCOMBOBOX_H
#define WVQCOMBOBOX_H
#include <QWidget>
#include <QObject>
#include <QComboBox>
#include <QVariant>
class wvQComboBox : public QComboBox
{
Q_OBJECT
//Q_PROPERTY(bool writeEnable READ writeEnable WRITE setWriteEnable)
public:
explicit wvQComboBox(QWidget *parent = 0);
bool writeEnable() {
return this->property("writeEnable").toBool();
}
void setWriteEnable(const bool & writeEnable){
this->setProperty("writeEnable",writeEnable);
}
bool newValReady() {
return this->property("newValReady").toBool();
}
void setNewValReady(const bool & newValReady){
this->setProperty("newValReady",newValReady);
}
QString getNewVal();
int getNewValIndex();
int oldVal; //comboBox Index before user edit began
private slots:
void do_indexChanged(){
this->setWriteEnable(true);
if(oldVal!=currentIndex()){
this->setNewValReady(true);
oldVal=currentIndex();
}
}
protected:
void focusInEvent ( QFocusEvent * event );
//void focusOutEvent ( QFocusEvent * event );//dont need because of currentIndexChanged(int)
};
#endif // WVQCOMBOBOX_H
#include "wvqcombobox.h"
wvQComboBox::wvQComboBox(QWidget *parent) :
QComboBox(parent)
{
this->setWriteEnable(true);
this->setNewValReady(false);
oldVal=this->currentIndex();
connect(this,SIGNAL(currentIndexChanged(int)),this,SLOT(do_indexChanged()));
}
void wvQComboBox::focusInEvent ( QFocusEvent * event ) {
this->setWriteEnable(false);
oldVal=this->currentIndex();
}
QString wvQComboBox::getNewVal(){
setNewValReady(false);
return this->currentText();
}
int wvQComboBox::getNewValIndex(){
setNewValReady(false);
return this->currentIndex();
}
This is most likely due to the fact that that file was not compilled with debug info, therefore the debugger won't be able to break there. Try linking your app to a debug version of libQtGui*.so/.dylib/.dll
I found the problem. All I needed to do was to put the function definition in the .cpp file.