14
votes

How do I add detachable areas to a QML ApplicationWindow?

Take the following application (Tiled) as an example. It has multiple detachable areas. In the first image all areas are attached, while in the second one area is in the process of being detached/reattached:

enter image description here

From C++ this can be realized with QDockWidget (see this question). But is there a solution with QML?

3
At the close vote: Please explain why it's too broad. I'm pretty sure there is either a predefined class for this functionality or a specific way to create detachable areas.Appleshell
I have not seen that functionality directly in QML. It's easily possible to create floating areas but I suspect you want a detachable window. It's not terribly useful if the device is a phone so it's probably pretty low on their priority listJay
@Appleshell I am currently facing the same problem. I had a look in the Qt doc but I didn't find anything so I think it isn't implemented yet. Do you find a solution in pure QML?SteveTJS
@SteveTJS scroll down to my answer. I made a small exampleMaxim Skvortsov
Take a look at my related work github.com/HamedMasafi/qmldockHamed Masafi

3 Answers

3
votes

I made a simple working example. You can find it here. There must be enough comments for you to sort it out.

I used dynamic creation of objects like that:

  • dynamically create component(DetachableItem.qml) and assign it to property(not necessary, but it is easier to find it)
  • create connection for this component's attached property, where I can call some function when it changes;
  • move the item into another window pushing the object into it's data property
  • move it back the same way - pushing it to data property of main window and hiding separate window.

Feel free to ask question or proposing some improvements. I am interested in any suggestions how to improve it!

UPD: I updated the example with new commit where I got rid of dynamic objects creation. If you are still interested in dynamic object creation, you can checkout to this commit

1
votes

Just an idea on how to achieve such behaviour. Have a look at the Window QML class and dynamic object creation to actually create a window by request.

Some (UNTESTED) pseudo-code, just to give an idea "DockWindow.qml":

import QtQuick 2.0
import QtQuick.Window 2.2

Rectangle {
 id: dockWidget

 property Window window: null
 property Item embedIn: null
 parent: window ? window : embedIn
 readonly property bool detached: window

 function detach() {
  if (!window) {
   window = Qt.createQmlObject('
    import QtQuick.Window 2.2
    Window { flags: …; }
    ', dockWidget, "dockWidget");
  }
 }

 function close() {
  if (window) {
   window.close();
  }
 }
}

Note: This code will not work out of the box and probably leads to a dependency loop on the "parent" property!

1
votes

As one possible solution you can create custom QDialog, use inside it QQuickView with desired qml stuff loaded from appropriate qml file. Communication with your main qml window and dialog will be done through Q_PROPERTY and Q_INVOKABLE defines in your custom dialog.

The pointer to your QDialog instance, for example, can be propagated to the QML as context property with help of QQmlContext::setContextProperty.