QML Popups not working properly with C++ application - qt

I have an application in Qt in which I can switch between c++ app and QML app (setting central widget to one or other).
The problem is that in order to work this, I had to change my main.qml from ApplicationWindow to Page and now Dialogs and all Popups in my QML app are not working properly (modality and focus is not working at all).
My code looks like that:
QQuickWidget *view = new QQuickWidget(this);
view->setSource(QUrl(QStringLiteral("qrc:/main.qml"))); //Page
MyCppApp *myCppApp = new MyCppApp (this); //QWidget
QStackedWidget *stackedWidget = new QStackedWidget;
stackedWidget->addWidget(view);
stackedWidget->addWidget(myCppApp);
stackedWidget->setCurrentIndex(1);
setCentralWidget(stackedWidget);
I know in Popup's documentation there is that "It can be used with Window or ApplicationWindow." but is there a way to get Popups in my QML work properly?
I am using Qt 5.8 and Qt Quick Controls 2.

For the modality you should not make the dialog window part of central widget in main window (otherwise it is modal relative to what?). Invoke it from main window. And to give it modal dialog looks and behavior you can apply window flags like that:
// this view is not a part of the app main window
view->setFlags(Qt::Dialog | Qt::WindowTitleHint |
Qt::WindowStaysOnTopHint | Qt::MSWindowsFixedSizeDialogHint);
Mind that Qt::MSWindowsFixedSizeDialogHint is of course applicable on Windows only. And for setting the focus:
// to set the edit focus such trick needed
QTimer::singleShot(0, view, SLOT(setFocus()));
I use that with QML widget container. Implementation details may differ. And no QML part visible. There you may need to take care of FocusScope then.

Related

Make the objects' size of a GUI adapt to window

I created a GUI with Qt5 but I will like the objects to be always contained in the window. When I change the size of the window (with the mouse), the objects dont resize themselves and therefore are hidden by the window.
Basically, I will like my GUI to act like a Web Page for example.
I think I have to use the Layout properties to do that but I dont seem to find it in Qt (in the QBBoxLayout or QWidget ?). I will like to change this in Qt and not in my PyQt script if possible.
Have you set the layout of the window ?
Normally you should have a code similar to this one
dialog = QDialog()
verticalLayout = QVBoxLayout()
label1 = QLabel("first")
label2 = QLabel("second")
verticalLayout.addWidget(label1)
verticalLayout.addWidget(label2)
dialog.setLayout(verticalLayout)
if you are creating the gui writing the necessary the code yourself.
If you are creating the gui with the designer, probably you have not applied a layout to your window.

Rendering QML over another window using QWidget

I am currently using QWidget to embed a window from another library (Panda3D). I've been trying to see if it was possible to add a QML-based interface to Panda3D by rendering a QQuickView over the QWidget containing Panda3D's window.
When I don't initialize Panda3D, I can see my QQuickView being properly rendered over the widget: but when I do reparent Panda3D's window to the widget, then the window is rendered over the QQuickView.
I'd like to know if what I'm trying to do is possible, and if yes, how would I do such a thing ?

How to make app looks nice in Qt?

I want to know is it possible to make application fully skinned/styled in Qt I mean by that not only controls inside the application window but the mainwindow itself! like close button/maximize button/minimize button and the bar, and the mainwindow border!, is it possible to do that in Qt? and how to?
Yes it is possible. The best method in Qt is to use Qt style sheets. The Qt documentation has plenty of examples and you can style all the widgets, either by specifying a whole class such as QPushButton, or a single, named widget.
As for the items on the title bar, I'm not sure if that's possible directly, but you could certainly turn off the main tool bar that contains the minimise / maximise buttons and then implement and style your own widgets while replicating their functionality.
The second argument to the QWidget constructor is Qt::WindowFlags. You can use the flags to control the properties of a window. For example, pass the flag Qt::FramelessWindowHint to create a borderless window.
There are a few ways to do this in code. You can use the setWindowsFlag method from within your widgets constructor:
setWindowFlags(Qt::FramelessWindowHint);
If you are creating a custom widget, you can pass the flag to QWidget's constructor:
YourWidget::YourWidget(QWidget *parent) : QWidget(parent, Qt::FramelessWindowHint)
{
// ....
}
Or you can pass the flag when you create a widget:
QWidget *your_widget = new QWidget(parent, Qt::FramelessWindowHint);
There are also flags for the minimize button (Qt::WindowMinimizeButtonHint), maximize button (Qt::WindowMaximizeButtonHint), close button (Qt::WindowCloseButtonHint), and title bar (Qt::WindowTitleHint). With these flags, you must also set Qt::CustomizeWindowHint to disable the defaults as described in the documentation.
See the flags documentation for a full list and additional details.
As #Merlin069 stated, style sheets allow you to control the look and feel of the widgets within your application.

