Dockable window implementation in qml
Unsolved
QML and Qt Quick
-
Hi,
I am trying to create a dock able window in qml , it kind of works partially correct but when i first undock it by dragging the window, it does not place the window at the mouse pointer i am not able to understand what i am doing wrong?
can anyone help me in fixing it ?
here is my code :
import QtQuick import QtQuick.Controls import QtQuick.Window import QtQuick.Controls.Material Item { id: root default property alias contents: placeholder.data property alias title: titleLabel.text implicitHeight: mainWindow.height - statusBar.height - 15 Rectangle { id: content anchors.fill: parent height: implicitHeight state: "docked" border.color: "slategrey" border.width: 1 ToolBar { id: toolBar implicitHeight: 30 Material.foreground: "white" Material.background: "#dcdcdc" anchors { top: parent.top; left: parent.left; right: parent.right } Label { id: titleLabel color: "black" anchors { left: parent.left; leftMargin: 8; verticalCenter: parent.verticalCenter } } MouseArea { id: dragMouseArea anchors.fill: parent hoverEnabled: false acceptedButtons: Qt.LeftButton | Qt.RightButton propagateComposedEvents: true property variant clickPos: "1,1" /*onPressed: (mouse) => { clickPos = Qt.point(mouse.x,mouse.y) if (content.state === "docked") { let globalMousePos = mapToGlobal(Qt.point(mouse.x, mouse.y)); var new_x = globalMousePos.x; var new_y = globalMousePos.y; let relativePosW = mapToItem(undockedContainer, Qt.point(mouse.x, mouse.y)); window.x = new_x ; window.y = new_y // Set the initial position of the window when undocked //window.x = new_x //window.y = new_y } }*/ /*onPositionChanged: (mouse) => { var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y) var new_x = window.x + delta.x var new_y = window.y + delta.y if (content.state === "docked") { // Check if the mouse is outside the bounds of the docked area if (mouse.y < toolBar.height || mouse.x < 0 || mouse.x > parent.width) { content.state = "undocked" // Move the window to the mouse position window.x = new_x window.y = new_y } } else { // Get the maximum x and y positions for the undocked window var max_x = Screen.desktopAvailableWidth - window.width var max_y = Screen.desktopAvailableHeight - window.height // Update the window position, making sure it stays within the screen bounds if (new_x < 0) new_x = 0 if (new_x > max_x) new_x = max_x if (new_y < 0) new_y = 0 if (new_y > max_y) new_y = max_y window.x = new_x window.y = new_y } }*/ property point relativePos; onPositionChanged: (mouse) => { // get the mouse pos in screen coordinates let globalMousePos = mapToGlobal(Qt.point(mouse.x, mouse.y)); var new_x = globalMousePos.x; var new_y = globalMousePos.y; if (content.state === "docked") { // Check if the mouse is outside the bounds of the docked area if (mouse.y < toolBar.height || mouse.x < 0 || mouse.x > parent.width) { console.log("Initial window position: " + new_x + " " + new_y); content.state = "undocked" // store the click point where the drag started relativePos = mapToItem(toolBar, Qt.point(mouse.x, mouse.y)); console.log("relativePos window position: " + relativePos.x + " " + relativePos.y); window.x = new_x - relativePos.x ; window.y = new_y - relativePos.y ; } } else { console.log("Move the window to the mouse position: " + new_x + " " + new_y); window.x = Math.max(0, Math.min(new_x - relativePos.x, Screen.desktopAvailableWidth - window.width)); window.y = Math.max(0, Math.min(new_y - relativePos.y, Screen.desktopAvailableHeight - window.height)); } } onClicked: (mouse) => { if (mouse.button === Qt.RightButton) contextMenu.popup() } //Adding a right click menu as well Menu { id: contextMenu spacing: 0 MenuItem { id: dockMenu; text: "Dock"; onClicked: content.state = "docked"; implicitHeight: 30} MenuItem { id: unDockMenu; text: "Float"; onClicked: content.state = "undocked" ; implicitHeight: 30} } //Adding a button on the right corder, to give users some hint on docking/undocking, since right click is not that obvious Row { anchors { right: parent.right; verticalCenter: parent.verticalCenter; } Button { icon.source: "inverted-triangle.svg" flat: true width: 20 Material.foreground: "black" text: qsTr("▶"); rotation: 90 //Preferred would be show an image here onClicked: { contextMenu.popup() } } } } } Item { id: placeholder anchors { top: toolBar.bottom; left: parent.left; right: parent.right; bottom: parent.bottom } } states: [ State { name: "undocked" PropertyChanges { target: root; height: 0 } PropertyChanges { target: window; visible: true } ParentChange { target: content; parent: undockedContainer } //PropertyChanges { target: window; visible: true; x: 250; y: 250 } //this is to make sure the width becomes zero and rest of the control takes the realstate PropertyChanges {target: navigationWindow; width: 0 } PropertyChanges {target: toolBar; Material.background: "#f0e68c" } PropertyChanges {target: unDockMenu; enabled: false } PropertyChanges {target: dockMenu; enabled: true } }, State { name: "docked" PropertyChanges { target: root; height: implicitHeight } PropertyChanges { target: window; visible: false } ParentChange { target: content; parent: root } PropertyChanges {target: unDockMenu; enabled: true } PropertyChanges {target: dockMenu; enabled: false } } ] } Window { id: window width: 250; height: 700; flags: Qt.FramelessWindowHint Item { id: undockedContainer anchors.fill: parent } onClosing: { content.state = "docked" } } }
-
Hi,
I am trying to create a dock able window in qml , it kind of works partially correct but when i first undock it by dragging the window, it does not place the window at the mouse pointer i am not able to understand what i am doing wrong?
can anyone help me in fixing it ?
here is my code :
import QtQuick import QtQuick.Controls import QtQuick.Window import QtQuick.Controls.Material Item { id: root default property alias contents: placeholder.data property alias title: titleLabel.text implicitHeight: mainWindow.height - statusBar.height - 15 Rectangle { id: content anchors.fill: parent height: implicitHeight state: "docked" border.color: "slategrey" border.width: 1 ToolBar { id: toolBar implicitHeight: 30 Material.foreground: "white" Material.background: "#dcdcdc" anchors { top: parent.top; left: parent.left; right: parent.right } Label { id: titleLabel color: "black" anchors { left: parent.left; leftMargin: 8; verticalCenter: parent.verticalCenter } } MouseArea { id: dragMouseArea anchors.fill: parent hoverEnabled: false acceptedButtons: Qt.LeftButton | Qt.RightButton propagateComposedEvents: true property variant clickPos: "1,1" /*onPressed: (mouse) => { clickPos = Qt.point(mouse.x,mouse.y) if (content.state === "docked") { let globalMousePos = mapToGlobal(Qt.point(mouse.x, mouse.y)); var new_x = globalMousePos.x; var new_y = globalMousePos.y; let relativePosW = mapToItem(undockedContainer, Qt.point(mouse.x, mouse.y)); window.x = new_x ; window.y = new_y // Set the initial position of the window when undocked //window.x = new_x //window.y = new_y } }*/ /*onPositionChanged: (mouse) => { var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y) var new_x = window.x + delta.x var new_y = window.y + delta.y if (content.state === "docked") { // Check if the mouse is outside the bounds of the docked area if (mouse.y < toolBar.height || mouse.x < 0 || mouse.x > parent.width) { content.state = "undocked" // Move the window to the mouse position window.x = new_x window.y = new_y } } else { // Get the maximum x and y positions for the undocked window var max_x = Screen.desktopAvailableWidth - window.width var max_y = Screen.desktopAvailableHeight - window.height // Update the window position, making sure it stays within the screen bounds if (new_x < 0) new_x = 0 if (new_x > max_x) new_x = max_x if (new_y < 0) new_y = 0 if (new_y > max_y) new_y = max_y window.x = new_x window.y = new_y } }*/ property point relativePos; onPositionChanged: (mouse) => { // get the mouse pos in screen coordinates let globalMousePos = mapToGlobal(Qt.point(mouse.x, mouse.y)); var new_x = globalMousePos.x; var new_y = globalMousePos.y; if (content.state === "docked") { // Check if the mouse is outside the bounds of the docked area if (mouse.y < toolBar.height || mouse.x < 0 || mouse.x > parent.width) { console.log("Initial window position: " + new_x + " " + new_y); content.state = "undocked" // store the click point where the drag started relativePos = mapToItem(toolBar, Qt.point(mouse.x, mouse.y)); console.log("relativePos window position: " + relativePos.x + " " + relativePos.y); window.x = new_x - relativePos.x ; window.y = new_y - relativePos.y ; } } else { console.log("Move the window to the mouse position: " + new_x + " " + new_y); window.x = Math.max(0, Math.min(new_x - relativePos.x, Screen.desktopAvailableWidth - window.width)); window.y = Math.max(0, Math.min(new_y - relativePos.y, Screen.desktopAvailableHeight - window.height)); } } onClicked: (mouse) => { if (mouse.button === Qt.RightButton) contextMenu.popup() } //Adding a right click menu as well Menu { id: contextMenu spacing: 0 MenuItem { id: dockMenu; text: "Dock"; onClicked: content.state = "docked"; implicitHeight: 30} MenuItem { id: unDockMenu; text: "Float"; onClicked: content.state = "undocked" ; implicitHeight: 30} } //Adding a button on the right corder, to give users some hint on docking/undocking, since right click is not that obvious Row { anchors { right: parent.right; verticalCenter: parent.verticalCenter; } Button { icon.source: "inverted-triangle.svg" flat: true width: 20 Material.foreground: "black" text: qsTr("▶"); rotation: 90 //Preferred would be show an image here onClicked: { contextMenu.popup() } } } } } Item { id: placeholder anchors { top: toolBar.bottom; left: parent.left; right: parent.right; bottom: parent.bottom } } states: [ State { name: "undocked" PropertyChanges { target: root; height: 0 } PropertyChanges { target: window; visible: true } ParentChange { target: content; parent: undockedContainer } //PropertyChanges { target: window; visible: true; x: 250; y: 250 } //this is to make sure the width becomes zero and rest of the control takes the realstate PropertyChanges {target: navigationWindow; width: 0 } PropertyChanges {target: toolBar; Material.background: "#f0e68c" } PropertyChanges {target: unDockMenu; enabled: false } PropertyChanges {target: dockMenu; enabled: true } }, State { name: "docked" PropertyChanges { target: root; height: implicitHeight } PropertyChanges { target: window; visible: false } ParentChange { target: content; parent: root } PropertyChanges {target: unDockMenu; enabled: true } PropertyChanges {target: dockMenu; enabled: false } } ] } Window { id: window width: 250; height: 700; flags: Qt.FramelessWindowHint Item { id: undockedContainer anchors.fill: parent } onClosing: { content.state = "docked" } } }
-
Hi QML experts,
Can anyone help me in resolving/fixing the issue that I am facing?
Thanks,