How to synthesize key press events? - c++

I am able to get key value's from HAL through a call back function in Qt. Created event for that key by
QKeyEvent *event = new QKeyEvent (QEvent::KeyPress,
inputKey.keyValue,
Qt::NoModifier);
Note: inputKey.keyValue Key value received from HAL Layer.
Now I need to Register This key event in Qt, So that if any key press happened in IR Remote then in respective form, keyPressEvent(e) or event(e) will get invoke. and based on the key press, specific action will get execute.
Note: More than one form is there, where key press event will trigger And more than one keys are there "Page_Up, Page_Down, Ok Key etc....."
tried to invoke Postevent() and connect(.......) but nothing helped me. KeyPressEvent() is not getting executed.

E.g. like this:
// receiver is a pointer to QObject
QCoreApplication::postEvent (receiver, event);
You can find more info here.
You can reimplement QObject::event() or QWidget::keyPressEvent in your widget to receive key events.
Visit this link or link for more information. See the example code below which consists of two buttons and a label. Clicking pushButton sends 'enter pressed' and pushButton_2 sends 'letter A pressed'. Key events are received in the event() function and label is updated accordingly.
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(sendKeyEvent()));
connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(sendKeyEvent()));
}
void MainWindow::sendKeyEvent()
{
QObject* button = QObject::sender();
if (button == ui->pushButton)
{
QKeyEvent *event = new QKeyEvent (QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
QCoreApplication::postEvent (this, event);
}
else if (button == ui->pushButton_2)
{
QKeyEvent *event = new QKeyEvent (QEvent::KeyPress, Qt::Key_A, Qt::NoModifier);
QCoreApplication::postEvent (this, event);
}
}
bool MainWindow::event(QEvent *event)
{
if (event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Enter) {
ui->label->setText("Enter received");
return true;
}
else if (keyEvent->key() == Qt::Key_A)
{
ui->label->setText("A received");
return true;
}
}
return QWidget::event(event);
}

You can create the event on the stack. Then use QCoreApplication::sendEvent to have the event immediately delivered:
QWidget w1, w2;
QKeyEvent event(QEvent::KeyPress, inputKey.keyValue, Qt::NoModifier);
QApplication::sendEvent(&w1, &ev);
QApplication::sendEvent(&w2, &ev);
Each sendEvent will call the widget's event method, that will then invoke the xxxxEvent protected methods as applicable. But don't do it yourself, as you then bypass the application-global event filters and depend on implementation details.
// WRONG!
w1.event(&ev);
// WRONG and won't compile since keyPressEvent is protected
w2.keyPressEvent(&ev);
Or, you can create it on the heap. Qt is managing the event's lifetime as soon as you post it. After you post, the event is not yours anymore and you can't reuse it. You must create multiple events for each post. The simplest way to avoid repetition is to create a local function that produces the events on demand.
QWidget w1, w2;
auto ev = [=]{ return new QKeyEvent(QEvent::KeyPress, inputKey.keyValue, Qt::NoModifier); };
QApplication::postEvent(&w1, ev());
QApplication::postEvent(&w2, ev());
The events will be added to the main thread's event queue. Once the control returns to QApplication::exec, they will be delivered to the widgets one-by-one. The widgets' event method will be called from QApplication::exec, not from postEvent.
The QWidget::event implementation decodes the event types and invokes the protected convenience handlers, such as keyPressEvent, enterEvent, etc. Its implementation follows the following pattern:
bool QWidget::event(QEvent * ev) {
switch (ev->type()) {
case QEvent::KeyPress:
keyPressEvent(static_cast<QKeyEvent*>(ev));
return true;
case QEvent::Enter:
enterEvent(static_cast<QEnterEvent*>(ev));
return true;
...
}
return QObject::event(ev);
}
When implementing handlers for event types that have such xxxxEvent convenience virtual methods, you should reimplement the virtual method, and not the event() itself. Thus your MainWindow should reimplement keyPressEvent:
void MainWindow::keyPressEvent(QKeyEvent * event) {
if (event->key() == Qt::Key_Enter)
ui->label->setText("Enter received");
else if (event->key() == Qt::Key_A)
ui->label->setText("A received");
QMainWindow::keyPressEvent(event);
}
If you wish your key events to be delivered to your window immediately, and that seems to be a reasonable approach, your sendKeyEvent method becomes much simpler:
void MainWindow::sendKeyEvent()
{
if (sender() == ui->pushButton) {
QKeyEvent event(QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier);
QApplication::sendEvent(this, &event);
}
else if (sender() == ui->pushButton_2) {
QKeyEvent event(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier);
QApplication::sendEvent(this, &event);
}
}
There is a way to simplify things further, though. Recall that the QObject supports dynamic properties. You can thus easily assign the keys as a property of the buttons, and automatically send the event whenever a button with a key property has been pressed:
static const char keyPropKey[] = "key";
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::sendKeyEvent);
connect(ui->pushButton_2, &QPushButton::clicked, this, &MainWindow::sendKeyEvent);
ui->pushButton.setProperty(keyPropKey, (int)Qt::Key_Enter);
ui->pushButton.setProperty(keyPropKey, (int)Qt::Key_A);
}
void MainWindow::sendKeyEvent()
{
auto key = sender().property(KeyPropKey);
if (key.isValid()) {
QKeyEvent event(QEvent::KeyPress, key.toInt(), Qt::NoModifier);
QApplication::sendEvent(this, &event);
}
}
Finally, as a stylistic nitpick: there's no reason to have the ui member be a pointer. You'll avoid one heap allocation, and plenty of indirections, by using it as a direct member.

