QDockWidget is closed if main window is minimized - c++

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 !

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.

Dragging QDockWidgets between QMainWindows

I have a question regarding dragging QDockWidgets between QMainWindows. I have an application with different "DockAreas" which have a QMainWindow member with one or more QDockWidgets. Additionally, I want to make QDockWidgets drag-and-droppable into other, already floating QDockWidgets (not tabbed!).
To have the nice hover-effect upon drag-and-drop, the floating QDockWidgets are embedded in a new instance of my DockArea with the QMainWindow member. Now I intercept the mousemove event of the dragged QDockWidget and change its parent when it hovers over another QMainWindow of my DockArea. Unfortunately, this causes a crash and it looks like the original QLayoutItem, where this QDockWidget was in, is gone.
void QDockWidgetPrivate::moveEvent(QMoveEvent *event)
{
// ...
// now this widgetItem member of state is kaputt
layout->hover(state->widgetItem, globalMousePos);
}
I found different suggestions for dragging-dropping QDockWidgets between QMainWindows on the internet:
1) Re-parenting - that's what I am trying atm
2) QDrag - did not work for me, async exec() breaks my application and at the end I have to reparent anyway
3) Call addDockWidget(...) of the new QMainWindow - docks the QDockWidget and I would have to make it floating again and somehow "continue the dragging"
I am open to any new suggestions :) Thank you in advance!
I'm wrestling with the same Problem right now and want to share.
Ich found this forum post dealing with the same problem: http://www.qtcentre.org/threads/41847-Dragging-QDockWidgets-between-QMainWindows
This solution is however flawed: it doesn't work properly if you allow the Dockables to be floating. And the enterEvent does not actually trigger when you enter the other window and still dragging the QDockWidget. It only triggers after release.
I'm also going for the reparenting (1). QDrag seems problematic when you also want to allow rearranging the QDockWidget within the Window.
I think one would correctly do this by reacting to the drop/release of the dragged QDockWidget. But I can't find an event or signal for this.

Context Menu works for child but not parent Widget

I'm developing a desktop program that displays data in several QWidget windows, and I'm attempting to use a context menu to allow the user to copy/save an image of the window for use elsewhere. I encounter a pretty strange error when trying to get the context menu to appear in the window. I initially used the Qt Design mode to create the on_Plot_customContextMenuRequested(const QPoint &pos) slot for the entire window (entire Qwidget?), which did not work. When I create the on_SignalPlot_customContextMenuRequested slot, it works perfectly, but only on that specific widget, which is a subset of the entire window. I use identical code for each slot, and the debug output shows that the individual widget context menu request signal is emitted but the signal for the whole window is not. Is there a way to get it to work for the whole window?
Could the fact that the two child widgets take up the entire window cause the issue? I use a grid layout to ensure that the plots resize with the window.
(I'd show an image of the designer layout, but I don't have enough reputation.)
Does not work (code for whole window):
void Plot::on_Plot_customContextMenuRequested(const QPoint &pos)
{
qDebug()<<"plot context menu requested";
qDebug()<<pos;
QMenu* menu=new QMenu();
menu->addAction(copyWinAct);
menu->addAction(saveWinAct);
menu->exec(QCursor::pos());
}
Works Perfectly (code for individual plot/widget):
void Plot::on_SignalPlot_customContextMenuRequested(const QPoint &pos)
{
qDebug()<<"plot context menu requested";
qDebug()<<pos;
QMenu* menu=new QMenu();
menu->addAction(copyWinAct);
menu->addAction(saveWinAct);
menu->exec(QCursor::pos());
}
Thanks for your help.
If anyone else has this problem, I've found a solution. By connecting the customContextMenuRequested signal to one slot, each sub-widget will display the same context menu. Setting the overall widget to the same slot will make the whole window behave in the same manner. I added the following code to the class default constructor and created the corresponding slot to get everything to behave properly.
this->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenuSlot(QPoint)));
QList<QWidget *> windowChildren=this->findChildren<QWidget *>();
foreach (QWidget *child, windowChildren)
{
child->setContextMenuPolicy(Qt::CustomContextMenu);
connect(child,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenuSlot(QPoint)));
}
Good luck to anyone else fighting this problem.

How can I add a QComboBox to the Main Toolbar in Qt Creator

I am writing a Text Editor on Qt Creator. I have a QPlainTextEdit as the central widget, and I want all the font-controlling tools in the main toolbar automatically added to all QMainWindow projects. When I try to drag and drop a QComboBox on to the main toolbar, A not-allowed icon is displayed.
Is there a way of doing this?
Thanks for your help in advance.
You can do what you want by calling the addWidget function of the QToolBar. So if you have called your main tool bar mainToolBar you can do in the constructor of your main window:
QComboBox* myComboBox = new QComboBox;
// Add values in the combo box
ui->mainToolBar->addWidget(myComboBox);
// make the connection between the combo box and a slot
Okay, looking a bit around in the cpp file I realized that I'm referring the wrong thing.
ui->mainToolBar->insertWidget(ui->actionLoadSettings, cbxSelect); will do the trick.

Show window in Qt without stealing focus

I'm using the Qt library to show a slideshow on the second monitor when the user isn't using the second monitor. An example is the user playing a game in the first monitor and showing the slideshow in the second monitor.
The problem is that when I open a new window in Qt, it automatically steals the focus from the previous application. Is there any way to prevent this from happening?
It took me a while to find it but I found it: setAttribute(Qt::WA_ShowWithoutActivating);
This forces the window not to activate. Even with the Qt::WindowStaysOnTopHint flag
If you want to make floating preview box/ any other widget just use below
thumbnail = new QLabel;
thumbnail->setAttribute(Qt::WA_ShowWithoutActivating);
thumbnail->setParent(0);
thumbnail->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);
Qt::Tool is important flag to make it work. I mean not stealing focus.
Widgets don't accept focus by default but presumably you haven't created a plain widget? Which subclass was it? QMainWindow or something else?
It's possible the window subclasses default to accepting focus so try explicitly calling QWidget::setFocusPolicy with Qt::NoFocus before calling QWidget::show().
Also, make sure you're not calling QWidget::activateWindow() on the window or any of its widgets at any point.