What signal can Qt Widget catch from Virtual Desktop? - c++

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?

Related

intercept and ignore a wheel event in a QTabWidget

I implement a UI with Qt. My UI is a mainwindow containing some widgets, and a supervisor to manage my widget behaviors. In one of my widget, outputDataWidget, I have a QTabWidget, and some other widgets.
In my tabWidget, I have a dataEditor to show points, and I create a "+" tab, to create a new tab. The tab creation is done by a connect function, which is in the mainwindow:
connect(outputWidget.get(), SIGNAL(SIG_createNewOutput(int)), projectSupervisor.get(), SLOT(sCreateNewOutput(int)));
My problem is: when we use the wheel mouse button in the tab header to go rigth, some new page are created. I would like intercept the signal and avoid the creation of a new tab.
I try to add a filter event in the mainwindow and in the outputdatawidget to ignore the wheel event. Then I try to reimplemeted wheelEvent(QWheelEvent* we) and event(QEvent *e) of the QTabWidget. Each time, we enter in thiese modification after call the connect (create the tab).
Have you an idea how to call the event before the connect, or how I can disable the wheelevent of a QTabWidget?
Thanks
You'll have to subclass QTabBar to handle the QWheelEvent, then call QTabWidget::setTabBar during initialization.
This is necessary because QTabWidget internally uses a QTabBar with Qt::WheelFocus, so the wheel event never propagates to the tab widget.

Adding CDialog inside CDockablePane and application becomes unresponsive

I want to add a CDialog control inside CDockablePane. When I use CDialog.DoModal() to display the dialog window, it makes the MFC application unresponsive and waiting for the CDialog result.
How can I make the application display the dialog and continue running without waiting for the CDialog result?
You cannot use DoModal to display the dialog. That displays a modal dialog, which prevents interaction with any other windows in your application until the dialog has been dismissed. Just like a message box does.
To display a non-modal dialog, you call the Create member function. Use the instance of your CDockablePane as the dialog's parent. You will also need to ensure that the dialog itself is a child window, without a border.
It might be easier to use a class derived from CFormView or CPaneDialog.

QTextEdit receives Control Key doesn't pass to main window

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.

Qt 5 - How to send data back from child dialog in real time

I have a settings dialog that has some settings that require another dialog to fully configure. My window shows a preview of the data as it's being tweaked by these settings. Upon clicking on the configuration button I launch another modal dialog with some knobs to twist to fine tune the particular setting.
I wish to send the result of the twisting of the knobs on the child dialog back to the parent dialog so that it can show the new preview data as the knobs on the child are being played with. The way I imagine it is I have a "refresh preview" function in the parent that is called after modification of it's data preview member variables. The question is, how do I do this? How can I access getters/setters from the parent dialog as a modal child dialog? If I do access them will the preview change or will it be blocked because of the modality of the child?
Thank you!
In Qt world, it is generally encouraged to exploit the Signal/Slot mechanism. In short, classes can send signals when something changes within that class. And slots can receive such signals provided we notified the receiving classes appropriately.
Let us look at how we can do it for our present case.
In our settings dialog constructor, we include this code (assumption is that you display the "another" dialog when a button is pressed):
Dialog *dialog = new Dialog();
connect(dialog->dial(), &QDial::valueChanged, this, &QSettingsDialog::changeTemp);
Code walkthrough:
Our QDialog has been constructed with a QDial object, dial. We access that member pointer with dialog->dial().
We tie the signal that emits the value changed on the dial to the slot called changeTemp that receives the value changed and sets the display widget on the settings dialog (parent) accordingly.
The changeTemp method might be like so:
void QSettingsDialog::changeTemp(int val)
{
lineEdit->setText(QString::number(val));
}
Notes:
You need to declare the Q_OBJECT macro on all classes that need to implement Signals and slot. In this case, both the settings dialog and the child dialog.
The above signal/slot signature is the new Qt5 signature. If you are on a version below 5.0, the signature is different. Refer to the docs.

How to disable user interaction in a Qt application when a DialogBox shown?

I have a modeless QDialog box that popup on errors/warning in my Qt application, I want to force the user to only focus on that dialog box and not click anything in the application until they clicked Ok on the dialog box.
I need the dialog box to remain modeless. A solution like hiding the main window or covering it up is not acceptable.
At the moment I'm using setModal(true); to solve my problem. But I think this method might be stopping the main application from executing.
From the documentation:
If you use show() and setModal(true) together to perform a long
operation, you must call QApplication::processEvents() periodically
during processing to enable the user to interact with the dialog.
Instead of using a QDialog box, try using qDebug statements in your code or a log file using qInstallMsgHandler.
You could also show a QTextEdit and post your log/error messages there in real time, too.
http://qt-project.org/doc/qt-4.8/debug.html
http://qt-project.org/doc/qt-4.8/qdebug.html#details
http://qt-project.org/doc/qt-4.8/qtglobal.html#qInstallMsgHandler
http://qt-project.org/doc/qt-4.8/qtextedit.html#details
If you still really want to debug using a QDialog box for errors, in a pseudo modal dialog but not modal dialog, you could try using eventFilters to prevent mouse and keyboard events from arriving at any other window, but it would be tricky to allow the exception to end up only at QDialog, but it is do-able.
You could also go to the one or two widgets that accept mouse and keyboard input, and ignore the input if the a QDialogBox is visible. But both of these ways of showing an error, but limiting input without making it Modal is really hacky, and would probably be error prone.