Catching Qt modifier key releases - qt

I'm a newcomer to Qt, but I'm trying to implement what basically amounts to a video-game-esque input loop in a Qt application (crazy, I know, but see if you can help). I need accurate, one-to-one event handling for key presses and key releases, for all keys, including modifiers, no matter how weirdly you chord-up the keyboard.
Of course, your main access to key events is through QKeyEvent. But let's say the following happens:
user presses and holds Ctrl
user presses and holds Up
user releases Ctrl and Up simultaneously
As far as I can tell, what I get from Qt is:
QKeyEvent for the pressing of Ctrl, by itself (Qt::Key_Ctrl)
QKeyEvent for the pressing of Up, by itself (Qt::Key_Up)
QKeyEvent for the releasing of Ctrl+Up, with key() == Qt::Key_Up and the Ctrl bit reflected in a modifier change.
This may be not exactly accurate, but it's my best guess as to what's going on from way too much debugging of the issue. In any event, the key release events when modifiers are involved are incredibly unreliable.
The Ctrl+Up sequence there at the end is the problem. Now, I know I'm getting modifier state in e->modifiers(), and I'm getting the key press in e->key(). I could do some complicated hacks, trying to remember the modifier state internally, to detect when the user's released the modifier. But then, the Qt docs inform me, speaking of e->modifiers(), that:
This function cannot always be trusted. The user can confuse it by pressing both Shift keys simultaneously and releasing one of them, for example.
This is exactly the case I'm trying to avoid.
Is there any reliable way to keep track of one-to-one key presses and releases, for both normal and modifier keys, in Qt? If not, what's the closest you can get?
EDIT: I can refine this a little bit. It seems that if you hold down Cmd on a Mac, press a few keys (letter keys, say), release them, then release Cmd, you don't get release events for the letter key releases. I'm going to try to isolate a small example and see if this is actually a Qt bug.

I think if you are getting very specific with the keyboard, you are going to have leave Qt and get something that is OS specific, or you need to handle the Qt events before any filtering happens.
Handle Qt Events Before Filtering
Accelerators in Qt look for and wait on Alt+__ combos and you can set up Ctrl+__ combos to be listened to by QAction.
Both of these types of Objects built into QApplication and the general GUI environment, might be interrupting the messages you are getting, and giving you less than what you are expecting.
Qt Documentation: The Event System ... this part has a link to this...
QCoreApplication::notify() ... which tells the highest level that a Qt Application can be written to handle input using the Qt API:
Installing an event filter on QCoreApplication::instance(). Such an event filter is able to process all events for all widgets, so it's just as powerful as reimplementing notify(); furthermore, it's possible to have more than one application-global event filter. Global event filters even see mouse events for disabled widgets. Note that application event filters are only called for objects that live in the main thread.
OS Specific Keyboard Handling Alternative
If looking at debug statements from a Qt event filter installed at the level mentioned above yields the same results as what you mentioned in your question, then you will need to go to the OS specific keyboard input stuff. For example in Windows you would need to scan the keyboard and or look at the VK state of the whole keyboard and do something with it (with something like GetKeyboardState() ).

I know it's a bit late to answer this question. Still... I have the same problem with Mac key release events and there is an open bug QTBUG-36839.
On Windows you may implement keyboard hook to catch every key presses/releases. But even that is not reliable in some cases. E.g. if you will type lock screen shortcut after unlocking you will NOT see any key release. I guess there must be something similar to hook on Mac. If it is important to you to remember what exactly physical key user pressed - I think this is one of the best ways. At the same time, from my experience, doing something low-level takes a lot of time and may bring a weird bugs in cases you never could imagine. So the question is: are you sure you cannot make what you need with something like QAction?
Or maybe you could just use Control instead of Command in your shortcuts :)

Related

How to distinguish different sources of spontaneous QCloseEvent in Qt5?

in my application, I override QMainWindow::closeEvent in order to do some logic before closing the app.
The only argument this function gets is of type QCloseEvent, and it's called whenever the user tries to close the app.
It happens when we click the X button, of course, but depending on platform we also have things like alt+f4, rightclick->close and possibly more.
My goal here is to distinguish between these. More specifically, I need to know if just the X button was pressed or not.
From to the docs, which can be found here: https://doc.qt.io/qt-5/qcloseevent-members.html
I can't see anything that would help me get this information.
There is a function spontaneous(), which allows me to check if the event was triggered programmatically or by the environment/user, but in the case I'm presenting, every event has this value as true.
Unfortunately, I don't even know if this is possible.
I expect that it could work in a way that X11 or some other component in the system would just send the same signal for every case, but I don't really know where to look for this information.
Other questions that I've found on stack cover the spontaneous vs non-spontaneous cases, thus the didn't help me.
closeEvent() is called after the window is closed, not necessarily when the application is closed. Therefore, it's not called until after all the logic for the key is processed.
Override keyEvent() and use that function to run your key press logic.
Documentation here

tcltk block input while processing in r

