Commit ddf4bea6 authored by Aleksi Suomalainen's avatar Aleksi Suomalainen Committed by GitHub

Merge pull request #57 from eekkelund/applauncher_improvements

Applauncher improvements
parents d609775b 11fc86e5
*.pro.user
*.pyc
.directory
*.o
*.so
*.qmlc
moc_*
qrc_*
.qmake.stash
*.spec.*
documentation.list
examples/touch/glacier-components
Makefile
installroot/
RPMS/
debug*.list
This diff is collapsed.
......@@ -22,8 +22,9 @@
// Copyright (c) 2011, Tom Swindell <t.swindell@rubyx.co.uk>
// Copyright (c) 2012, Timur Kristóf <venemo@fedoraproject.org>
import QtQuick 2.2
import QtQuick 2.6
import org.nemomobile.lipstick 0.1
import QtQuick.Controls 1.0
import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0
import org.nemomobile.glacier 1.0
......@@ -33,7 +34,6 @@ import org.nemomobile.glacier 1.0
Item {
id: switcherRoot
property bool closeMode: false
property bool visibleInHome: false
property alias runningAppsCount: switcherModel.itemCount
......@@ -46,12 +46,34 @@ Item {
closeMode = false;
}
}
// Empty switcher indicator
Rectangle {
id: topText
visible: switcherModel.itemCount === 0
width: noAppsLabel.width
height: Theme.itemHeightMedium
anchors {
top: parent.top
topMargin:Theme.itemSpacingLarge
horizontalCenter: parent.horizontalCenter
}
color: "transparent"
Label {
id: noAppsLabel
text: qsTr("No apps open")
anchors {
top: parent.top
left: parent.left
}
font.weight: Font.Light
font.pixelSize: Theme.fontSizeExtraLarge
}
}
Flickable {
id: flickable
contentHeight: gridview.height
width: closeMode ? parent.width - 20 : parent.width // see comment re right anchor below
MouseArea {
height: flickable.contentHeight > flickable.height ? flickable.contentHeight : flickable.height
width: flickable.width
......@@ -181,12 +203,4 @@ Item {
}
}
}
// Empty switcher indicator
Label {
visible: switcherModel.itemCount === 0
text: qsTr("No apps open")
width: parent.width
fontSizeMode: Text.HorizontalFit
}
}
......@@ -7,6 +7,8 @@ import QtQuick.Layouts 1.0
import org.nemomobile.lipstick 0.1
import org.nemomobile.devicelock 1.0
import "scripts/desktop.js" as Desktop
Item {
id: root
......@@ -39,6 +41,8 @@ Item {
id: authenticator
onAuthenticated: {
DeviceLock.unlock(authenticationToken)
Desktop.instance.setLockScreen(false)
Desktop.instance.codepadVisible = false
}
onFeedback: {
console.log('### still locked', feedback, attemptsRemaining)
......@@ -47,34 +51,46 @@ Item {
ColumnLayout {
anchors.fill: parent
spacing: 40
spacing: Theme.itemSpacingLarge
TextField {
id: lockCodeField
anchors.horizontalCenter: parent.horizontalCenter
readOnly: true
echoMode: TextInput.PasswordEchoOnEdit
anchors.horizontalCenter: parent.horizontalCenter
font.pixelSize: Theme.fontSizeExtraLarge
}
GridLayout {
height: parent.height
width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
columns: 3
Repeater {
model: ["1","2","3","4","5","6","7","8","9","Ca","0","OK"]
delegate:
Button {
style: ButtonStyle {}
Layout.fillWidth: true
text: modelData
height: Theme.itemHeightHuge
width: Theme.itemHeightHuge
Layout.maximumWidth: Theme.itemHeightHuge * 1.5
Layout.maximumHeight: Theme.itemHeightHuge * 1.5
Label {
id: btnLabel
text: modelData
font.pixelSize: Theme.fontSizeExtraLarge * 1.5
anchors {
centerIn: parent
}
}
onClicked: {
if (text !== "Ca" && text !== "OK") {
lockCodeField.insert(lockCodeField.cursorPosition, text)
if (btnLabel.text !== "Ca" && btnLabel.text !== "OK") {
lockCodeField.insert(lockCodeField.cursorPosition, btnLabel.text)
} else {
if (text === "OK") {
if (btnLabel.text === "OK") {
authenticator.enterLockCode(lockCodeField.text)
lockCodeField.text = ""
} else if (text === "Ca"){
} else if (btnLabel.text === "Ca"){
lockCodeField.text = ""
}
}
......
......@@ -33,7 +33,7 @@ import "notifications"
Flickable {
id: mainFlickable
clip: true
contentHeight: rootitem.height
contentWidth: parent.width
Item {
......@@ -43,26 +43,27 @@ Flickable {
// Day of week
Rectangle {
id: daterow
height: displayCurrentDate.height + 15
width: childrenRect.width
height: Theme.itemHeightMedium
width: parent.width
anchors{
top: parent.top
horizontalCenter: parent.horizontalCenter
topMargin: Theme.itemSpacingLarge
bottomMargin: Theme.itemSpacingLarge
}
color: "transparent"
Label {
id: displayDayOfWeek
text: Qt.formatDateTime(wallClock.time, "dddd") + ", "
color: "white"
font.pointSize: 12
font.bold: true
text: Qt.formatDateTime(wallClock.time, "dddd")
color: Theme.textColor
font.pixelSize: Theme.fontSizeExtraLarge
font.weight: Font.Bold
anchors {
top: parent.top
left: parent.left
topMargin: 30
horizontalCenter: parent.horizontalCenter
}
}
......@@ -70,12 +71,13 @@ Flickable {
Label {
id: displayCurrentDate
text: Qt.formatDate(wallClock.time, "d MMMM yyyy")
font.pointSize: 12
font.pixelSize: Theme.fontSizeExtraLarge
color: Theme.textColor
font.weight: Font.Light
wrapMode: Text.WordWrap
anchors {
left: displayDayOfWeek.right
top: parent.top
topMargin: 30
horizontalCenter: parent.horizontalCenter
top: displayDayOfWeek.bottom
}
}
}
......@@ -85,9 +87,9 @@ Flickable {
width: parent.width
anchors{
top: daterow.bottom
topMargin: 50
topMargin: Theme.itemSpacingHuge
}
spacing: 10
spacing: Theme.itemSpacingHuge
Repeater {
model: NotificationListModel {
id: notifmodel
......
This diff is collapsed.
// 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) 2017, Eetu Kahelin
// 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.6
import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0
import org.nemomobile.lipstick 0.1
Item {
id: wrapper
property alias iconCaption: iconText
property bool reordering: launcherItem.reordering
property bool isFolder
property int folderAppsCount
property bool notNemoIcon
property alias folderLoader: folderLoader
property alias folderModel:launcherItem.folderModel
onXChanged: moveTimer.start()
onYChanged: moveTimer.start()
Timer {
id: moveTimer
interval: 1
onTriggered: moveIcon()
}
function moveIcon() {
if (!reordering) {
if (!launcherItem.slideMoveAnim.running) {
launcherItem.slideMoveAnim.start()
}
}
}
// Application icon for the launcher
LauncherItemWrapper {
id: launcherItem
width: wrapper.width
height: wrapper.height
isFolder: wrapper.isFolder
notNemoIcon:wrapper.notNemoIcon
parentItem: wrapper.parent
clip: true
onClicked: {
// TODO: disallow if close mode enabled
if (modelData.object.type === LauncherModel.Folder) {
if(folderLoader.count>0 || reopenTimer.running) {
folderLoader.model = 0
} else {
folderLoader.model = modelData.object
}
}
}
Item {
id:folderIconStack
width: size
height: size
property int size: parent.width -parent.width/10
property int iconSize: (/*launcherItem.notNemoIcon ? size-size/3 : */ (size - size/4)) * 0.9
property real transparency: 0.6
property int iconCount: 4
property var icons: addIcons()
function addIcons() {
var iconsList = []
for (var i = 0; i < modelData.object.itemCount && i < iconCount; i++) {
var icon = (modelData.object.get(i).iconId.indexOf("/") == 0 ? "file://" : "image://theme/") + modelData.object.get(i).iconId
iconsList.push(icon)
}
return iconsList
}
Image {
width: folderIconStack.iconSize
height: folderIconStack.iconSize
opacity: folderIconStack.transparency
x:toppestIcon.x+Theme.itemSpacingSmall
y:toppestIcon.y+Theme.itemSpacingSmall
visible: folderIconStack.icons.length > folderIconStack.iconCount-1
source: visible ? folderIconStack.icons[folderIconStack.iconCount-1] : ""
}
Image {
width: folderIconStack.iconSize
height: folderIconStack.iconSize
opacity: folderIconStack.transparency
x:toppestIcon.x-Theme.itemSpacingSmall
y:toppestIcon.y+Theme.itemSpacingSmall
visible: folderIconStack.icons.length > folderIconStack.iconCount-2
source: visible ? folderIconStack.icons[folderIconStack.iconCount-2] : ""
}
Image {
width: folderIconStack.iconSize
height: folderIconStack.iconSize
opacity: folderIconStack.transparency
x:toppestIcon.x+Theme.itemSpacingSmall
y:toppestIcon.y-Theme.itemSpacingSmall
visible: folderIconStack.icons.length > folderIconStack.iconCount-3
source: visible ? folderIconStack.icons[folderIconStack.iconCount-3] : ""
}
Image {
id:toppestIcon
width: folderIconStack.iconSize
height: folderIconStack.iconSize
opacity: folderIconStack.transparency
anchors.centerIn: parent
visible: folderIconStack.icons.length > 0
source: visible ? folderIconStack.icons[0]: ""
}
Text{
id: itemsCount
visible: false// launcherItem.isFolder
text: wrapper.folderAppsCount
anchors.centerIn: parent
horizontalAlignment: Text.AlignHCenter
font.pixelSize: folderIconStack.iconSize.width/4
color: "white"
}
}
// Caption for the icon
Text {
id: iconText
// elide only works if an explicit width is set
width: launcherItem.width
elide: Text.ElideRight
horizontalAlignment: Text.AlignHCenter
font.pixelSize: Theme.fontSizeSmall
color: Theme.textColor
anchors {
left: parent.left
right: parent.right
bottom: parent.bottom
topMargin: Theme.itemSpacingExtraSmall
}
}
Rectangle {
id:triangle
width: wrapper.height/4
height: width
rotation: 45
color: "white"
opacity: 0.85
visible: folderLoader.visible && folderLoader.count > 0
anchors.top:launcherItem.bottom
anchors.horizontalCenter: launcherItem.horizontalCenter
}
}
GridView {
id: folderLoader
property Item reorderItem
property bool isRootFolder:false
cacheBuffer: folderLoader.contentHeight
parent: gridview.contentItem
y: wrapper.y + wrapper.width
x: 0
z: wrapper.z + 100
width: gridview.width
height: count == 0 ? 0 : (Math.floor((count*wrapper.height-1)/width) + 1) * wrapper.height
cellWidth: wrapper.width
cellHeight: wrapper.width
onReorderItemChanged: if(reorderItem == null) folderIconStack.icons=folderIconStack.addIcons()
Rectangle {
width: parent.width
height: parent.height
opacity: 0.85
color: triangle.color
radius: Theme.itemSpacingMedium
z: -1
}
delegate: LauncherItemDelegate {
id:folderLauncherItem
property QtObject modelData : model
property int cellIndex: index
parent: folderLoader
parentItem: folderLoader
width: wrapper.width
height: wrapper.height
notNemoIcon: isFolder || model.object.iconId == "" ? false : model.object.iconId.indexOf("harbour") > -1 || model.object.iconId.indexOf("apkd_launcher") > -1 ? true : false //Dirty but works most of the times
isFolder: model.object.type == LauncherModel.Folder
source: model.object.iconId == "" || isFolder ? "/usr/share/lipstick-glacier-home-qt5/qml/theme/default-icon.png" : (model.object.iconId.indexOf("/") == 0 ? "file://" : "image://theme/") + model.object.iconId
iconCaption.text: model.object.title
iconCaption.color: Theme.backgroundColor
folderModel:folderLoader.model
}
Behavior on height {
NumberAnimation {
easing.type: Easing.InQuad
duration: 100
}
}
}
//When display goes off, close the folderloader
Connections {
target: Lipstick.compositor
onDisplayOff: {
folderLoader.model = 0
}
}
InverseMouseArea {
anchors.fill: folderLoader
enabled: folderLoader.visible && folderLoader.count > 0
parent: folderLoader.contentItem
onPressed: {
folderLoader.model = 0
reopenTimer.start()
}
}
Timer {
id: reopenTimer
interval: 300
running: false
}
}
// 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) 2017, Eetu Kahelin
// 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.6
import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0
import org.nemomobile.lipstick 0.1
MouseArea {
property bool reordering
property int newIndex: -1
property int newFolderIndex: -1
property real oldY
property bool isFolder
property bool notNemoIcon
property Item parentItem
property alias slideMoveAnim: slideMoveAnim
property QtObject folderModel
property Item folderItem
property string deleteState: "basic"
id: launcherItem
parent: parentItem.contentItem
scale: gridview.newFolder && parentItem.folderIndex == cellIndex && !isFolder ? 0.5 : (reordering || parentItem.folderIndex == cellIndex ? 1.3 : 1)
transformOrigin: Item.Center
onXChanged: moved()
onYChanged: moved()
drag.minimumX: parentItem.contentItem.x - width/2
drag.maximumX: parentItem.contentItem.width + width/2
drag.minimumY: parentItem.contentItem.y -height/2 -height/4
drag.maximumY: parentItem.contentItem.height +height/2
onClicked: {
// TODO: disallow if close mode enabled
if (modelData.object.type !== LauncherModel.Folder) {
var winId = switcher.switchModel.getWindowIdForTitle(modelData.object.title)
if (winId == 0 || !modelData.object.isLaunching)
modelData.object.launchApplication()
else
Lipstick.compositor.windowToFront(winId)
}
}
onPressed: {
newIndex = -1
newFolderIndex = -1
}
onPressAndHold: {
reparent(parentItem)
parentItem.reorderItem = launcherItem
drag.target = launcherItem
z = 1000
reordering = true
if(!isFolder){
parentItem.onUninstall = true
}
// don't allow dragging an icon out of pages with a horizontal flick
pager.interactive = false
}
onReleased: {
if (reordering) {
reordering = false
reorderEnded()
reorderTimer.stop()
drag.target = null
parentItem.reorderItem = null
pager.interactive = true
parentItem.onUninstall = false
deleteState="basic"
deleter.uninstalling(deleteState)
parentItem.folderIndex = -1
reparent(parentItem.contentItem)
z = parent.z
slideMoveAnim.start()
}
}
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 = parentItem.contentItem.mapFromItem(launcherItem, width/2, height/2)
var item = parentItem.itemAt(gridViewPos.x, gridViewPos.y)
var idx = -1
var folderIdx = -1
var delPos = deleter.remove.mapFromItem(launcherItem, width/2, height/2)
var isdel = deleter.childAt(delPos.x, delPos.y-height/4)
var isdel2 = deleter.childAt(delPos.x, delPos.y+height/4)//hjelp?
if(!isFolder) {
if (isdel === deleter.remove || isdel2 === deleter.remove) {
deleteState="remove"
deleter.uninstalling(deleteState, iconCaption.text)
} else if (isdel === deleter.uninstall || isdel2 === deleter.uninstall) {
deleteState="uninstall"
deleter.uninstalling(deleteState, iconCaption.text)
} else{
deleteState="basic"
deleter.uninstalling(deleteState)
}
}
//When adding new icon to folder or creating new folder
var offset = gridViewPos.x - item.x
var folderThreshold = !isFolder ? item.width / 4 : item.width / 2
if (offset < folderThreshold) {
if (Math.abs(cellIndex - item.cellIndex) > 1 || cellIndex > item.cellIndex || item.y !== wrapper.offsetY) {
idx = cellIndex < item.cellIndex ? item.cellIndex - 1 : item.cellIndex
folderItem = null
}
} else if (offset >= item.width - folderThreshold) {
if (Math.abs(cellIndex - item.cellIndex) > 1 || cellIndex < item.cellIndex || item.y !== wrapper.offsetY) {
idx = cellIndex > item.cellIndex ? item.cellIndex + 1 : item.cellIndex
folderItem = null
}
} else if (item.cellIndex !== cellIndex && parent.isRootFolder && !isFolder) {
folderItem = item
folderIdx = item.cellIndex
}
if (newIndex !== idx) {
newIndex = idx
reorderTimer.restart()
}
if (newFolderIndex != folderIdx) {
newFolderIndex = folderIdx
reorderTimer.restart()
}
if (newFolderIndex != parentItem.folderIndex) {
parentItem.folderIndex = -1
}
}
}
function reorderEnded() {
//called when icon is released and reordering is true
if (parentItem.folderIndex >= 0) {
if (folderModel.get(parentItem.folderIndex).type == LauncherModel.Application) {
var folder = folderModel.createFolder(parentItem.folderIndex, qsTr("folder"))
if (folder) {
folderModel.moveToFolder(modelData.object, folder)
}
} else {
folderModel.moveToFolder(modelData.object, folderModel.get(parentItem.folderIndex))
}
parentItem.folderIndex = -1
parentItem.newFolderActive = false
}
//To drop appicon out of the folder
var realY = parseInt(parentItem.mapFromItem(launcherItem, 0, 0).y) + parseInt(((launcherItem.height*launcherItem.scale-launcherItem.height)/2).toFixed(2))
if (!parent.isRootFolder && (realY < -Math.abs(launcherItem.height/2) || realY > parentItem.height)) {
var parentFolderIndex = folderModel.parentFolder.indexOf(folderModel)
folderModel.parentFolder.moveToFolder(modelData.object, folderModel.parentFolder, parentFolderIndex+1)
}
if(deleteState != "basic"){
//Just placeholder to get visual feedback
enabled=false
deleteAnimation.start()
deleteTimer.start()
}
}
Timer {//Just placeholder to get visual feedback
id:deleteTimer
interval: 5000
onTriggered: {
iconWrapper.opacity=1.0
enabled = true
}
}
NumberAnimation { id:deleteAnimation; target: typeof iconWrapper !== 'undefined' ? iconWrapper : parent; property: "opacity"; to: 0.2; duration: 3000;}//Just placeholder to get visual feedback
Timer {
id: reorderTimer
interval: folderItem && folderItem.isFolder ? 10 : 100
onTriggered: {
if (newFolderIndex >= 0 && newFolderIndex !== cellIndex) {
if (!folderItem.isFolder) {
parentItem.newFolderActive = true
} else {
parentItem.newFolderActive = false
}
parentItem.folderIndex = newFolderIndex
} else if (newIndex != -1 && newIndex !== cellIndex) {
folderModel.move(cellIndex, 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 }
}
Connections {
target: modelData.object
ignoreUnknownSignals: true
onItemRemoved: {
var modelDataObject = modelData.object
//If there is only one item in folder, remove the folder
if (modelDataObject.itemCount === 1) {
var parentFolderIndex = modelDataObject.parentFolder.indexOf(modelDataObject)
modelDataObject.parentFolder.moveToFolder(modelDataObject.get(0), modelDataObject.parentFolder, parentFolderIndex)
modelDataObject.destroyFolder()
}
}
}
}
......@@ -14,7 +14,6 @@ Image {
key: "/home/glacier/lockScreen/wallpaperImage"
defaultValue: "/usr/share/lipstick-glacier-home-qt5/qml/images/graphics-wallpaper-home.jpg"
}
LockscreenClock {
id: clock
anchors {
......@@ -25,6 +24,7 @@ Image {
}
DeviceLockUI {
id: deviceLockUI
visible: false//DeviceLock.state === DeviceLock.Locked
anchors {
top: clock.bottom
left: parent.left
......
import QtQuick 2.0
import QtQuick 2.1
import org.nemomobile.devicelock 1.0
import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0
Rectangle {
id: lockscreenClock
......@@ -22,10 +25,10 @@ Rectangle {
Text {
id: timeDisplay
font.pointSize: 16
font.pixelSize: Theme.fontSizeExtraLarge * 2
font.weight: Font.Light
lineHeight: 0.85
color: "white"
color: Theme.textColor
horizontalAlignment: Text.AlignHCenter
anchors {
......@@ -35,22 +38,46 @@ Rectangle {
text: Qt.formatDateTime(wallClock.time, "hh:mm")
}
Rectangle {
id: dateRow
height: childrenRect.height
width: weekdayDisplay.width + dateDisplay.width
anchors {
horizontalCenter: parent.horizontalCenter
}
Text {
id: dateDisplay
color: "transparent"
font.pointSize: 14
color: "white"
opacity: 0.8
horizontalAlignment: Text.AlignHCenter
Label {
id: weekdayDisplay
anchors {
left: parent.left
right: parent.right
font.pixelSize: Theme.fontSizeLarge
color: Theme.textColor
horizontalAlignment: Text.AlignHCenter
font.weight: Font.Bold
anchors {
horizontalCenter: parent.horizontalCenter
}
text: Qt.formatDateTime(wallClock.time, "dddd")
}
text: Qt.formatDateTime(wallClock.time, "<b>dddd</b>, d MMMM yyyy")
Label {
id: dateDisplay
font.pixelSize: Theme.fontSizeLarge
color: Theme.textColor
horizontalAlignment: Text.AlignHCenter
font.weight: Font.Light
anchors {
horizontalCenter: parent.horizontalCenter
top: weekdayDisplay.bottom
}
text: Qt.formatDate(wallClock.time, "d MMMM yyyy")
}
}
}
}
......@@ -58,7 +58,10 @@ Page {
id: desktop
property alias lockscreen: lockScreen
property alias switcher: switcher
property alias codepad: codePad
property int statusBarHeight: statusbar.height
property bool codepadVisible: false
// Implements back key navigation
Keys.onReleased: {
......@@ -72,6 +75,7 @@ Page {
Statusbar {
id: statusbar
enabled: DeviceLock.state !== DeviceLock.Locked
}
GlacierRotation {
......@@ -80,7 +84,7 @@ Page {
unrotatedItems: [lockScreen]
}
orientation: Lipstick.compositor.screenOrientation
orientation: DeviceLock.state == DeviceLock.Locked ? nativeOrientation : Lipstick.compositor.screenOrientation
onOrientationChanged: {
if (!lockscreenVisible())
......@@ -142,7 +146,7 @@ Page {
}
// Initial view should be the AppLauncher
currentIndex: 0
//currentIndex: 0
}
Image {
id:wallpaper
......@@ -153,10 +157,21 @@ Page {
}
Lockscreen {
id: lockScreen
visible: DeviceLock.state >= DeviceLock.Locked
visible: lockscreenVisible()//DeviceLock.state == DeviceLock.Locked
width: parent.width
height: parent.height
z: 200
}
DeviceLockUI {
id: codePad
visible: DeviceLock.state == DeviceLock.Locked && codepadVisible
width: lockScreen.width
height:lockScreen.height / 2
anchors {
verticalCenter: lockScreen.verticalCenter
}
z: 200
}
}
This diff is collapsed.
......@@ -42,35 +42,67 @@ import "statusbar"
Item {
id: root
z: 201
height: Math.min(parent.width,parent.height)/10
height: Theme.itemHeightLarge
width: parent.width
anchors.bottom: parent.bottom
enabled: !lockscreenVisible()
Rectangle {
id: statusbar
color: "black"
color: Theme.fillDarkColor
anchors.fill: parent
opacity: 0.5
z: 200
}
MouseArea {
property int oldX
property int oldY
anchors.fill: row
z: row.z + 10
enabled: !lockscreenVisible()
onClicked: {
if(oldX != mouseX && oldY !== mouseY && row.childAt(mouseX, mouseY) && row.currentChild !== row.childAt(mouseX, mouseY)) {
row.currentChild = row.childAt(mouseX, mouseY)
row.currentChild.clicked()
}else {
row.currentChild = null
}
}
onPositionChanged: {
oldX = mouseX
oldY = mouseY
if(pressed && row.childAt(mouseX, mouseY)) {
if(row.currentChild !== row.childAt(mouseX, mouseY)) {
row.currentChild = row.childAt(mouseX, mouseY)
if(panel_loader.visible) panel_loader.visible = false
row.currentChild.clicked()
}
} else {
row.currentChild = null
}
}
}
Connections {
target: lipstickSettings;
onLockscreenVisibleChanged: {
if(lipstickSettings.lockscreenVisible) {
batteryChargePercentage.subscribe()
batteryIndicator.batteryChargePercentage.subscribe()
cellularSignalBars.subscribe()
cellularRegistrationStatus.subscribe()
cellularNetworkName.subscribe()
cellularDataTechnology.subscribe()
} else {
batteryChargePercentage.unsubscribe()
batteryIndicator.batteryChargePercentage.unsubscribe()
cellularSignalBars.unsubscribe()
cellularRegistrationStatus.unsubscribe()
cellularNetworkName.unsubscribe()
cellularDataTechnology.unsubscribe()
}
}
}
}
ContextProperty {
id: cellularSignalBars
......@@ -131,14 +163,39 @@ Item {
Loader {
id: panel_loader
anchors.bottom: root.top
height: 240
height: 0
width: parent.width
visible: false
onVisibleChanged: {
if(visible) riseUp.start()
else closeDown.start()
}
NumberAnimation {
id:riseUp
target: panel_loader
property: "height"
duration: 200
from:0
to:Theme.itemWidthMedium
easing.type: Easing.InOutQuad
}
NumberAnimation {
id:closeDown
target: panel_loader
property: "height"
duration: 200
from: panel_loader.height
to: 0
easing.type: Easing.InOutQuad
}
}
RowLayout {
id:row
anchors.fill: statusbar
spacing: root.height/4
property var currentChild
StatusbarItem {
iconSize: root.height/2
source: (cellularSignalBars.value > 0) ? "image://theme/icon_cell" + cellularSignalBars.value : "image://theme/icon_cell1"
......@@ -196,8 +253,10 @@ Item {
} else if (networkManager.defaultRoute.strength >= 40) {
return "image://theme/icon_wifi_focused1"
} else {
return "image://theme/icon_wifi_normal4"
return "image://theme/icon_wifi_0"
}
} else if (wifimodel.powered && !wlan.connected) {
return "image://theme/icon_wifi_touch"
} else {
return "image://theme/icon_wifi_0"
}
......@@ -224,6 +283,7 @@ Item {
}
StatusbarItem {
iconSize: root.height/2
anchors.verticalCenter: parent.verticalCenter
Label {
id: hours
width: root.height/4
......@@ -242,6 +302,8 @@ Item {
}
}
BatteryIndicator{}
BatteryIndicator{
id:batteryIndicator
}
}
}
This diff is collapsed.
import QtQuick 2.0
import QtQuick 2.6
import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0
......@@ -8,55 +8,115 @@ MouseArea {
height: childrenRect.height
width: rootitem.width
drag.target: notifyArea
drag.axis: Drag.XAxis
drag.minimumX: 0-Theme.itemHeightMedium
drag.maximumX: notifyArea.width
drag.onActiveChanged: {
if(!drag.active ) {
if((notifyArea.x > notifyArea.width/3)) {
slideAnimation.start()
}else slideBackAnimation.start()
}
}
onClicked: {
if (modelData.userRemovable) {
modelData.actionInvoked("default")
slideAnimation.start()
}
}
NumberAnimation {
id:slideAnimation
target: notifyArea
property: "x"
duration: 200
from: notifyArea.x
to: notifyArea.width
easing.type: Easing.InOutQuad
onStopped: modelData.actionInvoked("default")
}
NumberAnimation {
id:slideBackAnimation
target: notifyArea
property: "x"
duration: 200
from: notifyArea.x
to: 0
easing.type: Easing.InOutQuad
}
Rectangle {
anchors.fill: parent
color: "#11ffffff"
visible: notifyArea.pressed
radius: Theme.itemSpacingMedium
}
Image {
id: appIcon
height: 100
height: Theme.itemHeightExtraLarge
width: height
property string defaultIcon: "/usr/share/lipstick-glacier-home-qt5/qml/images/glacier.svg"
anchors{
left: parent.left
leftMargin: 20
leftMargin: Theme.itemSpacingLarge
}
source: {
if (modelData.icon)
return "image://theme/" + modelData.icon
else
return "/usr/share/lipstick-glacier-home-qt5/qml/images/glacier.svg"
return defaultIcon
}
onStatusChanged: {
if (appIcon.status == Image.Error) {
appIcon.source = defaultIcon
}
}
}
Label {
id: appName
text: modelData.appName
width: (rootitem.width-appIcon.width)-Theme.itemSpacingHuge
color: Theme.textColor
font.pixelSize: Theme.fontSizeMedium
font.capitalization: Font.AllUppercase
font.bold: true
anchors {
left: appIcon.right
top: parent.top
leftMargin: Theme.itemSpacingLarge
}
}
Label {
id: appSummary
text: modelData.summary
width: (rootitem.width-appIcon.width)-40
font.pointSize: 12
font.bold :true
font.capitalization: Font.AllUppercase
width: (rootitem.width-appIcon.width)-Theme.itemSpacingHuge
color: Theme.textColor
font.pixelSize: Theme.fontSizeLarge
//font.bold :true
//font.capitalization: Font.AllUppercase
anchors{
left: appIcon.right
leftMargin: 20
top: parent.top
left: appName.left
top: appName.bottom
topMargin: Theme.itemSpacingSmall
}
wrapMode: Text.Wrap
elide: Text.ElideRight
}
Label {
id: appBody
width: (rootitem.width-appIcon.width)-40
width: (rootitem.width-appIcon.width)-Theme.itemSpacingHuge
text: modelData.body
font.pointSize: 14
color: Theme.textColor
font.pixelSize: Theme.fontSizeMedium
anchors{
left: appSummary.left
left: appName.left
top: appSummary.bottom
}
wrapMode: Text.Wrap
elide: Text.ElideRight
}
}
......@@ -26,6 +26,7 @@ import QtQuick 2.0
import org.nemomobile.lipstick 0.1
import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0
import QtGraphicalEffects 1.0
import "../scripts/desktop.js" as Desktop
......@@ -39,27 +40,12 @@ Item {
rotation: Desktop.instance.parent.rotation
x: Desktop.instance.parent.x
y: Desktop.instance.parent.y
Rectangle {
id: dimmer
height: Math.min(parent.width,parent.height)/14
anchors.top: parent.top
anchors.topMargin: notificationArea.notificationHeight
anchors.left: parent.left
anchors.right: parent.right
gradient: Gradient {
GradientStop { position: 1.0; color: "black" }
GradientStop { position: 0; color: "transparent" }
}
}
MouseArea {
id: notificationArea
property int notificationHeight: Math.min(parent.width,parent.height)/12
property int notificationMargin: 14
property int notificationIconSize: Math.min(parent.width,parent.height)/12
property int notificationHeight: Theme.itemHeightExtraLarge
property int notificationMargin: Theme.itemSpacingExtraSmall
property int notificationIconSize: Theme.itemHeightMedium
anchors.top: parent.top
anchors.left: parent.left
width: notificationWindow.width
......@@ -67,14 +53,18 @@ Item {
onClicked: if (notificationPreviewPresenter.notification != null) notificationPreviewPresenter.notification.actionInvoked("default")
Rectangle {
id: notificationPreview
anchors {
fill: parent
}
color: "transparent"
radius: 10
gradient: Gradient {
GradientStop { position: 1.0; color: Theme.fillDarkColor }
GradientStop { position: 0; color: "transparent"}
}
opacity: 0
states: [
......@@ -149,13 +139,14 @@ Item {
top: parent.top
left: icon.right
right: parent.right
leftMargin: notificationArea.notificationMargin + 26
topMargin: notificationArea.notificationMargin
leftMargin: notificationArea.notificationMargin*2
rightMargin: notificationArea.notificationMargin
bottomMargin: notificationArea.notificationMargin
//bottomMargin: notificationArea.notificationMargin
}
font.pointSize: 12
font.pixelSize: Theme.fontSizeLarge
text: notificationPreviewPresenter.notification != null ? notificationPreviewPresenter.notification.previewSummary : ""
color: "white"
color: Theme.textColor
clip: true
elide: Text.ElideRight
}
......@@ -168,14 +159,33 @@ Item {
right: summary.right
}
font {
pointSize: 10
pixelSize: Theme.fontSizeMedium
bold: true
}
text: notificationPreviewPresenter.notification != null ? notificationPreviewPresenter.notification.previewBody : ""
color: "white"
color: Theme.textColor
clip: true
elide: Text.ElideRight
}
//The close button goes here that is in one of the designs
MouseArea {
id: notificationCloser
anchors {
right: parent.right
top: parent.top
}
height: notificationArea.notificationHeight
width: height
//The X icon goes here
/*Image {
id: closeIcon
anchors.centerIn: parent
width: Theme.itemHeightMedium
height: width
source: "/usr/share/lipstick-glacier-home-qt5/qml/images/closeapp.svg"
}*/
}
Connections {
target: notificationPreviewPresenter;
......
......@@ -4,11 +4,17 @@ import org.freedesktop.contextkit 1.0
StatusbarItem {
id: batteryIndicator
property int chargeValue: 0
property alias batteryChargePercentage: batteryChargePercentage
ContextProperty {
id: batteryChargePercentage
key: "Battery.ChargePercentage"
value: "100"
onValueChanged: {
if(batteryStateContextProperty.value != "charging") {
chargeIcon();
}
}
}
ContextProperty {
......@@ -17,7 +23,12 @@ StatusbarItem {
onValueChanged: {
if(batteryStateContextProperty.value == "charging")
{
chargingTimer.start()
if (batteryChargePercentage.value === 100) {
chargingTimer.stop()
chargeIcon()
}else {
chargingTimer.start()
}
}
else
{
......
......@@ -40,7 +40,7 @@ Component {
Label {
text: qsTr("Level")+ ": " + batteryChargePercentage.value + "%"
font.pointSize: 8
font.pixelSize: Theme.fontSizeMedium
anchors.centerIn: parent
}
}
......
......@@ -34,6 +34,7 @@ import QtQuick 2.0
import QtQuick.Controls 1.0
import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0
import org.nemomobile.lipstick 0.1
Rectangle {
id: commonPanel
......@@ -41,8 +42,14 @@ Rectangle {
property alias switcherEnabled: columnCheckBox.enabled
property alias switcherChecked: columnCheckBox.checked
property string name: ""
signal click
onClick: {
panel_loader.sourceComponent = parent.panel
panel_loader.visible = !panel_loader.visible
row.currentChild=null
}
height: 240
height: Theme.itemWidthMedium
width: root.width
color: "transparent"
......@@ -50,6 +57,20 @@ Rectangle {
anchors.fill: parent
color: "#313131"
opacity: 0.3
}
InverseMouseArea {
anchors.fill: parent
enabled: parent.visible
onPressed: {
parent.click()
}
}
MouseArea {
id:mouseArea
anchors.fill:parent
onClicked: parent.click()
}
clip: true
......@@ -60,7 +81,7 @@ Rectangle {
id: actionColumn
anchors{
top: commonPanel.top
topMargin: 20
topMargin: Theme.itemSpacingLarge
}
width: parent.width
Label{
......@@ -68,7 +89,7 @@ Rectangle {
text: name
anchors{
left: actionColumn.left
leftMargin: 20
leftMargin: Theme.itemSpacingLarge
}
wrapMode: Text.Wrap
font.pointSize: 8
......@@ -81,7 +102,7 @@ Rectangle {
visible: enabled
anchors{
right: actionColumn.right
rightMargin: 20
rightMargin: Theme.itemSpacingLarge
verticalCenter: nameLabel.verticalCenter
}
}
......@@ -89,12 +110,54 @@ Rectangle {
Column{
id: dataColumn
width: parent.width-40
width: parent.width-settingsIcon.width
anchors{
left: parent.left
leftMargin: 20
leftMargin: Theme.itemSpacingLarge
top: actionColumn.bottom
topMargin: 60
topMargin: Theme.itemSpacingHuge*1.5
}
}
//Just placeholder until IconButton will get merged
Image {
id:settingsIcon
fillMode: Image.PreserveAspectFit
height: Theme.itemHeightMedium
visible: parent.height > Theme.itemSpacingMedium
source: "image://theme/icon-app-settings" //maybe better icon? settings.png from statusbar spec
anchors{
right: parent.right
rightMargin: Theme.itemSpacingLarge
bottom:parent.bottom
bottomMargin: Theme.itemSpacingLarge
}
MouseArea {
anchors.fill:parent
onClicked: console.log("open right settings page...")
}
}
Connections {
target: lockScreen
onVisibleChanged: {
if(lockscreenVisible()) {
panel_loader.visible = false
}
}
}
Connections {
target: Lipstick.compositor
onDisplayOff: {
panel_loader.visible = false
}
onWindowAdded: {
if(window.category=="" && window.title !== "Home"){
panel_loader.visible = false
}
}
onWindowRaised: {
if(window.category=="" && window.title !== "Home"){
panel_loader.visible = false
}
}
}
}
......@@ -68,7 +68,7 @@ Component {
anchors.fill: simpanel
spacing: 0
RowLayout {
spacing: 16
spacing: Theme.itemSpacingMedium
TextField {
id: pinquery
width: 140
......@@ -138,7 +138,7 @@ Component {
Label {
visible: !needsPin
text: qsTr("No pin required!")
font.pointSize: 16
font.pixelSize:Theme.fontSizeMedium
anchors.centerIn: parent
}
}
......
......@@ -3,28 +3,41 @@ import QtQuick.Layouts 1.0
Item {
property alias source: icon.source
property alias pressed: mouse.pressed
property string panel_source
property Component panel
property double iconSize
Layout.fillWidth: true
Layout.fillHeight: true
function clicked() {
if (panel_source !== "" && !panel) {
panel_loader.source = panel_source
panel_loader.visible = !panel_loader.visible
}
if (panel && panel_source === "") {
panel_loader.sourceComponent = panel
panel_loader.visible = !panel_loader.visible
}
}
Rectangle{
anchors.fill:parent
opacity: 0.8
color: Theme.fillDarkColor
visible: panel_loader.visible && (panel_loader.sourceComponent == panel)
}
Image {
width: iconSize
fillMode: Image.PreserveAspectFit
height: iconSize
id: icon
anchors.centerIn: parent
}
MouseArea {
id:mouse
anchors.fill: parent
onClicked: {
if (panel_source !== "" && !panel) {
panel_loader.source = panel_source
panel_loader.visible = !panel_loader.visible
}
if (panel && panel_source === "") {
panel_loader.sourceComponent = panel
panel_loader.visible = !panel_loader.visible
}
}
enabled: !lockscreenVisible()
onClicked: parent.clicked()
}
}
......@@ -30,7 +30,7 @@
**
****************************************************************************************/
import QtQuick 2.1
import QtQuick 2.6
import QtQuick.Controls.Nemo 1.0
import QtQuick.Controls.Styles.Nemo 1.0
import MeeGo.Connman 0.2
......@@ -40,7 +40,7 @@ Component {
id: wifiPanel
name: "Wifi"
switcherEnabled: true
switcherChecked: true
switcherChecked: wifimodel.powered
onSwitcherCheckedChanged: {
wifimodel.setPowered(switcherChecked)
......@@ -57,10 +57,9 @@ Component {
model: wifimodel
delegate: Item {
width: wifiPanel.width
height: 40
height: Theme.itemHeightSmall
function getStrengthIndex(strength) {
var strengthIndex = "0"
if (strength >= 59) {
strengthIndex = "4"
} else if (strength >= 55) {
......@@ -73,21 +72,22 @@ Component {
return strengthIndex
}
Row {
spacing: 12
spacing: Theme.itemSpacingSmall
Image {
id: statusImage
source: (getStrengthIndex(modelData.strength) === "0")? "image://theme/icon_wifi_0" : "image://theme/icon_wifi_focused" + getStrengthIndex(modelData.strength)
source: (getStrengthIndex(modelData.strength) === "0")? "image://theme/icon_wifi_0" : (modelData.state === "online" ? "image://theme/icon_wifi_focused" : "image://theme/icon_wifi_normal")+ getStrengthIndex(modelData.strength)
}
Label {
anchors{
leftMargin: 20
leftMargin: Theme.itemSpacingLarge
verticalCenter: statusImage.verticalCenter
}
width: root.width
font.pointSize: 8
font.pixelSize: Theme.fontSizeMedium
text: modelData.name
wrapMode: Text.Wrap
color: modelData.state === "online" ? Theme.accentColor : Theme.textColor
}
}
}
......
......@@ -44,7 +44,10 @@ qml.files = qml/MainScreen.qml \
qml/CommonPanel.qml \
qml/ShutdownScreen.qml \
qml/GlacierRotation.qml \
qml/DeviceLockUI.qml
qml/DeviceLockUI.qml \
qml/LauncherItemWrapper.qml \
qml/LauncherItemFolder.qml \
qml/SearchListView.qml
qmlcompositor.path = /usr/share/lipstick-glacier-home-qt5/qml/compositor
qmlcompositor.files = qml/compositor/WindowWrapperMystic.qml \
......
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