QMainWindow close() signal not emitted - qt

To warn before closing a window that inherits from QMainWindow, I reimplemented its closeEvent, which works fine when I emit close() manually. However, clicking the "x" button does not trigger this; it just exits.
It does emit aboutToQuit() for the application, which I can use to "recover" the window after it already closes. But I want to the warning to precede the initial closing.
I'm not sure where the issue is. The window is top-level and there are no running threads. Have I misunderstood what signal is actually connected to the button click...? It is close(), right?

In your mainwindow class header( the closeEvent must be virtual ):
public:
/*!
* \brief closeEvent
* \param event
*/
virtual void closeEvent ( QCloseEvent * event );
Then in the cpp
void MainWindow::closeEvent( QCloseEvent *event )
{
//! Ignore the event by default.. otherwise the window will be closed always.
event->ignore();
if(!EntitiesSaverObserver::Instance()->isAllSaved())
{
QMessageBox msgBox;
msgBox.setWindowIcon(QIcon(":/Resources/Icons/warning.png"));
msgBox.setIconPixmap(QPixmap(":/Resources/Icons/warning.png"));
QString strToShow = QString("Some Entities has been created or modified...");
msgBox.setText(strToShow);
msgBox.setInformativeText("Do you want to save your changes?");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec();
switch (ret) {
case QMessageBox::Save:
{
// Save was clicked
qDebug() << "SAVE";
//! Do your stuff here
// ....
event->accept();
break;
}
case QMessageBox::Discard:
{
// Don't Save was clicked
qDebug() << "DISCARD";
event->accept();
break;
}
case QMessageBox::Cancel:
{
// Cancel was clicked
qDebug() << "CANCEL";
break;
}
default:
// should never be reached
break;
}
} else {
event->accept(); // Do not need to save nothing... accept the event and close the app
}
}
Moreover, if you want to put a button in your toolbar as a QAction, you could connect the signal and then:
void MainWindow::on_actionExit_triggered()
{
close();
}
This would call the close event of your main window. I hope this helps you.

just create a signal-slot QObject::connect(yourButton, SIGNAL(clicked()), this, SLOT(close()));

Related

How can I intercept and cancel the minimizing of a Window?