Related

Qt: transforming touch to mouse inside eventfilter on complex widgets

I'm working on a way of creating QWidgets that respond to touch, running as a plugin to a proprietary Qt 5.2 application. The application provides touch and gesture events (QTouchEvent, QGestureEvent), but no mouse events.
I have no control over the application itself, apart from what can be done at runtime, and I'm trying to be as minimally invasive as I can.
EDIT: To clarify the above paragraph, my code is being loaded automatically by Qt as a 'fake' image plugin. The host application appears to not have set Qt::AA_SynthesizeMouseForUnhandledTouchEvents, and when I tried to do it... things did not go well. The application has it's own set of touch and gesture handlers and Widgets it uses.
One option is to subclass each QWidget type and add custom event handling for touch events. I would rather not do this, however, as it would be tedious, and I don't really need advanced touch/gesture functionality for the most part.
Another option, which I've been trialing is to install an eventFilter on the widgets, which creates mouse events from the touch events, and sends the mouse event to the widget instead. This is working quite well for many simpler widgets, and even complex widgets like QFileDialog mostly work.
My problem comes with certain widget types (I've come across two so far), which either partially work, or don't work at all, and I'm not sure where I'm going wrong.
An example of a partially working widget with the eventFilter technique is the QComboBox. The combo box itself responds to the touch, and opens the dropdown list. However, the dropdown list itself just doesn't seem to work with the touch.
QDialogButtonBox is the most recent widget I've discovered that doesn't work. The eventFilter seems to trigger on the QDialogButtonBox itself, but not the button(s) for some reason.
Here are the relevant bits of the current (very) WIP experimental code:
From NDBWidgets.h
void setTouchFilter(QWidget *w);
class TouchFilter : public QObject
{
Q_OBJECT
public:
TouchFilter(QWidget* parent = nullptr);
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
};
And from NDBWidgets.cc
static void installTouchFilter(QWidget *w)
{
if (!w->property(touchFilterSet).isValid()) {
w->setProperty(touchFilterSet, QVariant(true));
w->setAttribute(Qt::WA_AcceptTouchEvents);
auto ef = new TouchFilter(w);
w->installEventFilter(ef);
}
}
void setTouchFilter(QWidget *w)
{
if (!w) {
return;
}
auto children = w->children();
nh_log("installing eventFilter on the following children:");
for (int i = 0; i < children.size(); ++i) {
if (auto wi = qobject_cast<QWidget*>(children.at(i))) {
nh_log(" Class: %s Name: %s", children.at(i)->metaObject()->className(), children.at(i)->objectName().toUtf8().constData());
installTouchFilter(wi);
// if (auto cb = qobject_cast<QComboBox*>(wi)) {
// setTouchFilter(cb->view());
// }
}
}
installTouchFilter(w);
}
TouchFilter::TouchFilter(QWidget *parent) : QObject(parent) {}
bool TouchFilter::eventFilter(QObject *obj, QEvent *event)
{
// Only care about widgets...
auto widget = qobject_cast<QWidget*>(obj);
if (!widget) {
return false;
}
auto type = event->type();
if (type == QEvent::TouchBegin || type == QEvent::TouchUpdate || type == QEvent::TouchEnd) {
event->accept();
auto tp = static_cast<QTouchEvent*>(event)->touchPoints().at(0);
nh_log("eventFilter triggered for class: %s name: %s", widget->metaObject()->className(), widget->objectName().toUtf8().constData());
if (type == QEvent::TouchBegin) {
nh_log("event TouchBegin captured");
QMouseEvent md(QEvent::MouseButtonPress, tp.pos(), tp.screenPos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QCoreApplication::sendEvent(widget, &md);
} else if (type == QEvent::TouchUpdate) {
nh_log("event TouchUpdate captured");
QMouseEvent mm(QEvent::MouseMove, tp.pos(), tp.screenPos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QCoreApplication::sendEvent(widget, &mm);
} else if (type == QEvent::TouchEnd) {
nh_log("event TouchEnd captured");
QMouseEvent mu(QEvent::MouseButtonRelease, tp.pos(), tp.screenPos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QCoreApplication::sendEvent(widget, &mu);
}
return true;
}
return false;
}
An example usage:
void NDBDbus::dlgComboBox() {
NDB_DBUS_USB_ASSERT((void) 0);
auto d = new QDialog();
d->setAttribute(Qt::WA_DeleteOnClose);
auto vl = new QVBoxLayout();
auto cb = new QComboBox(d);
cb->addItem("Item 1", QVariant(1));
cb->addItem("Item 2", QVariant(2));
vl->addWidget(cb);
auto bb = new QDialogButtonBox(QDialogButtonBox::Close, d);
connect(bb, &QDialogButtonBox::rejected, d, &QDialog::reject);
vl->addWidget(bb);
d->setLayout(vl);
setTouchFilter(d);
d->open();
}
I'm still very new to Qt event handling, and eventFilters, and I've gotten to the point where I'm rather stumped, so if anyone has any suggestions or ideas, I would very much appreciate them!
So, TLDR, and the final question: Is it possible to transform touch events to mouse events inside an eventFilter for widgets such as QComboBox or QDialogButtonBox? And if so, how?

How to send key to parent mainWindow from dialog in QT C++

I need a virtual keyboard for an embedded linux application (not QML). I couldn't find a better way, so now I am trying to create one. I want a dialog full of buttons that sends keys to parent mainWindow. It runs without errors, but happens nothing in lineEdit.
keyboard.cpp
Keyboard::Keyboard(QWidget *parent) :
QDialog(parent),
ui(new Ui::Keyboard)
{
ui->setupUi(this);
mainWindow = this->parent();
}
void Keyboard::on_btnA_clicked()
{
qDebug() << "Test1";
QKeyEvent event(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier);
qDebug() << "Test2";
QApplication::sendEvent(mainWindow, &event);
qDebug() << "Test3";
}
And in mainWindow.cpp to open keyboard dialog:
keyboard->show();
ui->lineEdit->setFocus();
What is the problem? Thanks in advance.
Several things:
Sending the event to mainWindow requires mainWindow to handle passing the event to the QLineEdit object, without seeing the rest of the code I can't say if this is being done or not; the alternative is sending directly to the QLineEdit like this:
QApplication::sendEvent(lineEdit, &event);
The QKeyEvent constructor also requires a fourth parameter - the string to send, in the example case an "a".
QKeyEvent event(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier);
should be
QKeyEvent event(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "a");
to send an "a".
Depending on the exact implementation you may also need to send a QEvent::KeyRelease after the QEvent::KeyPress, i.e.
QKeyEvent event1(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "b");
QKeyEvent event2(QEvent::KeyRelease, Qt::Key_A, Qt::NoModifier);
QApplication::sendEvent(edit, &event1);
QApplication::sendEvent(edit, &event2);
As (2) indicates, the key enumeration (i.e. Qt::Key_A) does not send an "a" as you would expect, the string that is sent is instead determined by the fourth parameter in the QKeyEvent constructor, i.e.
QKeyEvent event(QEvent::KeyPress, Qt::Key_A, Qt::NoModifier, "a");
QApplication::sendEvent(lineEdit, &event);
Is equivalent to
QKeyEvent event(QEvent::KeyPress, Qt::Key_B, Qt::NoModifier, "a");
QApplication::sendEvent(lineEdit, &event);
Using QKeyEvent in this manner will probably lead so some unpleasantness in handling backspaces and deletes. It is probably more elegant to simply append the desired character to the QLineEdit text,
lineEdit->setText(lineEdit->text().append("a"));
and use QLineEdit::backspace() and QLineEdit::delete() to handle backspace and delete keys.
Example
#include <QtWidgets/QApplication>
#include <qwidget.h>
#include <qmainwindow.h>
#include <qlineedit.h>
#include <qboxlayout.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow* main = new QMainWindow;
QWidget* central = new QWidget();
QBoxLayout* layout = new QBoxLayout(QBoxLayout::LeftToRight);
central->setLayout(layout);
QLineEdit* edit = new QLineEdit(central);
edit->setAlignment(Qt::AlignCenter);
layout->addWidget(edit);
edit->setText("sometext");
edit->backspace();
edit->setText(edit->text().append("a"));
main->setCentralWidget(central);
main->resize(600, 400);
main->show();
return a.exec();
}

A lot of widgets seems to have default behavior for the space bar key press event. How can I override this without subclassing every widget?

I have a very specific piece of code that needs to be executed instantly, no matter what else is going on in the gui, when the space bar is pressed. I have the following snippet of code in each of my keypress event filters:
else if(keyPressed == Qt::Key_Space){
emit sigHalted();
}
This works fine, unless certain widgets have focus. The ones causing me issues are:
QTableWidget
QPushButton
If I'm editing an in a QTableWidget, and I hit space bar, then it adds a space bar to the item in the QTableWidget instead of executing the code above. If I click a button with the mouse, and then hit space bar, it acts as if I clicked that same button again instead of executing the code above.
I know I can fix this behavior by subclassing the widgets and overriding their event filters, but I would prefer to avoid this, because I have a lot of buttons and tables and I would have to go through and replace all of them with the new, subclassed versions. Is there a way I can catch the space bar keypress event before it goes to the widget's default behavior?
You must use eventFilter.
Enable the event:
code:
#include <QApplication>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
qApp->installEventFilter(this);
}
Declare the function:
code:
bool eventFilter(QObject *watched, QEvent *event);
Override the function:
code:
bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::KeyPress){
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Escape){
//your code here
emit sigHalted();
return true;
}
else{
return false;
}
}
else
return QMainWindow::eventFilter(watched,event);
}

