Discussion:
[Interest] qml desktop corner
Damian Ivanov
2013-06-25 08:55:28 UTC
Permalink
Hi all,

Is there a way to anchor the whole qml application to an desktop edge
(e.g like a side bar with icons and stuff).
Something like anchor.app.desktop.left/right/bottom/top or is C/C++
detecting resolution and stuff absolutely necessary for that?

Thanks
Rutledge Shawn
2013-06-25 11:48:16 UTC
Permalink
Post by Damian Ivanov
Hi all,
Is there a way to anchor the whole qml application to an desktop edge
(e.g like a side bar with icons and stuff).
Something like anchor.app.desktop.left/right/bottom/top or is C/C++
detecting resolution and stuff absolutely necessary for that?
No anchors yet, but you access the screen width and height from QML, so I've been experimenting with stuff like that too.

Anchoring a splash window to the center of the screen is not hard, although anchors would make it more elegant. (see qtdeclarative/examples/quick/window/Splash.qml) Doing static anchoring to a screen edge isn't much harder, but I wanted to try animating the window position, to have it fly out whenever you mouse over it.

In QML the edge-anchored flyout window is sortof possible now that the Screen attached property has the screen width and also the desktop available width (excluding whatever existing menus, task bars and docks you might have). I'll include my experiment below.

It's not an official example yet because
1) the Screen attached property is still incomplete, you can't get everything that you can in QScreen. I already fixed that, but ran into too much resistance in code review, see https://codereview.qt-project.org/#change,48480
2) because the screen geometry information is incomplete, you cannot use this example on a virtual desktop consisting of two screens where the secondary is to the right of the primary. You can modify it to use Screen.desktopAvailableWidth instead of Screen.width, but then it will not work on a desktop where the secondary is to the left of the primary.
3) there is a focus issue, so mouse-over (MouseArea.hoverEnabled) doesn't work the same on every platform. (You might have to click on the window before it flies out)
4) the performance of window geometry animation depends on the window manager, so it will be jerky on some platforms
5) yes Alan wants to add something like anchors eventually, so then this example could be done elegantly; but it's not done yet, and it's not easy to do because a Window is not an Item, so the existing anchors attached property cannot be reused as-is. In an ideal OO language, there should have been an inherited class (or interface or mixin) which specifies rectangular geometry without assuming that it's a renderable thing like an Item, and then pointers in anchors and other places should use that type instead of QQuickItem *. But we always use single inheritance because only the top class in the inheritance chain can inherit QObject. The point of putting the rectangular geometric accessors in a mixin would be to have them be properties too; but moc only looks at the properties that are declared in the header that it's looking at. (Somebody correct me if this is actually possible somehow.) QQuickWindow inherits QWindow which inherits QObject; and QQuickItem inherits QObject. They are in different modules, too. So that's why it's hard to have a common inherited interface which the anchors could use, even though they are both just rectangles from the anchors' perspective. This is the situation that Interface is good for in Java.

But subject to those caveats, this example works for me on a single screen:

import QtQuick 2.1
import QtQuick.Window 2.1

