HowTo correctly close QDialog when main windows is hidden? - c++

I have some kind of dilemma.
I'm using:
MSVS 2008
Qt 4.7.3 (with Qt VS Add-in 1.1.9)
I wrote small Qt application, base on QMainWindow class, where also exists settings dialog (QDialog). Every works fine in GUI mode. After that I started to change my project to make it visible only in tray. Just comment in main.cpp show() method, like this:
MainWindow w;
//w.show();
return app.exec();
But from tray, I need to launch settings dialog, which is implemented in mainwindow.h/.cpp files. I added to tray menu action (QAction) which is starts that settings dialog. And here comes the unexpected problem: when I tried to close this settings dialog with [ X ] close button (in top right corner) my app closed!
Here is the action slot:
void MainWindow::onOpenSettingsDlgClicked()
{
SettingsDlg dlg( this );
dlg.exec();
}
I have tried to reimplement virtual reject() method for the settings dialog class, and set there only hide() function, but that solution not helped.
What I'm doing wrong?
Thanks you!

You should turn off the quitOnLastWindowClosed property which is turned on by default as defined in the doc (http://doc.qt.nokia.com/latest/qapplication.html#quitOnLastWindowClosed-prop)
This said, you'll have to handle the termination of your QApplication yourself, maybe with an [quit] entry in the tray menu.

Just found another option which seems better is to override closeEvent of the QDialog to only hide it.
void PrefDialog::closeEvent(QCloseEvent *event) {
this->hide();
event->ignore();
}
I found this seems better because it doesn't change the global application behaviour.

Related

QT Window Modality disables actions in menu

I am developing a desktop application on macOS. I have a class that is a subclass of QMainWindow. Inside this window there are many dockwidgets. I need to set WindowModality to WindowModal, so user cannot interact with other opened windows. But my window has a menubar with many menus that have some QActions inside and when I setWindowModality(Qt::WindowModal) it automatically disables every action in menu and I need them to be enabled.
Can anybody provide some simple solution for this? Or it is not possible?
Thank you very much.
EDIT:
I have many windows in my application. I have a real main window from which you can open another window and also from that window another window. And here is the situation where i need my child windows to be modal. But they also have their own menubar which gets automatically disabled when window modality is turned on. Ive been googling it already maybe for 10 hours without any solution. I cannot test it but I guess that on windows the menubar would not disable because the native menu is quite different.
If there is no specific need of using QWindow, then it'll be easier to achive this using QDialog class instead. Using QDialog you can simply show dialog as modal using exec() method.
EDIT: Basically, you can add QMenuBar element to every QLayout class object using QLayout::setMenuBar method.
If you want to add menu bar to QDialog, you've got to set layout for your dialog, then programatically create desired QMenuBar object and pass it to QDialog layout (which you can access using QDialog::layout method). Simple example below:
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
QMenuBar* menu = new QMenuBar();
QMenu* fileMenu = menu->addMenu("File"); //Create 'File' menu inside menu bar
QAction* closeAction = fileMenu->addAction("Close"); //Create 'Close' action in 'File' menu
connect(closeAction, QAction::triggered, this, close); //Close dialog after triggering 'Close' action
layout()->setMenuBar(menu); //Add menu bar to QDialog layout
}
Please consider the usage of Qt::ApplicationModal.
This keeps the modality but gives you other behaviour on MAC.

Qt - minimizing and maximizing app without standard titlebar buttons

I have a Qt application where there is only one widget which is not a MainWindow, just a QLabel. It has not title bar (obtained through setWindowFlags(Qt::FramelessWindowHint)), thus the standard minimize and maximize buttons are not available. But there is a sidebar at the widget's side where we provide a minimize button that should behave as the standard minimize button.
How do I do it?
I tried the solutions at Minimizing a Qt application and Qt C++ minimize and maximize window. Neither works. I can hide the app of course, on clicking the minimize button. Problem is, how to restore it through standard mechanisms?
Scenarios:
On Mac, the dock icon is clicked. Thankfully, OS X native APIs can give me a notification when dock icon is clicked, so based on that, I can unhide the widget and make it active.
On Mac, the app icon is double clicked in /Applications, or clicked in Launchpad. How do I get a notification for this? The code doesn't even come to the main.cpp that I can unhide it from there if it is hidden.
On Windows, the application icon in the taskbar is clicked (the app does not have a tray icon). How do I get notification for that and unhide it?
On Windows, the app icon is double clicked either in Program Files, or may be a desktop shortcut icon. How do I get notification for this to unhide it?
If this aproach is not correct, how do I show and hide the app as per standard behavior on both Mac and Windows?
Platform - Qt 5.3.1, 32 bit.
This is not an answer, but it might help sorting out which events are triggered (points 1,2 and 3).
#include <QApplication>
class newapp : public QApplication {
Q_OBJECT
public:
newapp( int &argc, char **argv ) : QApplication(argc, argv) {}
protected:
bool event(QEvent *ev) {
std::cerr << "APPLICATION EVENT " << ev->type() << std::endl;
return QApplication::event(ev);
}
};
and in your main.cc you will have
newapp myapp(argc,argv);
instead of
QApplication myapp(argc,argv)
Once you identify the events triggered, you're almost done: you need to tell to you newapp to restore the size of the Qlabel (there are tons of ways to do this, so provide your implementation and you might get more focused help)
For point 4, it's something else due to the different behavior between OSes as in Windows double clicking for the second time an app, will launch another instance of the application (on OSx it will raise the first opened app). You might find something that suit you in this project HERE