My Qt eventFilter() doesn't stop events as it should

Something is fundamentally wrong with my eventFilter, as it lets every single event through, while I want to stop everything. I've read lots of documentation on QEvent, eventFilter() and so on, but obviously I'm missing something big. Essentially, I'm trying to create my own modal-functionality for my popup-window class based on QDialog. I want to implement my own since the built-in setModal(true) includes a lot of features, e.g. playing QApplication::Beep(), that I want to exclude. Basically, I want to discard all events going to the QWidget (window) that created my popup. What I have so far is,
// popupdialog.h
#ifndef POPUPDIALOG_H
#define POPUPDIALOG_H
#include <QDialog>
#include <QString>
namespace Ui {class PopupDialog;}
class PopupDialog : public QDialog
{
Q_OBJECT
public:
explicit PopupDialog(QWidget *window=0, QString messageText="");
~PopupDialog();
private:
Ui::PopupDialog *ui;
QString messageText;
QWidget window; // the window that caused/created the popup
void mouseReleaseEvent(QMouseEvent*); // popup closes when clicked on
bool eventFilter(QObject *, QEvent*);
};
...
// popupdialog.cpp
#include "popupdialog.h"
#include "ui_popupdialog.h"
PopupDialog::PopupDialog(QWidget *window, QString messageText) :
QDialog(NULL), // parentless
ui(new Ui::PopupDialog),
messageText(messageText),
window(window)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose, true); // Prevents memory leak
setWindowFlags(Qt::Window | Qt::FramelessWindowHint);
ui->message_text_display->setText(messageText);
window->installEventFilter(this);
//this->installEventFilter(window); // tried this also, just to be sure ..
}
PopupDialog::~PopupDialog()
{
window->removeEventFilter(this);
delete ui;
}
// popup closes when clicked on
void PopupDialog::mouseReleaseEvent(QMouseEvent *e)
{
close();
}
Here's the problem, the filter doesn't work. Note that if I write a std::cout
inside the if(...), I see that it does trigger whenever events are sent to window, it just doesn't stop them.
bool PopupDialog::eventFilter(QObject *obj, QEvent *e)
{
if( obj == window )
return true; //should discard the signal (?)
else
return false; // I tried setting this to 'true' also without success
}
When the user interacts with the main program, a PopupDialog can be created like this:
PopupDialog *popup_msg = new PopupDialog(ptr_to_source_window, "some text message");
popup_msg->show();
// I understand that naming the source 'window' might be a little confusing.
// I apologise for that. The source can in fact be any 'QWidget'.
Everything else works as expected. Only the event filter fails. I want the filter to remove events sent to the window that created the popup; like mouse clicking and key pressing, until the popup is closed. I'm expecting to be extremely embarrassed when someone points out a trivial fix in my code.
You have to ignore all events that arrive in the widget tree of the window. Therefore, you need to install the eventFilter application-wide and check, if the object you are filtering on is a descendant of window. In other words: Replace
window->installEventFilter(this);
by
QCoreApplication::instance()->installEventFilter(this);
and implement the event filter function this way:
bool PopupDialog::eventFilter(QObject *obj, QEvent *e)
{
if ( !dynamic_cast<QInputEvent*>( event ) )
return false;
while ( obj != NULL )
{
if( obj == window )
return true;
obj = obj->parent();
}
return false;
}
I tried it, tested it and it worked for me.
Note: Using event filters in Qt is a bit messy in my experience, since it is not quite transparent what is happening. Expect bugs to pop up from time to time. You may consider disabling the main window instead, if you and your clients don't have a problem with the grayed-out main window as a consequence.
After the massive amount of responses, feedback, suggestions and time ivested in extensive research I've finally found what I believe to be the optimal, and safest solution. I wish to express my sincere gratidtude to everyone for their aid to what Kuba Ober describes as "(...) not as simple of a problem as you think".
We want to filter out all certain events from a widget, including its children. This is difficult, because events may be caught in the childrens default eventfilters and responded to, before they are caught and filtered by the the parent's custom filter for which the programmer implements. The following code solves this problem by installing the filter on all children upon their creation. This example assumes the use of Qt Creator UI-forms and is based on the following blog post: How to install eventfilters for all children.
// The widget class (based on QMainWindow, but could be anything) for
// which you want to install the event filter on, includings its children
class WidgetClassToBeFiltered : public QMainWindow
{
Q_OBJECT
public:
explicit WidgetClassToBeFiltered(QWidget *parent = 0);
~WidgetClassToBeFiltered();
private:
bool eventFilter(QObject*, QEvent*);
Ui::WidgetClassToBeFiltered *ui;
};
...
WidgetClassToBeFiltered::WidgetClassToBeFiltered(QWidget *parent) :
QMainWindow(parent), // Base Class constructor
ui(new Ui::WidgetClassToBeFiltered)
{
installEventFilter(this); // install filter BEFORE setupUI.
ui->setupUi(this);
}
...
bool WidgetClassToBeFiltered::eventFilter(QObject *obj, QEvent* e)
{
if( e->type() == QEvent::ChildAdded ) // install eventfilter on children
{
QChildEvent *ce = static_cast<QChildEvent*>(e);
ce->child()->installEventFilter(this);
}
else if( e->type() == QEvent::ChildRemoved ) // remove eventfilter from children
{
QChildEvent *ce = static_cast<QChildEvent*>(e);
ce->child()->removeEventFilter(this);
}
else if( (e->type() == QEvent::MouseButtonRelease) ) // e.g. filter out Mouse Buttons Relases
{
// do whatever ..
return true; // filter these events out
}
return QWidget::eventFilter( obj, e ); // apply default filter
}
Note that this works, because the eventfilter installs itself on added children! Hence, it should also work without the use of UI-forms.
Refer this code to filter out specific event:-
class MainWindow : public QMainWindow
{
public:
MainWindow();
protected:
bool eventFilter(QObject *obj, QEvent *ev);
private:
QTextEdit *textEdit;
};
MainWindow::MainWindow()
{
textEdit = new QTextEdit;
setCentralWidget(textEdit);
textEdit->installEventFilter(this);
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == textEdit) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
qDebug() << "Ate key press" << keyEvent->key();
return true;
} else {
return false;
}
} else {
// pass the event on to the parent class
return QMainWindow::eventFilter(obj, event);
}
}
If you want to set more specific event filter on multiple widgets you can refer following code:
class KeyPressEater : public QObject
{
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event);
};
bool KeyPressEater::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
qDebug("Ate key press %d", keyEvent->key());
return true;
} else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}
KeyPressEater *keyPressEater = new KeyPressEater(this);
QPushButton *pushButton = new QPushButton(this);
pushButton->installEventFilter(keyPressEater);

