Commit c7c88065 authored by Aleksi Suomalainen's avatar Aleksi Suomalainen

Stolen QML's

parent 9f76174b
// This file is part of colorful-home, a nice user experience for touchscreens.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Copyright (c) 2011, Tom Swindell <t.swindell@rubyx.co.uk>
// Copyright (c) 2012, Timur Kristóf <venemo@fedoraproject.org>
import QtQuick 2.0
import org.nemomobile.lipstick 0.1
// App Launcher page
// the place for browsing installed applications and launching them
GridView {
id: gridview
cellWidth: 115
cellHeight: cellWidth + 30
width: Math.floor(parent.width / cellWidth) * cellWidth
cacheBuffer: gridview.contentHeight
property Item reorderItem
// just for margin purposes
header: Item {
height: 30
}
footer: Item {
height: 20
}
model: LauncherModel { id: launcherModel }
delegate: LauncherItemDelegate {
id: launcherItem
width: gridview.cellWidth
height: gridview.cellHeight
source: model.object.iconId == "" ? ":/images/icons/apps.png" : (model.object.iconId.indexOf("/") == 0 ? "file://" : "image://theme/") + model.object.iconId
iconCaption: model.object.title
}
}
// This file is part of colorful-home, a nice user experience for touchscreens.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Copyright (c) 2011, Tom Swindell <t.swindell@rubyx.co.uk>
// Copyright (c) 2012, Timur Kristóf <venemo@fedoraproject.org>
import QtQuick 2.0
import org.nemomobile.lipstick 0.1
import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0
// App Switcher page
// The place for browsing already running apps
Item {
id: switcherRoot
property bool closeMode: false
property bool visibleInHome: false
property alias runningAppsCount: switcherModel.itemCount
onVisibleInHomeChanged: {
// Exit close mode when scrolling out of view
if (!visibleInHome && closeMode) {
closeMode = false;
}
}
Flickable {
id: flickable
contentHeight: gridview.height
width: parent.width - UiConstants.DefaultMargin // see comment re right anchor below
MouseArea {
height: flickable.contentHeight > flickable.height ? flickable.contentHeight : flickable.height
width: flickable.width
onPressAndHold: closeMode = !closeMode
onClicked: {
if (closeMode)
closeMode = false
}
}
anchors {
top: parent.top
bottom: toolBar.top
left: parent.left
// no right anchor to avoid double margin (complicated math)
margins: UiConstants.DefaultMargin
}
Grid {
id: gridview
columns: 2
spacing: UiConstants.DefaultMargin
move: Transition {
NumberAnimation {
properties: "x,y"
}
}
Repeater {
id: gridRepeater
model: WindowModel {
id:switcherModel
}
delegate: Item {
width: (flickable.width - (gridview.spacing * gridview.columns)) / gridview.columns
height: width * (desktop.height / desktop.width)
// The outer Item is necessary because of animations in SwitcherItem changing
// its size, which would break the Grid.
SwitcherItem {
id: switcherItem
width: parent.width
height: parent.height
}
function close() {
switcherItem.close()
}
}
}
}
}
Rectangle {
id: toolBar
color: 'black'
border {
width: 1
color: '#333333'
}
height: toolBarDone.height + 2*padding
property int padding: 9
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
margins: -1
bottomMargin: switcherRoot.closeMode ? 0 : -height
}
Behavior on anchors.bottomMargin { PropertyAnimation { duration: 100 } }
Button {
id: toolBarDone
width: parent.width / 3
anchors {
top: parent.top
topMargin: toolBar.padding
right: parent.horizontalCenter
rightMargin: toolBar.padding
}
text: 'Done'
onClicked: {
switcherRoot.closeMode = false;
}
}
Button {
id: toolBarCloseAll
width: toolBarDone.width
anchors {
top: parent.top
topMargin: toolBar.padding
left: parent.horizontalCenter
leftMargin: toolBar.padding
}
text: 'Close all'
onClicked: {
// TODO: use close animation inside item
for (var i = gridRepeater.count - 1; i >= 0; i--) {
gridRepeater.itemAt(i).close()
}
}
}
}
// Empty switcher indicator
Label {
enabled: switcherModel.itemCount === 0
text: "No apps open"
}
}
// This file is part of colorful-home, a nice user experience for touchscreens.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Copyright (c) 2013, Jolla Ltd <robin.burchell@jollamobile.com>
// Copyright (c) 2012, Timur Kristóf <venemo@fedoraproject.org>
// Copyright (c) 2011, Tom Swindell <t.swindell@rubyx.co.uk>
import QtQuick 2.0
import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0
Item {
id: wrapper
property alias source: iconImage.source
property alias iconCaption: iconText.text
property bool reordering
property int newIndex: -1
property real oldY
onXChanged: moveTimer.start()
onYChanged: moveTimer.start()
Timer {
id: moveTimer
interval: 1
onTriggered: moveIcon()
}
function moveIcon() {
if (!reordering) {
if (!slideMoveAnim.running) {
slideMoveAnim.start()
}
}
}
// Application icon for the launcher
MouseArea {
id: launcherItem
width: wrapper.width
height: wrapper.height
parent: gridview.contentItem
scale: reordering ? 1.3 : 1
transformOrigin: Item.Center
onXChanged: moved()
onYChanged: moved()
onClicked: {
// TODO: disallow if close mode enabled
model.object.launchApplication()
}
onPressAndHold: {
reparent(gridview)
reorderItem = launcherItem
drag.target = launcherItem
z = 1000
reordering = true
// don't allow dragging an icon out of pages with a horizontal flick
pager.interactive = false
}
onReleased: {
if (reordering) {
reordering = false
reorderTimer.stop()
drag.target = null
reorderItem = null
reparent(gridview.contentItem)
slideMoveAnim.start()
pager.interactive = true
}
}
function reparent(newParent) {
var newPos = mapToItem(newParent, 0, 0)
parent = newParent
x = newPos.x - width/2 * (1-scale)
y = newPos.y - height/2 * (1-scale)
}
function moved() {
if (reordering) {
var gridViewPos = gridview.contentItem.mapFromItem(launcherItem, width/2, height/2)
var idx = gridview.indexAt(gridViewPos.x, gridViewPos.y)
if (newIndex !== idx) {
reorderTimer.restart()
newIndex = idx
}
/*
var globalY = desktop.mapFromItem(launcherItem, 0, 0).y
if (globalY < 70) {
pageChangeTimer.start()
} else {
pageChangeTimer.stop()
}
*/
}
}
Timer {
id: reorderTimer
interval: 100
onTriggered: {
if (newIndex != -1 && newIndex !== index) {
launcherModel.move(index, newIndex)
}
newIndex = -1
}
}
Behavior on scale {
NumberAnimation { easing.type: Easing.InOutQuad; duration: 150 }
}
ParallelAnimation {
id: slideMoveAnim
NumberAnimation { target: launcherItem; property: "x"; to: wrapper.x; duration: 130; easing.type: Easing.OutQuint }
NumberAnimation { target: launcherItem; property: "y"; to: wrapper.y; duration: 130; easing.type: Easing.OutQuint }
}
Image {
id: iconImage
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: 8
}
width: 100
height: width
asynchronous: true
onStatusChanged: {
if (status === Image.Error) {
console.log("Error loading an app icon, falling back to default.");
iconImage.source = ":/images/icons/apps.png";
}
}
Spinner {
id: spinner
anchors.centerIn: parent
enabled: model.object.isLaunching
}
}
// Caption for the icon
Text {
id: iconText
// elide only works if an explicit width is set
width: parent.width
elide: Text.ElideRight
horizontalAlignment: Text.AlignHCenter
font.pixelSize: 18
color: 'white'
anchors {
left: parent.left
right: parent.right
top: iconImage.bottom
topMargin: 5
}
}
}
}
import QtQuick 2.0
Image {
id: lockScreen
source: wallpaperSource.value
/**
* openingState should be a value between 0 and 1, where 0 means
* the lockscreen is "down" (obscures the view) and 1 means the
* lockscreen is "up" (not visible).
**/
property real openingState: y / -height
visible: openingState < 1
onHeightChanged: {
if (mouseArea.fingerDown)
return // we'll fix this up on touch release via the animations
if (snapOpenAnimation.running)
snapOpenAnimation.to = -height
else if (!snapClosedAnimation.running && !LipstickSettings.lockscreenVisible)
y = -height
}
function snapPosition() {
if (LipstickSettings.lockscreenVisible) {
snapOpenAnimation.stop()
snapClosedAnimation.start()
} else {
snapClosedAnimation.stop()
snapOpenAnimation.start()
}
}
function cancelSnap() {
snapClosedAnimation.stop()
snapOpenAnimation.stop()
}
Connections {
target: LipstickSettings
onLockscreenVisibleChanged: snapPosition()
}
PropertyAnimation {
id: snapClosedAnimation
target: lockScreen
property: "y"
to: 0
easing.type: Easing.OutBounce
duration: 400
}
PropertyAnimation {
id: snapOpenAnimation
target: lockScreen
property: "y"
to: -height
easing.type: Easing.OutExpo
duration: 400
}
MouseArea {
id: mouseArea
property int pressY: 0
property bool fingerDown
property bool ignoreEvents
anchors.fill: parent
onPressed: {
fingerDown = true
cancelSnap()
pressY = mouseY
}
onPositionChanged: {
var delta = pressY - mouseY
pressY = mouseY + delta
if (parent.y - delta > 0)
return
parent.y = parent.y - delta
}
function snapBack() {
fingerDown = false
if (!LipstickSettings.lockscreenVisible || Math.abs(parent.y) > parent.height / 3) {
LipstickSettings.lockscreenVisible = false
} else if (LipstickSettings.lockscreenVisible) {
LipstickSettings.lockscreenVisible = true
}
lockScreen.snapPosition()
}
onCanceled: snapBack()
onReleased: snapBack()
}
LockscreenClock {
anchors {
top: parent.top
left: parent.left
right: parent.right
}
}
}
import QtQuick 2.0
Rectangle {
id: lockscreenClock
height: (timeDisplay.height + dateDisplay.height) * 1.5
gradient: Gradient {
GradientStop { position: 0.0; color: '#b0000000' }
GradientStop { position: 1.0; color: '#00000000' }
}
Column {
id: clockColumn
anchors {
left: parent.left
right: parent.right
top: parent.top
}
Text {
id: timeDisplay
font.pixelSize: 80
font.weight: Font.Light
lineHeight: 0.85
color: "white"
horizontalAlignment: Text.AlignHCenter
anchors {
left: parent.left
right: parent.right
}
text: Qt.formatDateTime(wallClock.time, "hh:mm")
}
Text {
id: dateDisplay
font.pixelSize: 20
color: "white"
opacity: 0.8
horizontalAlignment: Text.AlignHCenter
anchors {
left: parent.left
right: parent.right
}
text: Qt.formatDateTime(wallClock.time, "<b>dddd</b>, d MMMM yyyy")
}
}
}
...@@ -50,26 +50,59 @@ ApplicationWindow { ...@@ -50,26 +50,59 @@ ApplicationWindow {
} else { Qt.quit(); } } else { Qt.quit(); }
} }
} }
ListModel {
id: pageModel
ListElement {
title: "Live-Coding Arena"
page: "content/LiveCoding.qml"
}
}
initialPage: Page { initialPage: Page {
id: pageItem Item {
id: desktop
property bool isPortrait: width < height
tools: ToolBarLayoutExample { title: "Glacier UI" } anchors.fill: parent
// Pager for swiping between different pages of the home screen
Pager {
id: pager
scale: 0.7 + 0.3 * lockScreen.openingState
opacity: lockScreen.openingState
ListView {
model: pageModel
anchors.fill: parent anchors.fill: parent
clip: true
delegate: AndroidDelegate { model: VisualItemModel {
text: title AppLauncher {
onClicked: pageItem.Stack.view.push(Qt.resolvedUrl(page)) id: launcher
height: pager.height
}
AppSwitcher {
id: switcher
width: pager.width
height: pager.height
visibleInHome: x > -width && x < desktop.width
}
} }
// Initial view should be the AppLauncher
currentIndex: 1
} }
Lockscreen {
id: lockScreen
width: parent.width
height: parent.height
z: 200
onOpeningStateChanged: {
// When fully closed, reset the current page
if (openingState !== 0)
return
// Focus the switcher if any applications are running, otherwise the launcher
if (switcher.runningAppsCount > 0) {
pager.currentIndex = 2
} else {
pager.currentIndex = 1
} }
}
}
}
tools: ToolBarLayoutExample { title: "Glacier UI" }
} }
// This file is part of colorful-home, a nice user experience for touchscreens.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// Copyright (c) 2012, Timur Kristóf <venemo@fedoraproject.org>
import QtQuick 2.0
PathView {
id: pager
highlightRangeMode: PathView.StrictlyEnforceRange
preferredHighlightBegin: 0.5
preferredHighlightEnd: 0.5
flickDeceleration: 10000
highlightMoveDuration: 100
snapMode: PathView.SnapOneItem
clip: true
path: Path {
startX: - width * model.count / 2 + width / 2
startY: height / 2
PathLine {
x: width * model.count / 2 + width / 2
y: height / 2
}
}
}
...@@ -4,5 +4,12 @@ ...@@ -4,5 +4,12 @@
<file>qml/compositor/ScreenGestureArea.qml</file> <file>qml/compositor/ScreenGestureArea.qml</file>
<file>qml/compositor/WindowWrapperAlpha.qml</file> <file>qml/compositor/WindowWrapperAlpha.qml</file>
<file>qml/compositor/WindowWrapperBase.qml</file> <file>qml/compositor/WindowWrapperBase.qml</file>
<file>qml/AppLauncher.qml</file>
<file>qml/AppSwitcher.qml</file>
<file>qml/compositor.qml</file>
<file>qml/LauncherItemDelegate.qml</file>
<file>qml/Lockscreen.qml</file>
<file>qml/LockscreenClock.qml</file>
<file>qml/Pager.qml</file>
</qresource> </qresource>
</RCC> </RCC>
...@@ -26,7 +26,12 @@ PKGCONFIG += lipstick-qt5 ...@@ -26,7 +26,12 @@ PKGCONFIG += lipstick-qt5
OTHER_FILES += qml/*.qml \ OTHER_FILES += qml/*.qml \
qml/MainScreen.qml \ qml/MainScreen.qml \
qml/compositor.qml qml/compositor.qml \
qml/LauncherItemDelegate.qml \
qml/Lockscreen.qml \
qml/LockscreenClock.qml \
qml/AppSwitcher.qml \
qml/AppLauncher.qml
config.files = lipstick.conf config.files = lipstick.conf
config.path = /usr/share/lipstick config.path = /usr/share/lipstick
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment