I would like to handle keyboard events in command line application based on QCoreApplication class.
Following http://doc.qt.nokia.com/4.7/eventsandfilters.html I tried to reimplementing QCoreApplication::event(), but my code not works:
#include <QCoreApplication>
#include <QtGui/QKeyEvent>
class CoreApp : public QCoreApplication
{
Q_OBJECT
public:
explicit CoreApp(int & argc, char ** argv);
bool event(QEvent *event);
};
CoreApp::CoreApp(int & argc, char ** argv) :
QCoreApplication(argc,argv)
{
}
bool CoreApp::event(QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
if (ke->key() == Qt::Key_Q) {
qDebug("Quit?");
//qApp->quit();
return true;
}
}
return QCoreApplication::event(event);
}
int main(int argc, char *argv[])
{
CoreApp a(argc, argv);
return a.exec();
}
I've checked http://doc.qt.nokia.com/qq/qq11-events.html and didn't find solution.
How to handle these events properly?
Related
I'm following this document and I'm using qt to implement this event
#include <QCoreApplication>
#include <QDebug>
#include <libvirt/libvirt.h>
void
domainLifecycleCb(virConnectPtr conn,
virDomainPtr dom,
void * opaque)
{
qDebug() << "test";
}
int main(int argc, char *argv[])
{
virEventRegisterDefaultImpl();
QCoreApplication a(argc, argv);
virConnectPtr conn = virConnectOpen("qemu:///session");
virDomainPtr domain = virDomainLookupByName(conn, "Windows");
qDebug() << virConnectDomainEventRegisterAny(conn,
domain,
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(domainLifecycleCb),
NULL, NULL);
return a.exec();
}
I tried different methods but the event doesn't work when the domain gets shutdown or started.
By that I mean the callback function should get call when the domain life-cycle changes, And I'm determining that by showing an output in the callback function.
There is a function that needs to be called in a loop to keep the connection alive
#include <QCoreApplication>
#include <QDebug>
#include <libvirt/libvirt.h>
#include <QThread>
void domainLifecycleCb(virConnectPtr conn,
virDomainPtr dom,
void * opaque)
{
qDebug() << "test";
}
int main(int argc, char *argv[])
{
virEventRegisterDefaultImpl();
QCoreApplication a(argc, argv);
virConnectPtr conn = virConnectOpen("qemu:///session");
virDomainPtr domain = virDomainLookupByName(conn, "WindowsECO");
QThread *thread = QThread::create([]{
while (true) {
qDebug() << virEventRunDefaultImpl();
} });
thread->start();
qDebug() << virConnectDomainEventRegisterAny(conn,
domain,
VIR_DOMAIN_EVENT_ID_LIFECYCLE,
VIR_DOMAIN_EVENT_CALLBACK(domainLifecycleCb),
NULL, NULL);
return a.exec();
}
I need some virtual function/signal/event in a QApplication that centrally informs about any opened and closed window in the application (providing a pointer to the window object; including QMainWindow, QDialog, QWidget based windows).
This should work without manually registering all window instances and without manually manipulating each instance (e.g. by installing event filters or connections on each window object).
Also it should not be necessary to sub-class the tracked windows from some interface class or similar.
So, what is the best way in Qt to track all opened and closed windows in an application?
You must overwrite the notify method of QApplication(or QGuiApplication):
#include <QtWidgets>
class Application: public QApplication
{
public:
using QApplication::QApplication;
bool notify(QObject *receiver, QEvent *e) override
{
if(receiver->isWindowType()){
if(e->type() == QEvent::Show){
qDebug()<< receiver << "show";
}
else if (e->type() == QEvent::Close) {
qDebug()<< receiver << "close";
}
}
return QApplication::notify(receiver, e);
}
};
int main(int argc, char *argv[])
{
Application a(argc, argv);
QMainWindow m;
QDialog d;
QWidget w;
m.show();
d.show();
w.show();
return a.exec();
}
Update:
#include <QtWidgets>
class Application: public QApplication
{
public:
using QApplication::QApplication;
bool notify(QObject *receiver, QEvent *e) override
{
if(receiver->isWidgetType()){
QWidget *w = qobject_cast<QWidget *>(receiver);
if(w->isWindow()){
if(e->type() == QEvent::Show){
qDebug()<< w << "show";
}
else if (e->type() == QEvent::Close) {
qDebug()<< w << "close";
}
}
}
return QApplication::notify(receiver, e);
}
};
Is there a way to connect a signal before executing a default handler? I'm looking for a way to execute my function prior to QLineEdit::textChanged signal to execute notification about maximum length limit.
GTK+ has connect_before(), connect() and connect_after(). Is there something similar in Qt?
You can use the keyPressEvent method to issue the custom signal.
#include <QtWidgets>
class LineEdit: public QLineEdit
{
Q_OBJECT
public:
using QLineEdit::QLineEdit;
signals:
void maxLengthSignal();
protected:
void keyPressEvent(QKeyEvent *event) override{
if(!event->text().isEmpty() && maxLength() == text().length())
emit maxLengthSignal();
QLineEdit::keyPressEvent(event);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
LineEdit w;
QObject::connect(&w, &QLineEdit::textEdited, [](const QString & text){
qDebug()<< text;
});
QObject::connect(&w, &LineEdit::maxLengthSignal, [](){
qDebug()<< "maxLength signal";
});
w.setMaxLength(10);
w.show();
return a.exec();
}
#include "main.moc"
When calling QMetaMethod::invoke() on a method that contains default arguments, the invoke fails.
class MyClass : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE MyClass() : QObject(nullptr){}
public slots:
int MyMethod(int a = 0)
{
return a*2;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyClass* object = new MyClass();
QMetaObject *metaObject = object->metaObject();
for(int i=metaObject->methodOffset(); i<metaObject->methodCount(); i++)
{
if(metaObject->method(i).name() == "MyMethod")
{
int returnVal;
//returns false
metaObject->method(i).invoke(object,
Qt::DirectConnection,
Q_RETURN_ARG(int, returnVal));
break;
}
}
return a.exec();
}
If I pass an int as the first argument, then it runs fine. Is there any way to retrieve the default values of the arguments for the method so that way I can pass those instead of passing nothing?
I was about to manually store the defaults within the class for each method, but this is an ugly hack.
Thanks for your time.
If you review the generated .moc you see the following:
void MyClass::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
{
if (_c == QMetaObject::InvokeMetaMethod) {
MyClass *_t = static_cast<MyClass *>(_o);
Q_UNUSED(_t)
switch (_id) {
case 0: { int _r = _t->MyMethod((*reinterpret_cast< int(*)>(_a[1])));
if (_a[0]) *reinterpret_cast< int*>(_a[0]) = std::move(_r); } break;
case 1: { int _r = _t->MyMethod();
if (_a[0]) *reinterpret_cast< int*>(_a[0]) = std::move(_r); } break;
default: ;
}
}
}
As you can see there are 2 methods generated and that can be verified by printing the methods with that name:
#include <QCoreApplication>
#include <QMetaMethod>
#include <QDebug>
class MyClass: public QObject
{
Q_OBJECT
public:
using QObject::QObject;
public slots:
int MyMethod(int a = 0){ return a*2;}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyClass object;
const QMetaObject *metaObject = object.metaObject();
for(int i=metaObject->methodOffset(); i<metaObject->methodCount(); i++)
{
QMetaMethod method = metaObject->method(i);
if(method.name() == QByteArray("MyMethod"))
qDebug()<<i<<method.name();
};
return 0;
}
#include "main.moc"
Output:
5 "MyMethod"
6 "MyMethod"
So what sets them apart? The number of parameters, so you must add a filter that is the parameterCount().
#include <QCoreApplication>
#include <QMetaMethod>
#include <QDebug>
class MyClass: public QObject
{
Q_OBJECT
public:
using QObject::QObject;
public slots:
int MyMethod(int a = 0){ return a*2;}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyClass object;
const QMetaObject *metaObject = object.metaObject();
for(int i=metaObject->methodOffset(); i<metaObject->methodCount(); i++)
{
QMetaMethod method = metaObject->method(i);
if(method.name() == QByteArray("MyMethod") && method.parameterCount() == 0)
{
int returnVal;
bool status = method.invoke(&object,
Qt::DirectConnection,
Q_RETURN_ARG(int, returnVal));
Q_ASSERT(status);
qDebug()<<returnVal;
}
};
return 0;
}
#include "main.moc"
Output:
0
On the other hand if you want to avoid this kind of problems you can use QMetaObject::invokeMethod() that makes that verification:
MyClass object;
int returnVal;
bool status = QMetaObject::invokeMethod(&object,
"MyMethod",
Qt::DirectConnection,
Q_RETURN_ARG(int, returnVal));
Q_ASSERT(status);
qDebug()<<returnVal;
How does one disable tooltips on a Qt4 QToolBar?
Using QAction::setToolTip("") does nothing and I can't find any settings related to disabling tooltips on either a QAction or QToolbar!
Example:
Toolbar.h
#ifndef TOOLBAR_H
#define TOOLBAR_H
#include <QtGui>
class Toolbar : public QToolBar
{
Q_OBJECT
public:
Toolbar()
{
QAction *action = this->addAction("Action");
action->setToolTip("");
}
bool event(QEvent *event)
{
if(event->type() == QEvent::ToolTip)
{
qDebug() << "QEvent::ToolTip";
}
return QToolBar::event(event);
}
};
#include "moc_Toolbar.cpp"
#endif // TOOLBAR_H
main.cpp
#include <QtGui>
#include "Toolbar.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow window;
Toolbar *toolbar = new Toolbar;
window.addToolBar(toolbar);
window.setCentralWidget(new QWidget());
window.show();
return app.exec();
}
An event filter has to be used in this scenario.
Toolbar.h
#ifndef TOOLBAR_H
#define TOOLBAR_H
#include <QtGui>
class Toolbar : public QToolBar
{
Q_OBJECT
public:
Toolbar()
{
QAction *action = this->addAction("Action");
}
bool eventFilter(QObject *object, QEvent *event)
{
if(event->type() == QEvent::ToolTip)
{
return true;
}
return false;
}
};
#include "moc_Toolbar.cpp"
#endif // TOOLBAR_H
main.cpp
#include <QtGui>
#include "Toolbar.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow window;
Toolbar *toolbar = new Toolbar;
qApp->installEventFilter(toolbar);
window.addToolBar(toolbar);
window.setCentralWidget(new QWidget());
window.show();
return app.exec();
}
I'm not quite sure how to localize this to just the Toolbar but I don't like tooltips anyway so this is a quick way to disable all of them.