I have a Window subclass in my project, and at runtime the instance is created and shown entirely on the QML side. I know that I can prevent the window from being minimized by not including the WindowMinimizeButtonHint in the flags:, but I actually need to have the minimize button present and enabled but be able to intercept the minimize button click, cancel the actual minimizing, and do something else (FYI my client is requiring this non-standard windowing behavior, not me).
So far, the only thing I've been able to achieve is to handle the onWindowStateChanged: event, check if windowState === Qt.WindowStateMinimized and call show() from a timer (calling it inside the event handler directly does nothing). This results in the window moving down to the system tray and then suddenly coming back up to normal.
Is there any way to do this, something like an OnMinimized event that can be cancelled?
Edit: based on Benjamin T's answer, I'm at least part way to a solution for OSX:
#import <AppKit/AppKit.h>
bool NativeFilter::nativeEventFilter(const QByteArray &eventType,
void *message, long *result)
{
if (eventType == "mac_generic_NSEvent") {
NSEvent *event = static_cast<NSEvent *>(message);
if ([event type] == NSKeyDown) {
return true;
}
}
return false;
}
In this example I'm able to intercept and cancel all NSKeyDown events (while leaving other events like mouse clicks etc. still working). The remaining problem is that I still don't know to intercept a minimize event - NSEvent.h doesn't seem to have anything that covers that. Perhaps I need to cast to a different type of event?
Edit 2 - working solution:
I was not able to find any way to intercept the minimize event proper and cancel it, so my workaround is to instead intercept the click on the window, determine if the click is over the minimize button (or the close or zoom buttons) and cancel the event if so (and send a notification to my qml window that the click occurred). I also handle the case of double-clicking the titlebar to zoom the window, and using the Command-M keys to minimize the window.
First step is to implement a QAbstractNativeEventFilter. In your header:
#include <QAbstractNativeEventFilter>
class NativeFilter : public QAbstractNativeEventFilter {
public:
bool nativeEventFilter(const QByteArray &eventType, void *message,
long *result);
};
The implementation:
#import <AppKit/AppKit.h>
#import <AppKit/NSWindow.h>
#import <AppKit/NSButton.h>
bool NativeFilter::nativeEventFilter(const QByteArray &eventType, void
*message, long *result)
{
if (eventType == "mac_generic_NSEvent") {
NSEvent *event = static_cast<NSEvent *>(message);
NSWindow *win = [event window];
// TODO: determine whether or not this is a window whose
// events you want to intercept. I did this by checking
// [win title] but you may want to find and use the
// window's id instead.
// Detect a double-click on the titlebar. If the zoom button
// is enabled, send the full-screen message to the window
if ([event type] == NSLeftMouseUp) {
if ([event clickCount] > 1) {
NSPoint pt = [event locationInWindow];
CGRect rect = [win frame];
// event coordinates have y going in the opposite direction from frame coordinates, very annoying
CGFloat yInverted = rect.size.height - pt.y;
if (yInverted <= 20) {
// TODO: need the proper metrics for the height of the title bar
NSButton *btn = [win standardWindowButton:NSWindowZoomButton];
if (btn.enabled) {
// notify qml of zoom button click
}
return true;
}
}
}
if ([event type] == NSKeyDown) {
// detect command-M (for minimize app)
if ([event modifierFlags] & NSCommandKeyMask) {
// M key
if ([event keyCode] == 46) {
// notify qml of miniaturize button click
return true;
}
}
// TODO: we may be requested to handle keyboard actions for close and zoom buttons. e.g. ctrl-cmd-F is zoom, I think,
// and Command-H is hide.
}
if ([event type] == NSLeftMouseDown) {
NSPoint pt = [event locationInWindow];
CGRect rect = [win frame];
// event coordinates have y going in the opposite direction from frame coordinates, very annoying
CGFloat yInverted = rect.size.height - pt.y;
NSButton *btn = [win standardWindowButton:NSWindowMiniaturizeButton];
CGRect rectButton = [btn frame];
if ((yInverted >= rectButton.origin.y) && (yInverted <= (rectButton.origin.y + rectButton.size.height))) {
if ((pt.x >= rectButton.origin.x) && (pt.x <= (rectButton.origin.x + rectButton.size.width))) {
// notify .qml of miniaturize button click
return true;
}
}
btn = [win standardWindowButton:NSWindowZoomButton];
rectButton = [btn frame];
if (btn.enabled) {
if ((yInverted >= rectButton.origin.y) && (yInverted <= (rectButton.origin.y + rectButton.size.height))) {
if ((pt.x >= rectButton.origin.x) && (pt.x <= (rectButton.origin.x + rectButton.size.width))) {
// notify qml of zoom button click
return true;
}
}
}
btn = [win standardWindowButton:NSWindowCloseButton];
rectButton = [btn frame];
if ((yInverted >= rectButton.origin.y) && (yInverted <= (rectButton.origin.y + rectButton.size.height))) {
if ((pt.x >= rectButton.origin.x) && (pt.x <= (rectButton.origin.x + rectButton.size.width))) {
// notify qml of close button click
return true;
}
}
}
return false;
}
return false;
}
Then in main.cpp:
Application app(argc, argv);
app.installNativeEventFilter(new NativeFilter());
Generally speaking, you should use the event system ans not signal/slots to intercept events and changes.
The easiest way to do so is either to subclass the object you use and reimplement the appropriate event handler, or to use an event filter.
Since you are using QML, subclassing might be difficult as you don't have access to all Qt internal classes.
Here is what the code would look like when using event filtering.
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
auto root = engine.rootObjects().first();
root->installEventFilter(new EventFilter());
return app.exec();
}
class EventFilter : public QObject
{
Q_OBJECT
public:
explicit EventFilter(QObject *parent = nullptr);
bool eventFilter(QObject *watched, QEvent *event) override;
};
bool EventFilter::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::WindowStateChange) {
auto e = static_cast<QWindowStateChangeEvent *>(event);
auto window = static_cast<QWindow *>(watched);
if (window->windowStates().testFlag(Qt::WindowMinimized)
&& ! e->oldState().testFlag(Qt::WindowMinimized))
{
// Restore old state
window->setWindowStates(e->oldState());
return true;
}
}
// Do not filter event
return false;
}
However, you will quickly run into the same issue that when using the signal/slot mechanism: Qt only notify you when the window has already been minimized. Meaning that restoring the window at this point will make a hide/show effect.
So you need to go deeper and you a native event filter.
The following code works on Windows, you should adapt it for macOS:
class NativeFilter : public QAbstractNativeEventFilter {
public:
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result);
};
bool NativeFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
/* On Windows we interceot the click in the title bar. */
/* If we wait for the minimize event, it is already too late. */
#ifdef Q_OS_WIN
auto msg = static_cast<MSG *>(message);
// Filter out the event when the minimize button is pressed.
if (msg->message == WM_NCLBUTTONDOWN && msg->wParam == HTREDUCE)
return true;
#endif
/* Example macOS code from Qt doc, adapt to your need */
#ifdef Q_OS_MACOS
if (eventType == "mac_generic_NSEvent") {
NSEvent *event = static_cast<NSEvent *>(message);
if ([event type] == NSKeyDown) {
// Handle key event
qDebug() << QString::fromNSString([event characters]);
}
}
#endif
return false;
}
In your main():
QGuiApplication app(argc, argv);
app.installNativeEventFilter(new NativeFilter());
For more info, you can read the Qt documentation about QAbstractNativeEventFilter.
You may need to use QWindow::winId() to check to which window the native events are targeted.
As I am not a macOS developer, I do not know what you can do with NSEvent.
Also it seems the NSWindowDelegate class could be useful to you: https://developer.apple.com/documentation/appkit/nswindowdelegate
If you can retrieve a NSWindow from QWindow::winId(), you should be able to use it.

