Merge PR #835: Rework bottom panel

This commit is contained in:
jenkins 2022-06-22 17:13:11 +02:00
commit e67c098d93
25 changed files with 439 additions and 233 deletions

View File

@ -157,6 +157,7 @@ int main(int argc, char *argv[])
} }
qmlRegisterSingletonType(QUrl("qrc:///styles/" + styleController.currentStyle() + "/Style.qml"), "Nymea", 1, 0, "Style" ); qmlRegisterSingletonType(QUrl("qrc:///styles/" + styleController.currentStyle() + "/Style.qml"), "Nymea", 1, 0, "Style" );
qmlRegisterType(QUrl("qrc:///styles/" + styleController.currentStyle() + "/Background.qml"), "Nymea", 1, 0, "Background" );
qmlRegisterSingletonType(QUrl("qrc:///ui/Configuration.qml"), "Nymea", 1, 0, "Configuration"); qmlRegisterSingletonType(QUrl("qrc:///ui/Configuration.qml"), "Nymea", 1, 0, "Configuration");
engine->rootContext()->setContextProperty("styleController", &styleController); engine->rootContext()->setContextProperty("styleController", &styleController);

View File

@ -39,5 +39,11 @@
<file>ui/Configuration.qml</file> <file>ui/Configuration.qml</file>
<file>styles/dark/Dialog.qml</file> <file>styles/dark/Dialog.qml</file>
<file>styles/light/Dialog.qml</file> <file>styles/light/Dialog.qml</file>
<file>styles/dark/Background.qml</file>
<file>styles/light/Background.qml</file>
<file>styles/energize/Background.qml</file>
<file>styles/lime/Background.qml</file>
<file>styles/mellow/Background.qml</file>
<file>styles/noir/Background.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -0,0 +1,5 @@
import QtQuick 2.0
Rectangle {
color: Style.backgroundColor
}

View File

@ -33,8 +33,5 @@ import QtQuick.Templates 2.2
import QtQuick.Controls.Material 2.2 import QtQuick.Controls.Material 2.2
Page { Page {
background: Background {}
background: Rectangle {
color: Material.background
}
} }

View File

@ -0,0 +1,8 @@
import QtQuick 2.0
Rectangle {
gradient: Gradient {
GradientStop { position: 0.0; color: "#e3eae4" }
GradientStop { position: 1.0; color: "#cde2d8" }
}
}

View File

@ -33,11 +33,5 @@ import QtQuick.Templates 2.2
import QtQuick.Controls.Material 2.2 import QtQuick.Controls.Material 2.2
Page { Page {
background: Background {}
background: Rectangle {
gradient: Gradient {
GradientStop { position: 0.0; color: "#e3eae4" }
GradientStop { position: 1.0; color: "#cde2d8" }
}
}
} }

View File

@ -0,0 +1,5 @@
import QtQuick 2.0
Rectangle {
color: Style.backgroundColor
}

View File

@ -33,8 +33,5 @@ import QtQuick.Templates 2.2
import QtQuick.Controls.Material 2.2 import QtQuick.Controls.Material 2.2
Page { Page {
background: Background {}
background: Rectangle {
color: Material.background
}
} }

View File

@ -0,0 +1,5 @@
import QtQuick 2.0
Rectangle {
color: Style.backgroundColor
}

View File

@ -33,8 +33,5 @@ import QtQuick.Templates 2.2
import QtQuick.Controls.Material 2.2 import QtQuick.Controls.Material 2.2
Page { Page {
background: Background {}
background: Rectangle {
color: Material.background
}
} }

View File

@ -0,0 +1,5 @@
import QtQuick 2.0
Rectangle {
color: Style.backgroundColor
}

View File

@ -33,8 +33,5 @@ import QtQuick.Templates 2.2
import QtQuick.Controls.Material 2.2 import QtQuick.Controls.Material 2.2
Page { Page {
background: Background {}
background: Rectangle {
color: Material.background
}
} }

View File

@ -0,0 +1,5 @@
import QtQuick 2.0
Rectangle {
color: Style.backgroundColor
}

View File

@ -34,7 +34,5 @@ import QtQuick.Controls.Material 2.2
import Nymea 1.0 import Nymea 1.0
Page { Page {
background: Rectangle { background: Background {}
color: Style.backgroundColor
}
} }

View File

