Qt::Popup window flag and parent widget mouse event - c++

I want to create QCombobox with tree models support where each child list displayed in new window just like it happens in QMenu (without using QTreeView) but with QListView display features. All is going fine except one small thing: i lose all mouse events for parent widget when child popup is opened. So my question is how to keep taking mouse events during child popup is opened?
In qt basic example Window flags widget with Qt::Popup lose mouse event too. But in QMenu submenu been closed when mouse leave from parent action field. I mean this behaviour is supported by Qt and may be reached from the mox but it's hidden and I can't find a way to give it.
Qt::Tool or Qt::ToolTip modes give me necessary behaviour for parent widget but child widgets do not track mouse events for it's self

Related

Qt: Ignore MouseButtonRelease events when widget is hidden

The Documentation for QWidget says this:
mouseReleaseEvent() is called when a mouse button is released. A
widget receives mouse release events when it has received the
corresponding mouse press event. This means that if the user presses
the mouse inside your widget, then drags the mouse somewhere else
before releasing the mouse button, your widget receives the release
event. There is one exception: if a popup menu appears while the mouse
button is held down, this popup immediately steals the mouse events.
It also says this:
If you create new widgets in the mousePressEvent() the
mouseReleaseEvent() may not end up where you expect, depending on the
underlying window system (or X11 window manager), the widgets'
location and maybe more
In my programme, the is a context where the user can change the current visible widget by pressing Enter. If they click and hold on a toolbar button and press enter while the mouse is still pressed, they can send the mouse release event to the now hidden widget. This is a problem as the actions in the toolbar of the now hidden page, relate to a state which has been deinitialised when the active widget was changed.
The desired behaviour would be for the changing of active widget to somehow 'cancel' or 'release' the old widget's claim to the coming mouse release event even though it (or one of its children) received the corresponding mouse press event, and for the action in the toolbar not to be triggered.
Is there any way to do this? Or does anyone have any guidance on what I might be looking for?
Thanks
One options is by creating eventFilter function (either in widget itself (if your own) or parent widget), installing it with installEventFilter and then checking for mouse release event type and only accept the event if widget's isVisible() returns true.
Another option (in case you have your own Qt based widget class) is to override mouseReleaseEvent and do the same visibility check in there.

How to set Focus on a specific widget

I'm trying to implement GUI with various widgets for OpenGL project. I have a main widget for drawing the scene. The OpenGL widget is associated with Key and Mouse events, therefore the focus should always be on it. I've noticed if I click on say a push button, then the focus is moved to this button which means the focus is no longer associated with OpenGL widget. Clicking the widget by the mouse is not changing the focus. One of the solution is to turn off the focus for all widgets except the OpenGL widget in the GUI as follows
ui->processButton->setFocusPolicy(Qt::NoFocus);
ui->quitButton->setFocusPolicy(Qt::NoFocus);
ui->clearButton->setFocusPolicy(Qt::NoFocus);
ui->textEdit->setFocusPolicy(Qt::NoFocus);
ui->groupBox->setFocusPolicy(Qt::NoFocus);
if I have many widgets, then this solution is annoying especially if I add widgets later on. My question is is there a solution to set the focus on a specific widget?
Your solution is fine, you just shouldn't be enumerating widgets manually:
// C++11
for (auto widget : findChildren<QWidget*>())
if (! qobject_cast<QOpenGlWidget*>(widget)) widget->setFocusPolicy(Qt::NoFocus);
// C++98
foreach (QWidget * widget, findChildren<QWidget*>())
if (! qobject_cast<QOpenGlWidget*>(widget)) widget->setFocusPolicy(Qt::NoFocus);

QMenu is crossing the parent window frame?

I am using QtEmbedded-4.8 for my development project. A typical problem I am facing, is with the behavior of QWidgets.
I have used QMenu API for handling with menu. Problem is when a particular multilevel menu is opened, sometimes it is crossing the frame of the parent window.This thing should not happen in case of my project. I want the menu widget being displayed within the frame of parent window all time....
How to resolve this issue?

Use dialog controls without stealing focus

I have a modeless CDialog that contains controls, some CButtons and a CScrollbar. The CDialog is parented off of an edit box that I want to keep focus at all times. The problem is that whenever the user uses the controls, clicking a button or on the scrollbar, the control steals focus from the edit box, causing both the parent window to draw without focus (grayed-out header bar), and causing the control to take all the keyboard input. Is there a way for the controls to respond to mouse actions but not steal focus?
The controls and the dialog are all created with WS_CHILD. The controls are parented off the dialog, and the dialog is parented off of the edit box.
I've tried setting focus back after the controls are used, but that causes the parent window to flicker as it loses and then regains focus. Basically I want something that works like a combo box, where the scroll bar can be clicked or dragged around, but keyboard input still goes to the dialog itself, not just the scroll bar, and the whole thing never loses focus.
I haven't done anything like this for a long time, so I'm sure there are a million little details, but I think the starting point is to override the handling of WM_MOUSEACTIVATE.
I am a little confused about child-parent relationship you described.
Can you explain what do you mean by:
The CDialog is parented off of an edit box that I want to keep focus at all times
Any window hosting other windows inside of the client area is a parent of those windows. It is impossible to create window without WS_CHILD that is contained by other window.
Therefore all dialog’s controls are children of this dialog. It is also possible that child window hosts another child window.
CDialog is just an MFC representation of a dialog window; the same applies to other controls. For example CButton is an MFC class that wraps handle of the window’s window that is predefined as window button control.
Dialog never has focus unless is empty (does not have any controls). If dialog contains even one control, this control always has focus.
What focus means is that any given window receives mouse and keyboard messages. Only one control can have focus at any given time. In order for scroll bar to process mouse click or keyboard to move slider, scroll bar must have focus; therefore some other control must give it up.
Combo box drop box (I think this is what you are referring to) is not a child of the dialog. It is a popup window that for the duration has keyboard focus and captures mouse. When it drops down, dialog is deactivated and once dropdown hides, dialog state is changed back to active hence focus never changes, it returns to the control that had focus when dialog was deactivated.
What you are trying to do is probably possible but it would require a lot of coding. Probably hooking messages would do the job but I think it would be going against the stream.

Qt popup grabMouse for all children

I'm trying to create a popup menu like control that contains custom widgets. I need to capture the mouse, but I need to have the children in the widget still get their mouse messages. It appears the grabMouse sends events only to the widget that grabbed the mouse, not its children.
The popup is simply a series of buttons (using a QGridLayout). The control should work that the user presses the right-mouse button, the popup appears, they move to an item and release the mouse button. Optimally it would work exactly like a QMenu popup but with custom widgets and a custom layout.
How can I achieve this?
It appears that simply specifying attribute Qt::Popup is enough to get the fundamental behaviour required.
Installing an event filter on all children is also necessary. All mouse events, enter/leave/hover events must be captured. QT has a defect with grabMouse so that won't work -- the filter must be used to get expected behaviour.