How does QLineEdit triger QAbstractItemDelegate::commitData

I am developing a Qt application using QTreeView and QAbstractItemModel.
The model contains somewhat heterogenous data, which requires different controls for editing. I am implementing it by having a custom delegate, that queries model.data(Qt::EditRole) and the model would return the QWidget to be used as an editor.
I like how it works for QLineEdit - when I hit enter, delegate::setModelData is called automatically, so I do not have to connect QLineEdit::editingFinished to QAbstractItemDelegate::setModelData(), which is very convenient since the QLineEdit is returned from the model as QWidget to the delegate and it doesn't have to care what kind of widget it is.
With QComboBox it's a bit tricky - I want the comboBox to commit once the selection is made, so far I can only do it by connect(myComboBox, SIGNAL(activated(QString)), myDelegate, commitData()));
However, my delegate doesn't know the type of the editor widget and I do not want to edit the delegate's code for each new editor the model ends up passing it. I would really like to force combobox to do the same thing as QLineEdit does when the enter is clicked in the slot connected to its activated() signal.
So, what does the QLineEdit do to call delegate's setModelData?
Is there a generic way in Qt for the editor whatever it is to say "I'm done editing, take the data and pass it to the model"?
The QStyledItemDelegate (and QItemDelegate) defines an event filter that calls commitData if you press tab or return.
See the following excerpt from the Qt 4.8.6 source:
bool QStyledItemDelegate::eventFilter(QObject *object, QEvent *event)
{
QWidget *editor = qobject_cast<QWidget*>(object);
if (!editor)
return false;
if (event->type() == QEvent::KeyPress) {
switch (static_cast<QKeyEvent *>(event)->key()) {
case Qt::Key_Tab:
emit commitData(editor);
emit closeEditor(editor, QAbstractItemDelegate::EditNextItem);
return true;
case Qt::Key_Backtab:
emit commitData(editor);
emit closeEditor(editor, QAbstractItemDelegate::EditPreviousItem);
return true;
case Qt::Key_Enter:
case Qt::Key_Return:
#ifndef QT_NO_TEXTEDIT
if (qobject_cast<QTextEdit *>(editor) || qobject_cast<QPlainTextEdit *>(editor))
return false; // don't filter enter key events for QTextEdit
// We want the editor to be able to process the key press
// before committing the data (e.g. so it can do
// validation/fixup of the input).
#endif // QT_NO_TEXTEDIT
#ifndef QT_NO_LINEEDIT
if (QLineEdit *e = qobject_cast<QLineEdit*>(editor))
if (!e->hasAcceptableInput())
return false;
#endif // QT_NO_LINEEDIT
QMetaObject::invokeMethod(this, "_q_commitDataAndCloseEditor",
Qt::QueuedConnection, Q_ARG(QWidget*, editor));
return false;
case Qt::Key_Escape:
// don't commit data
emit closeEditor(editor, QAbstractItemDelegate::RevertModelCache);
break;
default:
return false;
}
if (editor->parentWidget())
editor->parentWidget()->setFocus();
return true;
} else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) {
//the Hide event will take care of he editors that are in fact complete dialogs
if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) {
QWidget *w = QApplication::focusWidget();
while (w) { // don't worry about focus changes internally in the editor
if (w == editor)
return false;
w = w->parentWidget();
}
#ifndef QT_NO_DRAGANDDROP
// The window may lose focus during an drag operation.
// i.e when dragging involves the taskbar on Windows.
if (QDragManager::self() && QDragManager::self()->object != 0)
return false;
#endif
emit commitData(editor);
emit closeEditor(editor, NoHint);
}
} else if (event->type() == QEvent::ShortcutOverride) {
if (static_cast<QKeyEvent*>(event)->key() == Qt::Key_Escape) {
event->accept();
return true;
}
}
return false;
}