@ -54,6 +54,11 @@ Page {
d.configOverlay = configComponent.createObject(contentContainer) d.configOverlay = configComponent.createObject(contentContainer)
} }
// Removing the background from this page only because the MainViewBase adds it again in
// a deepter layer as we need to include it in the blurring of the header and footer.
// We don't want to paint the background on the entire screen twice (overdraw is costly)
background: null
header: Item { header: Item {
id: mainHeader id: mainHeader
height: 0 height: 0
@ -70,20 +75,6 @@ Page {
} }
} }
// Label {
// anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter }
// horizontalAlignment: Text.AlignHCenter
// leftPadding: Math.max(menuButton.width, additionalIcons.width)
// rightPadding: leftPadding
// elide: Text.ElideRight
// font: Style.bigFont
// text: d.configOverlay !== null ?
// qsTr("Configure main view")
// : swipeView.currentItem.item.title.length > 0 ? swipeView.currentItem.item.title : filteredContentModel.modelData(swipeView.currentIndex, "displayName")
// }
Row { Row {
id: additionalIcons id: additionalIcons
anchors { right: parent.right; top: parent.top } anchors { right: parent.right; top: parent.top }
@ -222,8 +213,7 @@ Page {
} }
} }
tabBar.currentIndex = Qt.binding(function() { return mainViewSettings.currentIndex; }) swipeView.currentIndex = mainViewSettings.currentIndex
swipeView.currentIndex = Qt.binding(function() { return tabBar.currentIndex; })
mainViewSettings.currentIndex = Qt.binding(function() { return swipeView.currentIndex; }) mainViewSettings.currentIndex = Qt.binding(function() { return swipeView.currentIndex; })
} }
} }
@ -242,16 +232,11 @@ Page {
clip: true clip: true
property int headerSize: 48 property int headerSize: 48
property int footerSize: app.landscape ? 48 : 64
readonly property int scrollOffset: swipeView.currentItem.item.contentY readonly property int scrollOffset: swipeView.currentItem ? swipeView.currentItem.item.contentY : 0
readonly property int headerBlurSize: Math.min(headerSize, scrollOffset * 2) readonly property int headerBlurSize: Math.min(headerSize, scrollOffset * 2)
Rectangle {
width: parent.width
height: contentContainer.headerBlurSize
color: Style.backgroundColor
}
SwipeView { SwipeView {
id: swipeView id: swipeView
anchors.fill: parent anchors.fill: parent
@ -276,6 +261,12 @@ Page {
value: swipeView.currentIndex == index value: swipeView.currentIndex == index
} }
Binding {
target: mainViewLoader.item
property: "bottomMargin"
value: footer.visible ? contentContainer.footerSize : 0
}
Image { Image {
source: "qrc:/styles/%1/logo-wide.svg".arg(styleController.currentStyle) source: "qrc:/styles/%1/logo-wide.svg".arg(styleController.currentStyle)
anchors { anchors {
@ -287,12 +278,13 @@ Page {
height: 28 height: 28
sourceSize.height: height sourceSize.height: height
antialiasing: true antialiasing: true
z: 2
} }
} }
} }
} }
ColumnLayout { ColumnLayout {
anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter; margins: app.margins } anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter; margins: app.margins }
spacing: app.margins spacing: app.margins
@ -314,9 +306,9 @@ Page {
ShaderEffectSource { ShaderEffectSource {
id: headerBlurSource id: headerBlurSource
width: contentContainer.width width: contentContainer.width
height: contentContainer.headerBlurSize height: d.configOverlay ? contentContainer.headerSize : contentContainer.headerBlurSize
sourceItem: contentContainer sourceItem: contentContainer
sourceRect: Qt.rect(0, 0, contentContainer.width, contentContainer.headerBlurSize) sourceRect: Qt.rect(0, 0, contentContainer.width, d.configOverlay ? contentContainer.headerSize : contentContainer.headerBlurSize)
visible: false visible: false
} }
@ -326,7 +318,7 @@ Page {
top: parent.top; top: parent.top;
right: parent.right; right: parent.right;
} }
height: contentContainer.headerBlurSize height: d.configOverlay ? contentContainer.headerSize : contentContainer.headerBlurSize
radius: 40 radius: 40
transparentBorder: true transparentBorder: true
source: headerBlurSource source: headerBlurSource
@ -339,7 +331,7 @@ Page {
top: parent.top top: parent.top
right: parent.right right: parent.right
} }
height: contentContainer.headerBlurSize height: d.configOverlay ? contentContainer.headerSize : contentContainer.headerBlurSize
gradient: Gradient { gradient: Gradient {
GradientStop { position: 0.1; color: Style.backgroundColor } GradientStop { position: 0.1; color: Style.backgroundColor }
@ -348,17 +340,53 @@ Page {
} }
} }
footer: Item { ShaderEffectSource {
readonly property bool shown: tabsRepeater.count > 1 || d.configOverlay id: footerBlurSource
implicitHeight: shown ? 64 + (app.landscape ? -20 : 0) : 0 width: contentContainer.width
Behavior on implicitHeight { NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }} height: contentContainer.footerSize
sourceItem: contentContainer
sourceRect: Qt.rect(0, contentContainer.height - height, contentContainer.width, contentContainer.footerSize)
visible: false
enabled: footer.shown
}
TabBar { FastBlur {
id: tabBar anchors {
anchors { left: parent.left; top: parent.top; right: parent.right } left: parent.left;
height: 64 + (app.landscape ? -20 : 0) bottom: parent.bottom;
Material.elevation: 3 right: parent.right;
position: TabBar.Footer }
height: contentContainer.footerSize
radius: 40
transparentBorder: false
source: footerBlurSource
visible: footer.shown
}
Rectangle {
id: footer
readonly property bool shown: tabsRepeater.count > 1 || d.configOverlay
visible: shown
anchors {
left: parent.left
bottom: parent.bottom
right: parent.right
}
height: contentContainer.footerSize
Behavior on height { NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }}
// color: "transparent"
gradient: Gradient {
GradientStop { position: 0; color: "transparent" }
GradientStop { position: 0.4; color: Qt.rgba(Style.backgroundColor.r, Style.backgroundColor.g, Style.backgroundColor.b, 0.7) }
GradientStop { position: 1; color: Style.backgroundColor }
}
RowLayout {
id: tabsLayout
anchors.fill: parent
spacing: 0
opacity: d.configOverlay ? 0 : 1 opacity: d.configOverlay ? 0 : 1
Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.InOutQuad } } Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.InOutQuad } }
@ -366,14 +394,18 @@ Page {
Repeater { Repeater {
id: tabsRepeater id: tabsRepeater
model: d.configOverlay != null ? null : filteredContentModel model: d.configOverlay != null ? null : filteredContentModel
// model: filteredContentModel
delegate: MainPageTabButton { delegate: MainPageTabButton {
Layout.fillWidth: true
Layout.fillHeight: true
alignment: app.landscape ? Qt.Horizontal : Qt.Vertical alignment: app.landscape ? Qt.Horizontal : Qt.Vertical
checked: index === swipeView.currentIndex
height: tabBar.height height: tabBar.height
anchors.verticalCenter: parent.verticalCenter // anchors.verticalCenter: parent.verticalCenter
text: model.displayName text: model.displayName
iconSource: "../images/" + model.icon + ".svg" iconSource: "../images/" + model.icon + ".svg"
onClicked: swipeView.currentIndex = index
onPressAndHold: { onPressAndHold: {
root.configureViews(); root.configureViews();
} }
@ -381,80 +413,83 @@ Page {
} }
} }
TabBar {
anchors.fill: tabBar MainPageTabButton {
Material.elevation: 3 anchors.fill: parent
position: TabBar.Footer alignment: app.landscape ? Qt.Horizontal : Qt.Vertical
text: d.configOverlay ? qsTr("Done") : qsTr("Configure")
iconSource: "../images/configure.svg"
opacity: d.configOverlay ? 1 : 0 opacity: d.configOverlay ? 1 : 0
Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.InOutQuad } } Behavior on opacity { NumberAnimation { duration: 200; easing.type: Easing.InOutQuad } }
visible: opacity > 0 visible: opacity > 0
MainPageTabButton { checked: true
height: tabBar.height
alignment: app.landscape ? Qt.Horizontal : Qt.Vertical
text: d.configOverlay ? qsTr("Done") : qsTr("Configure")
iconSource: "../images/configure.svg"
anchors.verticalCenter: parent.verticalCenter
checked: false onClicked: {
checkable: false if (d.configOverlay) {
d.configOverlay.destroy()
onClicked: { } else {
if (d.configOverlay) { PlatformHelper.vibrate(PlatformHelper.HapticsFeedbackSelection)
d.configOverlay.destroy() d.configOverlay = configComponent.createObject(contentContainer)
} else {
PlatformHelper.vibrate(PlatformHelper.HapticsFeedbackSelection)
d.configOverlay = configComponent.createObject(contentContainer)
}
} }
} }
} }
} }
Component { Component {
id: configComponent id: configComponent
Item { Background {
id: configOverlay id: configOverlay
width: contentContainer.width width: contentContainer.width
height: contentContainer.height height: contentContainer.height
NumberAnimation {
target: configOverlay
property: "scale"
duration: 200
easing.type: Easing.InOutQuad
from: 2
to: 1
running: true
}
NumberAnimation {
target: configOverlay
property: "opacity"
duration: 200
easing.type: Easing.InOutQuad
from: 0
to: 1
running: true
}
ListView { ListView {
id: configListView id: configListView
anchors.fill: parent
model: mainMenuModel model: mainMenuModel
width: parent.width topMargin: contentContainer.headerSize
height: parent.height / 3 bottomMargin: contentContainer.footerSize
anchors.centerIn: parent
orientation: ListView.Horizontal
moveDisplaced: Transition {
NumberAnimation { properties: "x,y"; duration: 200 }
}
property int delegateWidth: width / 3
property bool dragging: draggingIndex >= 0 property bool dragging: draggingIndex >= 0
property int draggingIndex : -1 property int draggingIndex : -1
moveDisplaced: Transition { NumberAnimation { properties: "y" } }
delegate: NymeaItemDelegate {
id: viewConfigDelegate
width: parent.width
text: model.displayName
iconName: Qt.resolvedUrl("images/" + model.icon + ".svg")
progressive: false
checked: mainViewSettings.filterList.indexOf(model.name) >= 0
visible: index !== configListView.draggingIndex
additionalItem: CheckBox {
checked: viewConfigDelegate.checked
anchors.verticalCenter: parent.verticalCenter
onClicked: {
var newList = []
for (var i = 0; i < mainMenuModel.count; i++) {
var entry = mainMenuModel.get(i).name;
if (entry === model.name) {
if (!isEnabled) {
newList.push(model.name)
}
} else {
if (mainViewSettings.filterList.indexOf(entry) >= 0) {
newList.push(entry)
}
}
}
if (newList.length === 0) {
newList.push(Configuration.defaultMainView)
}
mainViewSettings.filterList = newList
}
}
}
MouseArea { MouseArea {
id: dndArea id: dndArea
anchors.fill: parent anchors.fill: parent
@ -463,22 +498,28 @@ Page {
onPressAndHold: { onPressAndHold: {
mouse.accepted = true mouse.accepted = true
var mouseXInListView = configListView.contentItem.mapFromItem(dndArea, mouseX, mouseY).x; var mouseYInListView = configListView.contentItem.mapFromItem(dndArea, mouseX, mouseY).y;
configListView.draggingIndex = configListView.indexAt(mouseXInListView, mouseY) configListView.draggingIndex = configListView.indexAt(mouseX, mouseYInListView)
var item = mainMenuModel.get(configListView.draggingIndex) var item = mainMenuModel.get(configListView.draggingIndex)
dndItem.displayName = item.displayName print("draggingIndex", configListView.draggingIndex)
dndItem.icon = item.icon dndItem.text = item.displayName
var visualItem = configListView.itemAt(mouseXInListView, mouseY) dndItem.iconName = item.icon
dndItem.isEnabled = visualItem.isEnabled var visualItem = configListView.itemAt(mouseX, mouseYInListView)
dndArea.dragOffset = configListView.mapToItem(visualItem, mouseX, mouseY).x dndItem.checked = visualItem.checked
dndArea.dragOffset = configListView.mapToItem(visualItem, mouseX, mouseY).y
PlatformHelper.vibrate(PlatformHelper.HapticsFeedbackImpact) PlatformHelper.vibrate(PlatformHelper.HapticsFeedbackImpact)
} }
onMouseYChanged: { onMouseYChanged: {
if (configListView.dragging) { if (configListView.dragging) {
var mouseXInListView = configListView.contentItem.mapFromItem(dndArea, mouseX, mouseY).x; var mouseYInListView = configListView.contentItem.mapFromItem(dndArea, mouseX, mouseY).y;
var indexUnderMouse = configListView.indexAt(mouseXInListView - dndArea.dragOffset / 2, mouseY) var indexUnderMouse = configListView.indexAt(mouseX, mouseYInListView - dndArea.dragOffset / 2)
if (indexUnderMouse < 0) {
return;
}
indexUnderMouse = Math.min(Math.max(0, indexUnderMouse), configListView.count - 1) indexUnderMouse = Math.min(Math.max(0, indexUnderMouse), configListView.count - 1)
if (configListView.draggingIndex !== indexUnderMouse) { if (configListView.draggingIndex !== indexUnderMouse) {
print("moving to", indexUnderMouse)
PlatformHelper.vibrate(PlatformHelper.HapticsFeedbackSelection) PlatformHelper.vibrate(PlatformHelper.HapticsFeedbackSelection)
mainMenuModel.move(configListView.draggingIndex, indexUnderMouse, 1) mainMenuModel.move(configListView.draggingIndex, indexUnderMouse, 1)
configListView.draggingIndex = indexUnderMouse; configListView.draggingIndex = indexUnderMouse;
@ -487,8 +528,8 @@ Page {
} }
onReleased: { onReleased: {
print("released!") print("released!")
var mouseXInListView = configListView.contentItem.mapFromItem(dndArea, mouseX, mouseY).x; var mouseYInListView = configListView.contentItem.mapFromItem(dndArea, mouseX, mouseY).y;
var clickedIndex = configListView.indexAt(mouseXInListView, mouseY) var clickedIndex = configListView.indexAt(mouseX, mouseYInListView)
var item = mainMenuModel.get(clickedIndex) var item = mainMenuModel.get(clickedIndex)
var isEnabled = mainViewSettings.filterList.indexOf(item.name) >= 0; var isEnabled = mainViewSettings.filterList.indexOf(item.name) >= 0;
if (!configListView.dragging) { if (!configListView.dragging) {
@ -519,114 +560,244 @@ Page {
} }
mainViewSettings.sortOrder = newSortOrder; mainViewSettings.sortOrder = newSortOrder;
} }
Timer { // Timer {
id: scroller // id: scroller
interval: 2 // interval: 2
repeat: true // repeat: true
running: direction != 0 // running: direction != 0
property int direction: { // property int direction: {
if (!configListView.dragging) { // if (!configListView.dragging) {
return 0; // return 0;
} // }
return dndArea.mouseX < 50 ? -2 : dndArea.mouseX > dndArea.width - 50 ? 2 : 0 // return dndArea.mouseY < 50 ? -2 : dndArea.mouseY > dndArea.height - 50 ? 2 : 0
} // }
onTriggered: { // onTriggered: {
configListView.contentX = Math.min(Math.max(0, configListView.contentX + direction), configListView.contentWidth - configListView.width) // configListView.contentY = Math.min(Math.max(0, configListView.contentY + direction), configListView.contentHeight - configListView.height)
} // }
} // }
} }
delegate: BigTile { NymeaItemDelegate {
id: configDelegate
width: configListView.delegateWidth
height: configListView.height
property bool isEnabled: mainViewSettings.filterList.indexOf(model.name) >= 0
visible: configListView.draggingIndex !== index
leftPadding: 0
rightPadding: 0
topPadding: 0
bottomPadding: 0
header: RowLayout {
id: headerRow
width: parent.width
Label {
text: model.displayName
Layout.fillWidth: true
elide: Text.ElideRight
}
}
contentItem: Item {
Layout.fillWidth: true
implicitHeight: configListView.height - headerRow.height - Style.margins * 2
ColorIcon {
anchors.centerIn: parent
width: Math.min(parent.width, parent.height) * .6
height: width
name: Qt.resolvedUrl("images/" + model.icon + ".svg")
color: configDelegate.isEnabled ? Style.accentColor : Style.iconColor
}
}
}
Item {
id: dndItem id: dndItem
width: configListView.delegateWidth
height: configListView.height
property bool isEnabled: false
property string displayName: ""
property string icon: "things"
visible: configListView.dragging visible: configListView.dragging
x: dndArea.mouseX - dndArea.dragOffset y: dndArea.mouseY - dndArea.dragOffset
onVisibleChanged: { width: configListView.width
if (visible) { progressive: false
dragStartAnimation.start(); additionalItem: CheckBox {
} checked: dndItem.checked
anchors.verticalCenter: parent.verticalCenter
} }
NumberAnimation {
id: dragStartAnimation
target: dndItem
property: "scale"
from: 1
to: 0.95
duration: 200
}
BigTile {
id: dndTile
anchors.fill: parent
// anchors.margins: app.margins / 2
Material.elevation: 2
leftPadding: 0
rightPadding: 0
topPadding: 0
bottomPadding: 0
header: RowLayout {
Label {
text: dndItem.displayName
}
}
contentItem: Item {
Layout.fillWidth: true
implicitHeight: configListView.height - header.height
ColorIcon {
anchors.centerIn: parent
width: Math.min(parent.width, parent.height) * .6
height: width
name: Qt.resolvedUrl("images/" + dndItem.icon + ".svg")
color: dndItem.isEnabled ? Style.accentColor : Style.iconColor
}
}
}
} }
} }
// NumberAnimation {
// target: configOverlay
// property: "scale"
// duration: 200
// easing.type: Easing.InOutQuad
// from: 2
// to: 1
// running: true
// }
// NumberAnimation {
// target: configOverlay
// property: "opacity"
// duration: 200
// easing.type: Easing.InOutQuad
// from: 0
// to: 1
// running: true
// }
// ListView {
// id: configListView
// model: mainMenuModel
// width: parent.width
// height: parent.height / 3
// anchors.centerIn: parent
// orientation: ListView.Horizontal
// moveDisplaced: Transition {
// NumberAnimation { properties: "x,y"; duration: 200 }
// }
// property int delegateWidth: width / 3
// property bool dragging: draggingIndex >= 0
// property int draggingIndex : -1
// MouseArea {
// id: dndArea
// anchors.fill: parent
// preventStealing: configListView.dragging
// property int dragOffset: 0
// onPressAndHold: {
// mouse.accepted = true
// var mouseXInListView = configListView.contentItem.mapFromItem(dndArea, mouseX, mouseY).x;
// configListView.draggingIndex = configListView.indexAt(mouseXInListView, mouseY)
// var item = mainMenuModel.get(configListView.draggingIndex)
// dndItem.displayName = item.displayName
// dndItem.icon = item.icon
// var visualItem = configListView.itemAt(mouseXInListView, mouseY)
// dndItem.isEnabled = visualItem.isEnabled
// dndArea.dragOffset = configListView.mapToItem(visualItem, mouseX, mouseY).x
// PlatformHelper.vibrate(PlatformHelper.HapticsFeedbackImpact)
// }
// onMouseYChanged: {
// if (configListView.dragging) {
// var mouseXInListView = configListView.contentItem.mapFromItem(dndArea, mouseX, mouseY).x;
// var indexUnderMouse = configListView.indexAt(mouseXInListView - dndArea.dragOffset / 2, mouseY)
// indexUnderMouse = Math.min(Math.max(0, indexUnderMouse), configListView.count - 1)
// if (configListView.draggingIndex !== indexUnderMouse) {
// PlatformHelper.vibrate(PlatformHelper.HapticsFeedbackSelection)
// mainMenuModel.move(configListView.draggingIndex, indexUnderMouse, 1)
// configListView.draggingIndex = indexUnderMouse;
// }
// }
// }
// onReleased: {
// print("released!")
// var mouseXInListView = configListView.contentItem.mapFromItem(dndArea, mouseX, mouseY).x;
// var clickedIndex = configListView.indexAt(mouseXInListView, mouseY)
// var item = mainMenuModel.get(clickedIndex)
// var isEnabled = mainViewSettings.filterList.indexOf(item.name) >= 0;
// if (!configListView.dragging) {
// var newList = []
// for (var i = 0; i < mainMenuModel.count; i++) {
// var entry = mainMenuModel.get(i).name;
// if (entry === item.name) {
// if (!isEnabled) {
// newList.push(item.name)
// }
// } else {
// if (mainViewSettings.filterList.indexOf(entry) >= 0) {
// newList.push(entry)
// }
// }
// }
// if (newList.length === 0) {
// newList.push(Configuration.defaultMainView)
// }
// mainViewSettings.filterList = newList
// }
// configListView.draggingIndex = -1;
// var newSortOrder = []
// for (var i = 0; i < mainMenuModel.count; i++) {
// newSortOrder.push(mainMenuModel.get(i).name)
// }
// mainViewSettings.sortOrder = newSortOrder;
// }
// Timer {
// id: scroller
// interval: 2
// repeat: true
// running: direction != 0
// property int direction: {
// if (!configListView.dragging) {
// return 0;
// }
// return dndArea.mouseX < 50 ? -2 : dndArea.mouseX > dndArea.width - 50 ? 2 : 0
// }
// onTriggered: {
// configListView.contentX = Math.min(Math.max(0, configListView.contentX + direction), configListView.contentWidth - configListView.width)
// }
// }
// }
// delegate: BigTile {
// id: configDelegate
// width: configListView.delegateWidth
// height: configListView.height
// property bool isEnabled: mainViewSettings.filterList.indexOf(model.name) >= 0
// visible: configListView.draggingIndex !== index
// leftPadding: 0
// rightPadding: 0
// topPadding: 0
// bottomPadding: 0
// header: RowLayout {
// id: headerRow
// width: parent.width
// Label {
// text: model.displayName
// Layout.fillWidth: true
// elide: Text.ElideRight
// }
// }
// contentItem: Item {
// Layout.fillWidth: true
// implicitHeight: configListView.height - headerRow.height - Style.margins * 2
// ColorIcon {
// anchors.centerIn: parent
// width: Math.min(parent.width, parent.height) * .6
// height: width
// name: Qt.resolvedUrl("images/" + model.icon + ".svg")
// color: configDelegate.isEnabled ? Style.accentColor : Style.iconColor
// }
// }
// }
// Item {
// id: dndItem
// width: configListView.delegateWidth
// height: configListView.height
// property bool isEnabled: false
// property string displayName: ""
// property string icon: "things"
// visible: configListView.dragging
// x: dndArea.mouseX - dndArea.dragOffset
// onVisibleChanged: {
// if (visible) {
// dragStartAnimation.start();
// }
// }
// NumberAnimation {
// id: dragStartAnimation
// target: dndItem
// property: "scale"
// from: 1
// to: 0.95
// duration: 200
// }
// BigTile {
// id: dndTile
// anchors.fill: parent
// // anchors.margins: app.margins / 2
// Material.elevation: 2
// leftPadding: 0
// rightPadding: 0
// topPadding: 0
// bottomPadding: 0
// header: RowLayout {
// Label {
// text: dndItem.displayName
// }
// }
// contentItem: Item {
// Layout.fillWidth: true
// implicitHeight: configListView.height - header.height
// ColorIcon {
// anchors.centerIn: parent
// width: Math.min(parent.width, parent.height) * .6
// height: width
// name: Qt.resolvedUrl("images/" + dndItem.icon + ".svg")
// color: dndItem.isEnabled ? Style.accentColor : Style.iconColor
// }
// }
// }
// }
// }
} }
} }

View File

@ -47,18 +47,20 @@ TabButton {
spacing: root.alignment == Qt.Horizontal ? app.margins : app.margins / 2 spacing: root.alignment == Qt.Horizontal ? app.margins : app.margins / 2
horizontalItemAlignment: Grid.AlignHCenter horizontalItemAlignment: Grid.AlignHCenter
verticalItemAlignment: Grid.AlignVCenter verticalItemAlignment: Grid.AlignVCenter
opacity: root.checked ? 1 : .4
Behavior on opacity { NumberAnimation { duration: Style.animationDuration; easing.type: Easing.InOutQuad } }
ColorIcon { ColorIcon {
width: Style.iconSize width: Style.iconSize
height: Style.iconSize height: Style.iconSize
name: root.iconSource name: root.iconSource
color: root.checked ? Style.accentColor : Style.iconColor color: Style.foregroundColor
} }
Label { Label {
id: textLabel id: textLabel
text: root.text text: root.text
font.pixelSize: app.smallFont font.pixelSize: app.smallFont
color: root.checked ? Style.accentColor : Material.foreground color: Style.foregroundColor
} }
} }
} }

View File

@ -44,10 +44,15 @@ Item {
property bool isCurrentItem: false property bool isCurrentItem: false
property int topMargin: 40 property int topMargin: 40
property int bottomMargin: 64
property int contentY: 0 // Relative to topMargin property int contentY: 0 // Relative to topMargin
property var headerButtons: [] property var headerButtons: []
Background {
anchors.fill: parent
}
// Prevent scroll events to swipe left/right in case they fall through the grid // Prevent scroll events to swipe left/right in case they fall through the grid
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent

View File

@ -97,6 +97,7 @@ MainViewBase {
contentHeight: energyGrid.childrenRect.height contentHeight: energyGrid.childrenRect.height
visible: !engine.thingManager.fetchingData && engine.jsonRpcClient.experiences.hasOwnProperty("Energy") && engine.jsonRpcClient.experiences["Energy"] >= "0.2" visible: !engine.thingManager.fetchingData && engine.jsonRpcClient.experiences.hasOwnProperty("Energy") && engine.jsonRpcClient.experiences["Energy"] >= "0.2"
topMargin: root.topMargin topMargin: root.topMargin
bottomMargin: root.bottomMargin
// GridLayout directly in a flickable causes problems at initialisation // GridLayout directly in a flickable causes problems at initialisation
Item { Item {

View File

@ -53,6 +53,8 @@ MainViewBase {
anchors.fill: parent anchors.fill: parent
anchors.margins: app.margins / 2 anchors.margins: app.margins / 2
topMargin: root.topMargin topMargin: root.topMargin
bottomMargin: root.bottomMargin
readonly property int minTileWidth: 172 readonly property int minTileWidth: 172
readonly property int tilesPerRow: root.width / minTileWidth readonly property int tilesPerRow: root.width / minTileWidth

View File

@ -51,7 +51,7 @@ MainViewBase {
id: swipeView id: swipeView
anchors.fill: parent anchors.fill: parent
anchors.topMargin: root.topMargin anchors.topMargin: root.topMargin
anchors.bottomMargin: pageIndicator.visible ? pageIndicator.height : 0 anchors.bottomMargin: root.bottomMargin + (pageIndicator.visible ? pageIndicator.height : 0)
Repeater { Repeater {
model: garagesFilterModel model: garagesFilterModel

View File

@ -44,6 +44,7 @@ MainViewBase {
anchors.fill: parent anchors.fill: parent
anchors.margins: app.margins / 2 anchors.margins: app.margins / 2
topMargin: root.topMargin topMargin: root.topMargin
bottomMargin: root.bottomMargin
readonly property int minTileWidth: 172 readonly property int minTileWidth: 172
readonly property int tilesPerRow: root.width / minTileWidth readonly property int tilesPerRow: root.width / minTileWidth

View File

@ -50,7 +50,7 @@ MainViewBase {
SwipeView { SwipeView {
id: swipeView id: swipeView
anchors { left: parent.left; top: parent.top; right: parent.right; bottom: parent.bottom } anchors { left: parent.left; top: parent.top; right: parent.right; bottom: parent.bottom; bottomMargin: root.bottomMargin }
currentIndex: pageIndicator.currentIndex currentIndex: pageIndicator.currentIndex
Repeater { Repeater {
@ -67,6 +67,7 @@ MainViewBase {
currentIndex: swipeView.currentIndex currentIndex: swipeView.currentIndex
interactive: true interactive: true
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.bottomMargin: root.bottomMargin
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
} }

View File

@ -45,6 +45,7 @@ MainViewBase {
anchors.fill: parent anchors.fill: parent
anchors.margins: app.margins / 2 anchors.margins: app.margins / 2
topMargin: root.topMargin topMargin: root.topMargin
bottomMargin: root.bottomMargin
readonly property int minTileWidth: 172 readonly property int minTileWidth: 172
readonly property int tilesPerRow: root.width / minTileWidth readonly property int tilesPerRow: root.width / minTileWidth

View File

@ -57,6 +57,7 @@ MainViewBase {
anchors.fill: parent anchors.fill: parent
anchors.margins: app.margins / 2 anchors.margins: app.margins / 2
topMargin: root.topMargin topMargin: root.topMargin
bottomMargin: root.bottomMargin
model: mainModel model: mainModel
readonly property int minTileWidth: 172 readonly property int minTileWidth: 172

View File

@ -37,7 +37,7 @@ import Nymea 1.0
import "../../components" import "../../components"
import "../../delegates" import "../../delegates"
Item { MainViewBase {
id: root id: root
property var model: null property var model: null
@ -75,9 +75,10 @@ Item {
Flickable { Flickable {
id: flickable id: flickable
anchors.fill: parent anchors.fill: parent
anchors.margins: app.margins / 2 anchors.margins: Style.smallMargins
contentHeight: Math.max(layout.implicitHeight, height) contentHeight: Math.max(layout.implicitHeight, height)
contentWidth: width contentWidth: width
bottomMargin: root.bottomMargin
MouseArea { MouseArea {
width: flickable.contentWidth width: flickable.contentWidth