Access native QFileDialog

I'm writing a ui test for a Qt application. Now this application raises a QFileDialog which must be automatically filled in and committed.
I already have a QTimer which runs even when the modal dialog is shown. This approach works for many dialogs e.g. QMessageBox or QColorDialog.
The Problem is, that the QFileDialog is a native dialog. So I can't search for the dialog widget, because there is none.
Is there a way to access the native dialog.
I'm developing on Ubuntu so I guess it's a GTK dialog. The tests will always run on Ubuntu.
Depending on your needs you could just set QFileDialog::DontUseNativeDialog to true using void QFileDialog::setOption(Option option, bool on = true) before you show the dialog. Then you should have a widget to search for.
See: http://doc.qt.io/qt-5/qfiledialog.html#setOption

Add button click handler in Qt project, Visual Studio

I have Qt SDK and Visual Studio Qt Add-In working in VS2008. I created Qt UI project with main window class MainWindow. Double-click on mainwindow.ui opens Qt Designer. Then I added push button to the window, and called it pushButton. In Signals-Slots mode I managed to connect button's clicked signal with MainWindow ButtonClicked slot. Signal/Slot editor looks like this:
Sender pushButton
Signal clicked()
Receiver MainWindowClass
Slot ButtonClicked()
mainwindow.ui file was changed, reflecting this new information. However, mainwindow.cpp and mainwindow.h remain unchanged. I expect to see the place where I can add my own code. So, I added this code manually:
// mainwindow.h
...
protected slots:
void ButtonClicked();
// mainwindow.cpp
void MainWindow::ButtonClicked()
{
QMessageBox msgBox;
msgBox.setText("Clicked");
msgBox.exec();
}
It works, but I wonder whether this is correct way to do this. Is slot declaration and implementation supposed to be added manually, or I am missing something?
If you use signal/slot editor, you have to add these codes manually. Old Qt Add-In was automatically add these if you double click on a button from designer. Now Qt Designer is a seperate application. Double clicking is not possible.
Also you can use automatic connections. With automatic connections you dont need to connect signals with slots. Functions which has special naming convention, automatically called. Like on_okButton_clicked.

QDockWidget is closed if main window is minimized

I'm using Qt 4.7 on Windows 7 Ultimate 32 bit.
The QMainWindow of my program has a QDockWidget. I've noticed that if I minimize the main window by the minimize button on the title bar, after restoring it the dock widget is closed. I didn't write any support for a feature like this!
How does this happen and how to prevent this?
Thanks.
I encountered this error when writing my own application. I have QDockWidget with options for my application. Using Qt Creator I created menu with QAction actionMenu which was checkable. Then I connected QDockWidget and QAction like this:
QObject::connect(ui->dockWidget, SIGNAL(visibilityChanged(bool)),
ui->actionMenu, SLOT(setChecked(bool)));
QObject::connect(ui->actionMenu, SIGNAL(toggled(bool)),
ui->dockWidget, SLOT(setVisible(bool)));
The order of connection is not important. And then when I minimized application with QDockWidget being visible, after I restored it QDockWidget was closed and actionMenu was unchecked.
In fact there are two solutions. First which works for me is to use SIGNAL(triggered(bool)) instead of SIGNAL(toggled(bool)):
QObject::connect(ui->dockWidget, SIGNAL(visibilityChanged(bool)),
ui->actionMenu, SLOT(setChecked(bool)));
QObject::connect(ui->actionMenu, SIGNAL(triggered(bool)),
ui->dockWidget, SLOT(setVisible(bool)));
The second solution uses action which you can obtain from QDockWidget:
// Retrieve action from QDockWidget.
QAction *action = ui->dockWidget->toggleViewAction();
// Adjust any parameter you want.
action->setText(QString("&Menu"));
action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M));
action->setStatusTip(QString("Press to show/hide menu widget."));
action->setChecked(true);
// Install action in the menu.
ui->menuOptions->addAction(action);
I know for sure that SIGNAL(toggled(bool)) was causing in my application closure of QDockWidget.
I faced the same problem... I managed to get rid of it by using a method called StoreWindowsLayout and RestoreWindowsLayout.
StoreWindowsLayout will save the content of the ByteArray returned by the Method QMainwindow::saveState().
RestoreWindowsLayout will restore that bytearray, and therefore your windows layout, the qdockwidget visibility state and so on...
I call StoreWindowsLayout on ApplicationMainFrm::changeEvent, on ApplicationMainFrm::closeEvent (it's likely this one you'll need) and in ApplicationMainFrm::hide().
Then I use restoreWindowsLayout in ApplicationMainFrm::showEvent.
Exemple of use of restoreWindowsLayout in my MainForm :
void ApplicationMainFrm::showEvent(QShowEvent* pEvent)
{
QMainWindow::showEvent(pEvent);
restoreWindowsLayout();
}
Hope it helps !