Qt: Program crashes when it emits signals

I am using VTK and Qt, and I need to know, when which mouse-button is pressed or released.
That for I created a new class, which inherits QObject and vtkInteractorStyleTrackballCamera:
class CModelMouseInteractorStyle :
public vtkInteractorStyleTrackballCamera,
public QObject
{
public:
CModelMouseInteractorStyle();
virtual void OnLeftButtonDown()
{
std::cout << "Pressed left mouse button." << std::endl;
// Forward events
vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
// emit signal
emit leftButtonDown();
}
virtual void OnLeftButtonUp()
{
std::cout << "Released left mouse button." << std::endl;
// Forward events
vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
// emit signal
emit leftButtonUp();
}
// I have similar functions for right and middle mouse-button
...
signals:
void leftButtonDown();
void leftButtonUp();
// and similar signals, too
...
};
I get the right couts whenever a button is pressed/released and I can interact with my scene as I want to, but only as long as I don't emit any signals.
As soon as I emit a signal in on of the functions, I get a symbol lookup error and the whole program crashes.
Am I doing something wrong? Do I have forgotten any thing?
I am using Qt4.7.4 and Vtk5.8.

Drag and drop of QGraphicsItem between two pairs of QGraphicsScene/QGraphicsView

I have an application with a mainwindow in which I create a QGraphicsScene like this:
DiagramWindow::DiagramWindow()
{
scene = new QGraphicsScene(0, 0, 600, 500);
Then on the same program, I'm calling another window with another (different)QGraphicsScene. Both of these scenes have their respective QGraphicsViews and I use the same custom class to draw QGraphicsItem in each scene/window.
Now I'm trying to implement drag and drop between the two scenes/windows using this and I'm getting an effect that I think is similar/the same as in this SO question
. Basically, when I drag a QGraphicsItem from the second window/scene to the main window, it does not trigger the event on the scene, BUT it does trigger in in the main window's toolbar/ borders.
My event handling functions are:
void DiagramWindow::dragEnterEvent(QDragEnterEvent *event)
{
qDebug() << "I'm on the main window!";
event->acceptProposedAction();
}
and
void DiagramWindow::dropEvent(QDropEvent *event)
{
event->acceptProposedAction();
qDebug() << "got a drop!";
}
According to the answers there, I would have to setAcceptDrops() in a QGraphicsScene (which is not possible), so the trick seems to be to overload the QGraphicsScene::dragMoveEvent(). Since I don't have a specific class for my QGraphicsScene (just for it's parent DiagramWindow), I don't know how I can write a function to target the scene's specific dragMoveEvent().
QUESTION 1 I was hoping I could do something like:
DiagramWindow->scene::dragMoveEvent()
{
...
}
But of course this is not possible. I'm really new to C++/Qt and the general workflow/syntax dynamics still ellude me. How can I target the QGraphicsScene inside my MainWindow to write the event handling function?
QUESTION 2 Also, I noticed that by rewriting these event handling functions, I (obviously) lost most of the funcionality I had in the main window - selecting and moving around the QGraphicsItems no longer works. Is there anyway I can make these events trigger only if the events are being originated in the second window? I have looked at QDrag->source() but I'm not getting how it works either - something like, if the events originate in the second window, do this, else, keep doing what you were doing before - which I don't actually know what is... :)
Question1
If the event is received by the diagramWindow, and want it receive by the scene which is currently displayed by a view, then what you should do is pass the event to the view, that will convert it to a QGraphicsSceneDragDropEvent and redirect it to the scene:
void DiagramWindow::dragMoveEvent(event)
{
view->dragMoveEvent(event);
}
Question 2
Don't know much about Drag event so can't help, but to get the previous behaviour depending on a if statement, you should do:
void MyDerivedClass::myEvent(event)
{
if(...)
// do specific behaviour
else
QBaseClass::myEvent(event); // default behaviour
}
assuming your class MyDerivedClass(in your case, DiagramWindow) inherits from the Qt class QBaseClass (in your case, QMainWindow?), and the event method you want to override is myEvent() (in your case, dragMoveEvent).
Working example:
I don't know exacly what your class DiagramWindow is, but here is a working example that should give you all the necessary ideas to make it work in your case. I suggest you start from this working example, and modify it to get what you need.
main.cpp:
#include <QApplication>
#include "Scene.h"
#include "View.h"
int main(int argc, char * argv[])
{
QApplication app(argc,argv);
Scene * scene1 = new Scene(1);
View * view1 = new View(scene1, 1);
Scene * scene2 = new Scene(2);
View * view2 = new View(scene2,2);
view1->show();
view2->show();
return app.exec();
}
Scene.h:
#ifndef SCENE_H
#define SCENE_H
#include <QGraphicsScene>
#include <QGraphicsEllipseItem>
class Item;
class Item: public QGraphicsEllipseItem
{
public:
Item(int x,int y);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
};
class Scene: public QGraphicsScene
{
public:
Scene(int i);
protected:
virtual void dragEnterEvent ( QGraphicsSceneDragDropEvent * event );
virtual void dragLeaveEvent ( QGraphicsSceneDragDropEvent * event );
virtual void dragMoveEvent ( QGraphicsSceneDragDropEvent * event );
virtual void dropEvent ( QGraphicsSceneDragDropEvent * event );
int i;
};
#endif
Scene.cpp:
#include "Scene.h"
#include <QtDebug>
#include <QGraphicsSceneMouseEvent>
#include <QDrag>
#include <QMimeData>
Item::Item(int x, int y) : QGraphicsEllipseItem(x,y,50,50) {}
void Item::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
qDebug() << "item mouse press";
// Create the mime data that will be transfered from one scene
// to another
QMimeData * mimeData = new QMimeData;
// In our case, the data will be the address of the item.
//
// Note: This is UNSAFE, and just for the sake of example. The
// good way to do it is to create your own mime type, containing
// all the information necessary to recreate an identical Item.
//
// This is because drag and drop is meant to work between
// applications, and the address of your item is not accessible
// by other applications (deferencing it would produce a
// segfault). It works fine in this case since you perform a
// drag and drop between different windows of the same
// application.
Item * item = this;
QByteArray byteArray(reinterpret_cast<char*>(&item),sizeof(Item*));
mimeData->setData("Item",byteArray);
// start the event
QDrag * drag = new QDrag(event->widget());
drag->setMimeData(mimeData);
drag->start();
}
Scene::Scene(int i) : i(i)
{
Item * item = new Item(100+100*i,100);
addItem(item);
}
void Scene::dragEnterEvent ( QGraphicsSceneDragDropEvent * event )
{
qDebug() << "scene" << i << "drag enter";
}
void Scene::dragLeaveEvent ( QGraphicsSceneDragDropEvent * event )
{
qDebug() << "scene" << i << "drag leave";
}
void Scene::dragMoveEvent ( QGraphicsSceneDragDropEvent * event )
{
qDebug() << "scene" << i << "drag move";
}
void Scene::dropEvent ( QGraphicsSceneDragDropEvent * event )
{
qDebug() << "scene" << i << "drop";
// retrieve the address of the item from the mime data
QByteArray byteArray = event->mimeData()->data("Item");
Item * item = *reinterpret_cast<Item**>(byteArray.data());
// add the item to the scene (automatically remove it from the
// other scene)
addItem(item);
}
View.h:
#ifndef VIEW_H
#define VIEW_H
#include <QGraphicsView>
#include "Scene.h"
class View: public QGraphicsView
{
public:
View(Scene * scene, int i);
protected:
virtual void dragEnterEvent ( QDragEnterEvent * event );
virtual void dragLeaveEvent ( QDragLeaveEvent * event );
virtual void dragMoveEvent ( QDragMoveEvent * event );
virtual void dropEvent ( QDropEvent * event );
private:
Scene * scene_;
int i;
};
#endif
View.cpp:
#include "View.h"
#include <QtDebug>
View::View(Scene * scene, int i) :
QGraphicsView(scene),
scene_(scene),
i(i)
{
}
void View::dragEnterEvent ( QDragEnterEvent * event )
{
qDebug() << "view" << i << "drag enter";
QGraphicsView::dragEnterEvent(event);
}
void View::dragLeaveEvent ( QDragLeaveEvent * event )
{
qDebug() << "view" << i <<"drag leave";
QGraphicsView::dragLeaveEvent(event);
}
void View::dragMoveEvent ( QDragMoveEvent * event )
{
qDebug() << "view" << i << "drag move";
QGraphicsView::dragMoveEvent(event);
}
void View::dropEvent ( QDropEvent * event )
{
qDebug() << "view" << i << "drop";
QGraphicsView::dropEvent(event);
}
In your case, if you need to explicitly call view->someDragDropEvent(event) from your DiagramWindow, then you just have to change the protected: to public:. But I don't think it is necessary, just try without reimplementing the drag and drop event in DiagramWindow, and it should automatically call the one of your view.

