QTextEdit receives Control Key doesn't pass to main window - c++

I have a QTextEdit on my QMainWindow. I have overridden my main window keyPressEvent method and put a few hotkey handlers in there (ie: Ctrl+J, Ctrl+K). These hotkeys are global to the application.
The issue I have is that when the QTextEdit widget has focus, these key presses seem to be consumed by the widget and never seen by the form. The interesting thing is that these key combos do nothing in the QTextEdit.
How can I have the QTextEdit ignore key combinations that it has no behaviour associated with? Alternatively, how might I accomplish my goal in Qt?

Whichever widget has the keyboard focus will nominally consume all keyboard events. There's no notion of an "unhandled" keyboard event. Qt's event semantics for keyboard events don't work that way.
You need to use a QShortcut. Internally, it acts as an application-wide event filter for keystroke sequences, it's tied into the private implementation of QApplication. The only other way for you to do it would be to act as an application-wide event filter that acts on keystroke events.

Related

What signal can Qt Widget catch from Virtual Desktop?

I have a C++ app which pops up a QDockWidget. I want this widget to close when the user clicks outside the widget, and have achieved this using the eventFilter() to catch the event QEvent::WindowDeactivate, and call Hide().
I also need the QDockWidget to close when the user changes desktop - and this doesn't require a mouse click. (Windows virtual desktop).
I've looked for some other appropriately named QEvent but no luck. My QDockWidget allows user input via keyboard, so I can't use keyboard focus for hiding.
What signal or event could I watch for to Hide() when a user changes windows desktop?

How do I pass QEvents to child widgets?

Here's the situation:
I have a custom widget subclassed from QTabWidget that I've implemented to accept QDropEvents for files. When files are dropped on the TabWidget they are opened for editing. This part works fine. However, I want to implement drag and drop functionality as part of the editor (think like a LabView-esque GUI). I have properly implemented the event handlers and acceptsDrops on the EditorWidget but the TabWidget receives all the events and attempts to process them as files. I can differentiate file-related events from the editor's events by mimedata but I can't figure out how to pass the event from the TabWidgeton to the appropriate EditorWidget.
So the question:
How can I pass a QDropEvent from the widget which received it from the system to another widget which it owns? Alternatively, how do I tell the system which widget should receive the event, based on the contents of said event?
What I've tried:
I can't call the dropEvent method of the child as it's protected. I could create a series of my own methods that pass the events around but that seems redundant and fragile. I've looked into installing an EventFilter, but from what I can tell that only discards events, it doesn't say "not me try someone else."
Thanks in advance for your assistance!
Intersting! I think that accepting the event in the parent widget, and then trying to forward it to the child widget, is not the right approach architecturally. It would basically violate encapsulation (objects handling their own events).
If I were you, I would investigate why the child widget isn't seeing the event first. Children widgets are on top of their parents, so your child widget should have a first go at the event. Did you call setAcceptDrops(true)?
When you fix that, in the child widget event handler you can analyze the event and call event->ignore() if the event should be forwarded to the parent QTabWidget. If you don't call ignore(), the child will "consume" the event and it will not be propagated to the parent!
Here's an old blog post on event propagation that could help:
http://blog.qt.io/blog/2006/05/27/mouse-event-propagation/
Solving my own problem:
As Pliny stated the child should see the event first. My problem appears to have been that in EditorWidget I had not implemented dragEnterEvent and dragMoveEvent so even though I had implemented dropEvent in EditorWidget the TabWidget took control of the drag and therefore stole the drop.

Qt/QML: How to activate a Shortcut from C++?

I have an application which receives input from a serial port and interprets them as key events. The key events are created in C++ and sent to QGuiApplication::focusWindow() with qApp->sendEvent.
The GUI is implemented in QML and has been handling input through key event handlers. I would like to start using the Shortcut QML class to handle cases where I want behavior regardless of which object has focus.
I've discovered that Shortcuts which respond to a real keyboard will not respond to qApp->sendEvent, nor do they respond to qApp->postEvent.
Getting the behavior I want to reliably occur without Shortcut would be a real pain - is there I way I can handle my synthetic events which will make them visible to Shortcut?
Qt shortcut objects work through parts of the Qt system which are not part of the regular API, but are exposed to QPA. Specifically, QWindowSystemInterface::handleShortcutEvent, which takes as arguments the current focus window and most of the information encapsulated in a QKeyEvent.
// A helper to send a QKeyEvent to shortcuts
bool handleShortcutEvent(const QKeyEvent &ev, QWindow *focusWindow) {
return QWindowSystemInterface::handleShortcutEvent(focusWindow, ev.timestamp(), ev.key(), ev.modifiers(), ev.nativeScanCode(), ev.nativeVirtualKey(), ev.nativeModifiers(), ev.text(), ev.isAutoRepeat(), ev.count());
}
// in my key event generating function
if(!handleShortcutEvent(event, focusWindow))
qApp->sendEvent(focusWindow, &event);

Handle EVT_CHAR in wxFrame or wxDialog

As we all know, EVT_CHAR is a basic event which don't propagate to wxTopLevelWindow(wxFrame and wxDialog).
But I have a wxDialog without any wxWidgets controls on it, and need to handle user keyboard input (handle EVT_CHAR event).
I saw the wiki about catch key events globally, but it's not work on EVT_CHAR event as EVT_CHAR event need to be translated to get user input
And I have try to have wxDialog a hided children wxWindow which foward EVT_CHAR to its parent wxDialog. It works on Windows platform, and not on OSX which is my target platform.
Is there a way to implement it ?
Why do you need to handle all keyboard entry in the dialog itself? There are two typical cases for this that I know of: either you want to handle the key presses in several different controls in the same way, or you need to handle some particular key press (e.g. WXK_F1) in all controls. The former can be done by binding the same event handler to several controls. The latter -- by using accelerator table with an entry for the key that you want to handle specially.
Finally, I implemented what I want according to this:
http://trac.wxwidgets.org/ticket/15345
In wxWidgets 3.0, wxNSView implementes NSTextInputClient protocol, which makes every widgets can handle EVT_CHAR correctly.
But EVT_CHAR still cannnot be handle by wxDialog or wxFrame, because of some call of IsUserPanel() function. So I commented some call of IsUserPanel to make it work for me.

Preventing Mouse-wheel scrolling of controls

I am developing an application using the MFC library and I am currently trying to prevent the user accidentally changing one of the combo box controls when they are scrolling the mouse wheel.
I am looking for a solution without deriving a new class from the CComboBox class and preventing the mouse scrolling there.
My understanding of the system is that Windows passes the WM_MOUSEWHEEL message to the Combo box control which handles it (scrolling the combo box) and then this is propagated up the chain of parent controls (so them to my CFormView etc.), which means I cannot prevent the scrolling by capturing the event in my form view.
Does anyone have a solution to this problem? Thanks in advance!
You can always derive a control from CComboBox and trap the WM_MOUSEWHEEL message in the control itself. Then simply use your new derived combo box in your form view.
If you don't want to create a derived class (perhaps it's too big a change for your project), you can subclass the combo box and trap the WM_MOUSEWHEEL there.
Override the PreTranslateMessage handler in the main window class and look for WM_MOUSEWHEEL messages. Compare the pMsg->hwnd handle in PreTranslateMessage handler with the combobox handle, if found, filter the messages away.