RGTK2 block user input while processing its explain how to block user input using RGTK2 but I dont know how to add that code to my GUI code, im using tcltk. What I want same like in RGTK2 block user input while processing but using tcltk2
I use this code to run button "filter cluster" and the command function is filter (function to do something)
tkpack(tkbutton(f4, text='Filter Cluster', command=filter), side='left',padx= 5, pady = 20)
In tcltk, you would use tkgrab.set on a non-responsive window and tkfocus on a window that has a binding on the <Key> event that prevents further processing. An inconspicuous tkframe is great for that sort of thing — set it to size 1×1, but ensure it is on the screen — as it has no default behaviour to get in the way. (You'll also want to make a bunch of cosmetic changes, such as marking the widgets as disabled and setting the cursor to watch.) In 8.6, there's tk busy (call with tcl("tk","busy",…) since the Tcl tk command appears to not have a convenient mapping) which makes this all much easier (though I don't know if/how that's mapped into R). The simplest way to release a grabbed window is to destroy it, but you can also tkgrab.release.
Do not use a global grab. They're easy to get wrong and can cause you a lot of grief. (If you insist, you're strongly recommended to make mouse activity cancel it and to test very thoroughly. Locking up your display is not a pleasant experience!) The default local grabs are less of a problem, since you can switch to another program and kill off a stuck app if necessary.
The full documentation for Tk (and Tcl) is online; pick the version of the docs for the version of the library that you're using, probably 8.5, hopefully 8.6 ('cos it has some nice extras) and possibly 8.4 (old skool!) As the R documentation for tcltk says, you can invoke anything in Tcl or Tk through tcl(…), passing in the words of the command name and arguments as many strings… (Tcl is a naturally var-args language and uses that extensively.) The limited scope of the default convenience mapping should not hinder you substantively.
General advice, not so closely related to your question
Most Tk programmers try to write their code to not lock users out that way if possible. You get a better user experience if you can keep the GUI responsive and instead just temporarily disable (via the state option on most reactive widgets) the parts that would otherwise trigger reentrancy problems for the duration. (The long-running processing might be also event-driven, or put in another thread, or even delegated to a sub-process. Just remember, Tk GUIs are strictly single threaded — the implementation assumes this very deeply, though it's possible to have wholly independent apps in different threads, if rather hairy to get working right — so you've got to come back to the GUI thread to update anything in the GUI.)

How can I stop Qt::ForbiddenCursor from appearing during a drag?

I'm implementing a drag and drop interface with Qt across X11 and Windows. The interface handles events such that it is not illegal for a user to drop a dragged object on an area which can't handle drops.
In this case, Qt::IgnoreAction should therefore not be treated as an incorrect potential action. To communicate this fact to the user I need a way to stop Qt::ForbiddenCursor from displaying if the current Qt::DropAction is Qt::IgnoreAction.
There are three ways I can see to achieve this (in order of preference):
To override the QCursor used for a drag with Qt::IgnoreAction to something other than Qt::ForbiddenCursor.
To override the bitmap used for Qt::ForbiddenCursor. This is pretty dirty but would be an acceptable solution as long as I don't have to delve into OS-specific configuration.
To override the call made by Qt when a drag leaves a valid drop area (I assume that Qt does the equivalent of QDropEvent::setDropAction(Qt::IgnoreAction) in this case).
Could anyone suggest ways to acheive any of the above?
Note: I have also attempted to use QApplication::setOverrideCursor() just before calling QDrag::exec(). This doesn't seem to have any effect.
Check if QDragEnterEvent comes to application itself (install event filter on QApplication object). If it does, simply accept it and cursor will appear normal.

Save current state of entire GUI in Qt?

I have an app written in Qt that has many widgets, including lists, tables, trees, line edits, etc. As the user progresses through the app, they may need to save the current state, leave, and come back later to pick up where they left off. I do not have a the data separate from the GUI (all data is stored in the widgets themselves). I have found a way to loop through all the widgets and save the current state, but it takes a significant amount of time. Is there a faster or built in way to save the current state of the GUI? I am trying to avoid re-writing the code to have a data model that is only represented by the GUI due to limited time available.
Is Qt's session management what you're looking for?
You can save every param on its actual change, or when user leaves the page, not on exit. And don't try to save every parameter of every widget, use smarter algorithm
As a good crossplatform and flexible way to save state of your GUI is to use Qt's mechanism -- QSettings (official documentation).
But, really, there are re-writing moments, which you can't avoid.

Notes and remarks over the GUI

I am developing a flex application for collaborative data analysis. To present the data my application uses standard and custom components (grids, charts etc.).
I want to deliver the feature that allows users making notes over the GUI of my application. So, other users will see they notes late on.
At the moment my question is: How can be implemented mechanism that allows making notes over the GUI? All suggestions and examples are welcome?
There are a lot of ways to approach this. ( Check out Buzzword, MS Word, and Acrobat all for slightly different approaches of note taking on a document--I assume an application GUI could use any of the same approaches ).
I'd start by saying that the click event bubbles:
http://livedocs.adobe.com/flex/3/langref/flash/display/InteractiveObject.html#event:click
So, listen for the click event on every child of your main application file. When you receive that click event you can provide some business logic as to whether or not you want to add a comment /note on the component that was clicked. Then you just some "note" component for collecting and displaying the note data. You an position them based on the x, y values of the click event.
So, actually my problem is much easier then I expected (thank for great design of Flex).
I decided to utilize PopUpManager functionality for my task. It does everything I need at the moment.

Resources