Qt - two signals and modal dialog window

I have a QDialog based class.
I have one QEditLine *editLine and QButton *button.
I use clicked() signal of button. And editingFinished() signal of editLine.
When I change the text in the editLine and press the button firstly editingFinished() signal is emitted. In the slot method I call QMessageBox::question().
After that I can't receive clicked() signal of my button.
I tried to use Qt::QueuedConnection for connect method, but it does not help.
How to solve my problem?
I think the issue is that the event loop for the message box is blocking the main event loop so your button's signal is not emitted. But how do you plan to click the button anyway if you have a modal dialog open?
Here is the code:
Window::Window(QWidget *parent)
: QDialog(parent)
{
setupUi(this);
appPath = QApplication::applicationDirPath();
connect(pButton, SIGNAL(clicked()), this, SLOT(build()), Qt::QueuedConnection);
connect(pLineEdit, SIGNAL(editingFinished()), this, SLOT(pathChanged()), Qt::QueuedConnection);
}
void Window::pathChanged()
{
QString path = pLineEdit->text();
if(createPath(path))
updatePath(path);
}
bool Window::createPath(QString path)
{
if(!QDir(path).exists())
{
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, tr("Folder is not exist"), "Folder " + path + " is not exist. Do you want to create it?", QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes)
{
QDir dir;
dir.mkpath(path);
}
}
return true;
}
class Window : public QDialog, public Ui::GLConverterDialogUI
{
Q_OBJECT
public:
Window(QWidget *parent = 0);
~Window(void);
......
}
I have the same problem in another application. I use some library. I guess that this library use pressed() signal of QAbstractButton instead of clicked(). And when I call QFileDialog::getSaveFileName() after button is pressed it seems that mouseReleaseEvent() is also not called. So after closing of dialog button is still pressed and I have to send MouseButtonRealese event manually.
Maybe I should call dialog with some special parameters?

Resources