How to set QFileDialog's parent to a QQuickView

The only window in my application is a QQuickView which is a subclass of QWindow, not of QWidget, so if I want to use a QFileDialog to give the user the option to save a file, I do not know how to set its parent to be the QQuickView. I know that the QFileDialog works without a parent, but if it does not have a parent, it is not centered over the QQuickView. This is not a big problem on its own, but on my OS (Ubuntu 13.10) a QFileDialog without a parent sometimes appears under the QQuickView window and the user sees only a “flashing” taskbar icon.
I use Qt 5.2. I initially tried to use the FileDialog type in the Qt Quick Dialogs module but it does not have some features I need (such as the defaultSuffix property).
Right, this is a serious problem of QML. You cannot utilize the QFileDialog because you don't have a QWidget app and FileDialog lacks some critical features.
See: FileDialog in QTQuick (QML): Save file under given name
At the moment we are using code from deep down in the Qt source code, which is not in the public API. It only requires a Window instead of a Widget to do modality right.
Maybe I can write a blog post about that over Christmas.

Detecting click outside QWidget

My application has non-rectangular popup widgets.
their class defines the following to achieve that transparency:
setAttribute(Qt::WA_NoSystemBackground, true);
setAttribute(Qt::WA_TranslucentBackground, true);
I also use:
this->setWindowFlags(Qt::Popup| Qt::FramelessWindowHint);
The problem is that on windows 7, an automatic "shadow" is being drawn on the bottom and right sides of my window. This is highly undesirable.
So, I tried using Qt::Tool instead of Qt::Popup
this->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
This works visually. No shadow, but now a mouse click outside my widget window will not automatically close/hide it as it would have done with a Qt::Popup.
So, I need one of these two solutions:
A way to have Qt::Popup and get rid of that automatic windows shadow decoration
A way to let the Qt::Tool window a mouse click occurred outside of it.
One note: My application is built for Windows XP and up. I cannot use a Vista/Win7 only runtime DLLs, nor can i have a "Windows XP" and "Vista and up" separate builds.
Any advice will be welcome.
You could manually watch for when the focus changes from your Qt::Tool window. So basically you watch for when the focus goes onto another window of your process or when your application loses focus.
How to detect that my application lost focus in Qt?
Hope that helps.
Finally after realizing that no amount of "SetFocusPolicy" calls will allow me to receive those events for a Qt::Tool window, I've resorted to something else to fix my problem:
I kept the Qt:tool as Qt::Popup caused an undesired shadowing effect, tarnishing my owner draw frame. Removing this style cannot be done in Qt and I didn't want to mess with platform specific conditional code.
I installed an event filter with my Qt::tool window and I began receiving events that assisted me in understanding when other parts of my application were clicked, or if the application itself lost focus to another application. This was what I needed, functionality wise. I could also get an event when users click the non-client areas of the application's main window, such as the windows caption so that I can close it when dragging begins etc.
My solution for Windows 7:
QDialog *d = new QDialog;
d->setStyleSheet("background:transparent;");
d->setAttribute(Qt::WA_DeleteOnClose, true);
d->setAttribute(Qt::WA_TranslucentBackground, true);
#ifdef Q_OS_WIN
d->createWinId();
#endif
d->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint);
d->show();
I set my QListView
d->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint);
Install eventfilter and used MousePressEvent to hide qlistview widget.
MousePressEvent on list never comes to filter they produce other events which I didn't debug.
So if you want to design auto completer this will be perfect. Tested in Qt5.3.1.

Resources