Qt Tab rename when double clicked

i am using visual Studio with Qt.
i do not have access to Qt designer. its all done through coding (C++);
i have an opensource software called easypaint.
i got stuck at trying to rename tabs. I want to be able to rename tabs when user double clicks on the tab itself.
i created a new function to filter the doubleClick event :
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
`enter code here`{
if (event->type() == QEvent::MouseButtonDblClick) {
return true;
} else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}
then i added this line to a function that initializes the TabWidget:
installEventFilter(mTabWidget);
can anyone please guide me through this.
Thank you
Most likely Qt doesn't allow an inline editor to open on the tab's name. So you'd most likely have to create and run a very small QDialog to query for the new name:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == mTabWidget &&
event->type() == QEvent::MouseButtonDblClick) {
// query and set tab(s) names
QTabWidget *tab = qobject_cast<QTabWidget *>(obj);
if(tab)
{
QDialog dlg;
QVBoxLayout la(&dlg);
QLineEdit ed;
la.addWidget(&ed);
QDialogButtonBox bb(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
la.addWidget(&bb);
dlg.setLayout(&la);
if(dlg.exec() == QDialog::Accepted)
{
tab->setTabText(0, ed.text());
return true;
}
}
}
// Standard event processing
return QObject::eventFilter(obj, event);
}
It might be that Qt's dynamic memory management doesn't like the local class instances, so you'd have to convert all those class instances created to pointers created with new, but then please don't forget to tell the QDialog to delete on close or call dlg->deleteLater() after you queried the new name.
Another way to solve this via a fake inline editor would need a bit more work:
create a QLineEdit
move it right above the tab's, bring it up front and set keyboard focus to it
wire signals and slots
pressing enter should use the contents of the QLineEdit
leaving focus from the line edit should be treated as "abort" and delete the line editor
implement the slots to do what's needed.
You can write the event filter in the fallowing way:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == mTabWidget &&
event->type() == QEvent::MouseButtonDblClick) {
QTabWidget *tab = qobject_cast<QTabWidget *>(obj);
// Set tab(s) names
tab->setTabText(0, "New Name");
}
// Standard event processing
return QObject::eventFilter(obj, event);
}