Window {
id: root
width: 200
height: 200
visible: true
y: 40
property int xOpen: Screen.width - 10
property int xClosed: Screen.width - root.width + rect.radius
color: "transparent"
flags: Qt.FramelessWindowHint
Component.onCompleted: {
root.x = xOpen
root.y = 40
}

Rectangle {
id: rect
anchors.fill: parent
radius: 40
border.color: "white"
border.width: 3
color: "#D0444422"
antialiasing: true
Rectangle {
anchors.fill: parent
anchors.margins: 1
border.color: "black"
border.width: 2
antialiasing: true
color: "transparent"
radius: parent.radius
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: state = "stateOpen"
onExited: state = "stateClosed"
onClicked: state = "stateOpen"

//~ onStateChanged: console.log("state " + state)

states: [
State {
name: "stateOpen"
},
State {
name: "stateClosed"
}
]

transitions: [
Transition {
from: "stateOpen"
to: "stateClosed"
NumberAnimation {
target: root
properties: "x"
to: root.xOpen
from: root.xClosed
duration: 1000
easing {type: Easing.OutBounce; overshoot: 5}
}
},
Transition {
from: "stateClosed"
to: "stateOpen"
NumberAnimation {
target: root
properties: "x"
from: root.xOpen
to: root.xClosed
duration: 1000
easing {type: Easing.OutBounce; overshoot: 5}
}
}
]
}
}
}
Damian Ivanov
2013-06-27 17:45:52 UTC
Permalink
Thanks! Did what I was trying to :)
Post by Rutledge Shawn
Post by Damian Ivanov
Hi all,
Is there a way to anchor the whole qml application to an desktop edge
(e.g like a side bar with icons and stuff).
Something like anchor.app.desktop.left/right/bottom/top or is C/C++
detecting resolution and stuff absolutely necessary for that?
No anchors yet, but you access the screen width and height from QML, so I've been experimenting with stuff like that too.
Anchoring a splash window to the center of the screen is not hard, although anchors would make it more elegant. (see qtdeclarative/examples/quick/window/Splash.qml) Doing static anchoring to a screen edge isn't much harder, but I wanted to try animating the window position, to have it fly out whenever you mouse over it.
In QML the edge-anchored flyout window is sortof possible now that the Screen attached property has the screen width and also the desktop available width (excluding whatever existing menus, task bars and docks you might have). I'll include my experiment below.
It's not an official example yet because
1) the Screen attached property is still incomplete, you can't get everything that you can in QScreen. I already fixed that, but ran into too much resistance in code review, see https://codereview.qt-project.org/#change,48480
2) because the screen geometry information is incomplete, you cannot use this example on a virtual desktop consisting of two screens where the secondary is to the right of the primary. You can modify it to use Screen.desktopAvailableWidth instead of Screen.width, but then it will not work on a desktop where the secondary is to the left of the primary.
3) there is a focus issue, so mouse-over (MouseArea.hoverEnabled) doesn't work the same on every platform. (You might have to click on the window before it flies out)
4) the performance of window geometry animation depends on the window manager, so it will be jerky on some platforms
5) yes Alan wants to add something like anchors eventually, so then this example could be done elegantly; but it's not done yet, and it's not easy to do because a Window is not an Item, so the existing anchors attached property cannot be reused as-is. In an ideal OO language, there should have been an inherited class (or interface or mixin) which specifies rectangular geometry without assuming that it's a renderable thing like an Item, and then pointers in anchors and other places should use that type instead of QQuickItem *. But we always use single inheritance because only the top class in the inheritance chain can inherit QObject. The point of putting the rectangular geometric accessors in a mixin would be to have them be properties too; but moc only looks at the properties that are declared in the header that it's looking at. (Somebody correct me if this is actually possible somehow.) QQuickWindow inherits QWindow which inherits QObject; and QQuickItem inherits QObject. They are in different modules, too. So that's why it's hard to have a common inherited interface which the anchors could use, even though they are both just rectangles from the anchors' perspective. This is the situation that Interface is good for in Java.
import QtQuick 2.1
import QtQuick.Window 2.1
Window {
id: root
width: 200
height: 200
visible: true
y: 40
property int xOpen: Screen.width - 10
property int xClosed: Screen.width - root.width + rect.radius
color: "transparent"
flags: Qt.FramelessWindowHint
Component.onCompleted: {
root.x = xOpen
root.y = 40
}
Rectangle {
id: rect
anchors.fill: parent
radius: 40
border.color: "white"
border.width: 3
color: "#D0444422"
antialiasing: true
Rectangle {
anchors.fill: parent
anchors.margins: 1
border.color: "black"
border.width: 2
antialiasing: true
color: "transparent"
radius: parent.radius
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: state = "stateOpen"
onExited: state = "stateClosed"
onClicked: state = "stateOpen"
//~ onStateChanged: console.log("state " + state)
states: [
State {
name: "stateOpen"
},
State {
name: "stateClosed"
}
]
transitions: [
Transition {
from: "stateOpen"
to: "stateClosed"
NumberAnimation {
target: root
properties: "x"
to: root.xOpen
from: root.xClosed
duration: 1000
easing {type: Easing.OutBounce; overshoot: 5}
}
},
Transition {
from: "stateClosed"
to: "stateOpen"
NumberAnimation {
target: root
properties: "x"
from: root.xOpen
to: root.xClosed
duration: 1000
easing {type: Easing.OutBounce; overshoot: 5}
}
}
]
}
}
}
Alan Alpert
2013-06-27 20:09:29 UTC
Permalink
On Tue, Jun 25, 2013 at 4:48 AM, Rutledge Shawn
Post by Rutledge Shawn
[...]
5) yes Alan wants to add something like anchors eventually, so then this example could be done elegantly; but it's not done yet, and it's not easy to do because a Window is not an Item, so the existing anchors attached property cannot be reused as-is. In an ideal OO language, there should have been an inherited class (or interface or mixin) which specifies rectangular geometry without assuming that it's a renderable thing like an Item, and then pointers in anchors and other places should use that type instead of QQuickItem *. But we always use single inheritance because only the top class in the inheritance chain can inherit QObject. The point of putting the rectangular geometric accessors in a mixin would be to have them be properties too; but moc only looks at the properties that are declared in the header that it's looking at. (Somebody correct me if this is actually possible somehow.) QQuickWindow inherits QWindow which inherits QObject; and QQuickItem inherits QObje
ct. They are in different modules, too. So that's why it's hard to have a common inherited interface which the anchors could use, even though they are both just rectangles from the anchors' perspective. This is the situation that Interface is good for in Java.
You forget that we have a meta-object system built on top of C++. We
could have the C++ typing require only that the target is a QObject,
and then do a runtime check on the properties available, and then
access the properties through that interface. Kinda breaks how half
the point of anchors was to be more efficient than property bindings,
but maybe that can also be solved under the covers...

--
Alan Alpert
Rutledge Shawn
2013-06-28 08:16:07 UTC
Permalink
Post by Alan Alpert
You forget that we have a meta-object system built on top of C++.
Well, I was talking about moc above.
Post by Alan Alpert
We could have the C++ typing require only that the target is a QObject,
and then do a runtime check on the properties available, and then
access the properties through that interface. Kinda breaks how half
the point of anchors was to be more efficient than property bindings,
but maybe that can also be solved under the covers…
Good point. But some of the work can be cached, e.g. the anchor can lazily get and keep the QMetaMethods for the setX and setY of the thing that it's going to move and the getters from the reference object, and just invoke() them repeatedly. If they could be somehow converted to plain function pointers, I suppose it would be faster than calling invoke()?

Or maybe we should make QQuickAnchorLine and QQuickAnchorsPrivate into templates so they can access other types of objects that have the same accessors. QQuickAnchors itself could start with QObjects and choose the right template at runtime.
Loading...