summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Dirk Hohndel <dirk@hohndel.org>2019-11-11 22:03:40 +0100
committerGravatar Dirk Hohndel <dirk@hohndel.org>2020-03-09 12:41:11 -0700
commitb382445e59c97e93ef53e0e6e378b8ec11f12a27 (patch)
tree8c29fece5ce2cb3aae58b02d70f39e54cfc3d5ac
parent64ae6d54a7e506051917bddb50424257ccf5c1cf (diff)
downloadsubsurface-b382445e59c97e93ef53e0e6e378b8ec11f12a27.tar.gz
mobile/divelist: rewrite the QML dive list
This isn't perfect yet, but it looks fairly reasonable. This commit was mainly written by Dirk, but includes a few fixes from Berthold which where squashed into this commit as they really should have been part of the initial version. Signed-off-by: Dirk Hohndel <dirk@hohndel.org> Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
-rw-r--r--mobile-widgets/qml/DiveList.qml548
-rw-r--r--mobile-widgets/qml/main.qml4
2 files changed, 209 insertions, 343 deletions
diff --git a/mobile-widgets/qml/DiveList.qml b/mobile-widgets/qml/DiveList.qml
index ae866f23c..a9ff4e8d6 100644
--- a/mobile-widgets/qml/DiveList.qml
+++ b/mobile-widgets/qml/DiveList.qml
@@ -12,19 +12,8 @@ Kirigami.ScrollablePage {
objectName: "DiveList"
title: qsTr("Dive list")
verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff
- property int numDives: diveListView.count
- property color textColor: subsurfaceTheme.textColor
- property color secondaryTextColor: subsurfaceTheme.secondaryTextColor
property int horizontalPadding: Kirigami.Units.gridUnit / 2 - Kirigami.Units.smallSpacing + 1
- property QtObject diveListModel: diveTripModel
-
- opacity: 0
- Behavior on opacity {
- NumberAnimation {
- duration: 200
- easing.type: Easing.OutQuad
- }
- }
+ property QtObject diveListModel: mobileListModel
supportsRefreshing: true
onRefreshingChanged: {
@@ -34,377 +23,253 @@ Kirigami.ScrollablePage {
manager.saveChangesCloud(true)
refreshing = false
} else {
- manager.appendTextToLog("sync with cloud storage requested, but credential status is " + PrefCloudStorage.cloud_verification_status)
+ manager.appendTextToLog("sync with cloud storage requested, but credentialStatus is " + Backend.cloud_verification_status)
manager.appendTextToLog("no syncing, turn off spinner")
refreshing = false
}
}
}
- onVisibleChanged: {
- if (visible) {
- page.actions.main = page.downloadFromDCAction
- page.actions.right = page.addDiveAction
- page.actions.left = page.filterToggleAction
- page.title = qsTr("Dive list")
- if (diveListView.count === 0)
- showPassiveNotification(qsTr("Please tap the '+' button to add a dive (or download dives from a supported dive computer)"), 3000)
- }
- }
Component {
- id: diveDelegate
+ id: diveOrTripDelegate
Kirigami.AbstractListItem {
// this allows us to access properties of the currentItem from outside
property variant myData: model
-
- leftPadding: 0
- topPadding: 0
- id: innerListItem
- enabled: true
+ id: diveOrTripDelegateItem
+ padding: 0
supportsMouseEvents: true
- checked: model.selected
- width: parent.width
- height: (collapsed & 1) ? diveListEntry.height + Kirigami.Units.smallSpacing : 0
- visible: collapsed & 1
- backgroundColor: checked ? subsurfaceTheme.primaryColor : subsurfaceTheme.backgroundColor
- activeBackgroundColor: subsurfaceTheme.primaryColor
- textColor: checked ? subsurfaceTheme.primaryTextColor : subsurfaceTheme.textColor
+ checked: !isTrip && current
+ anchors {
+ left: parent.left
+ right: parent.right
+ }
+ height: (isTrip ? 9 : 11) * Kirigami.Units.smallSpacing // delegateInnerItem.height
- states: [
- State {
- name: "isHidden";
- when: (collapsed & 1) == 0
- PropertyChanges {
- target: innerListItem
- height: 0
- visible: false
- }
- },
- State {
- name: "isVisible";
- when: (collapsed & 1) == 1
- PropertyChanges {
- target: innerListItem
- height: diveListEntry.height + Kirigami.Units.smallSpacing
- visible: true
- }
- }
- ]
- // When clicked, the mode changes to details view
+ // When clicked, a trip expands / unexpands, a dive is opened in DiveDetails
onClicked: {
- if (detailsWindow.state === "view") {
- //diveListView.currentIndex = index
- detailsWindow.showDiveIndex(id);
- // switch to detailsWindow (or push it if it's not in the stack)
- var i = rootItem.pageIndex(detailsWindow)
- if (i === -1)
- pageStack.push(detailsWindow)
- else
- pageStack.currentIndex = i
+ if (isTrip) {
+ manager.appendTextToLog("clicked on trip " + tripTitle)
+ // toggle expand (backend to deal with unexpand other trip)
+ manager.toggle(model.row);
+ } else {
+ manager.appendTextToLog("clicked on dive")
+ if (detailsWindow.state === "view") {
+ detailsWindow.showDiveIndex(id); // we need access to dive->id
+ // switch to detailsWindow (or push it if it's not in the stack)
+ var i = rootItem.pageIndex(detailsWindow)
+ if (i === -1)
+ pageStack.push(detailsWindow)
+ else
+ pageStack.currentIndex = i
+ }
}
}
- property bool deleteButtonVisible: false
- property bool copyButtonVisible: false
- property bool pasteButtonVisible: false
-
- onPressAndHold: {
- deleteButtonVisible = true
- copyButtonVisible = true
- pasteButtonVisible = true
- timer.restart()
- }
+ // first we look at the trip
Item {
+ id: delegateInnerItem
+ width: page.width
+ height: childrenRect.height
Rectangle {
- id: leftBarDive
- width: tripId == "" ? 0 : Kirigami.Units.smallSpacing
- height: diveListEntry.height * 0.8
- color: subsurfaceTheme.lightPrimaryColor
+ id: headingBackground
+ height: visible ? 8 * Kirigami.Units.smallSpacing : 0
anchors {
+ topMargin: Kirigami.Units.smallSpacing / 2
left: parent.left
- top: parent.top
- leftMargin: Kirigami.Units.smallSpacing
- topMargin: Kirigami.Units.smallSpacing * 2
- bottomMargin: Kirigami.Units.smallSpacing * 2
+ right: parent.right
}
- }
- Item {
- id: diveListEntry
- width: parent.width - Kirigami.Units.gridUnit * (innerListItem.deleteButtonVisible ? 3 * 3 : 1)
- height: Math.ceil(childrenRect.height + Kirigami.Units.smallSpacing)
- anchors.left: leftBarDive.right
- Controls.Label {
- id: locationText
- text: (undefined !== location && "" != location) ? location : qsTr("<unnamed dive site>")
- font.weight: Font.Bold
- font.pointSize: subsurfaceTheme.regularPointSize
- elide: Text.ElideRight
- maximumLineCount: 1 // needed for elide to work at all
- color: textColor
+ color: subsurfaceTheme.lightPrimaryColor
+ visible: isTrip
+ Rectangle {
+ id: dateBox
+ height: 1.8 * Kirigami.Units.gridUnit
+ width: 2.2 * Kirigami.Units.gridUnit
+ color: subsurfaceTheme.primaryColor
+ radius: Kirigami.Units.smallSpacing * 2
+ antialiasing: true
anchors {
+ verticalCenter: parent.verticalCenter
left: parent.left
- leftMargin: horizontalPadding * 2
- topMargin: Kirigami.Units.smallSpacing
- top: parent.top
- right: parent.right
- }
- }
- Row {
- anchors {
- left: locationText.left
- top: locationText.bottom
- topMargin: Kirigami.Units.smallSpacing
- bottom: numberText.bottom
+ leftMargin: Kirigami.Units.smallSpacing
}
-
- Controls.Label {
- id: dateLabel
- text: (undefined !== dateTime) ? dateTime : ""
- width: Math.max(locationText.width * 0.45, paintedWidth) // helps vertical alignment throughout listview
- font.pointSize: subsurfaceTheme.smallPointSize
- color: innerListItem.checked ? subsurfaceTheme.darkerPrimaryTextColor : secondaryTextColor
- }
- // spacer, just in case
Controls.Label {
- text: " "
- width: Kirigami.Units.largeSpacing
- }
- // let's try to show the depth / duration very compact
- Controls.Label {
- text: (undefined !== depthDuration) ? depthDuration : ""
- width: Math.max(Kirigami.Units.gridUnit * 3, paintedWidth) // helps vertical alignment throughout listview
- font.pointSize: subsurfaceTheme.smallPointSize
- color: innerListItem.checked ? subsurfaceTheme.darkerPrimaryTextColor : secondaryTextColor
+ visible: headingBackground.visible
+ text: visible ? tripShortDate : ""
+ color: subsurfaceTheme.primaryTextColor
+ font.pointSize: subsurfaceTheme.smallPointSize * 0.8
+ lineHeightMode: Text.FixedHeight
+ lineHeight: Kirigami.Units.gridUnit *.8
+ horizontalAlignment: Text.AlignHCenter
+ height: contentHeight
+ anchors {
+ horizontalCenter: parent.horizontalCenter
+ verticalCenter: parent.verticalCenter
+ }
}
}
Controls.Label {
- id: numberText
- text: "#" + number
- font.pointSize: subsurfaceTheme.smallPointSize
- color: innerListItem.checked ? subsurfaceTheme.darkerPrimaryTextColor : secondaryTextColor
- anchors {
- right: parent.right
- rightMargin: horizontalPadding
- top: locationText.bottom
- topMargin: Kirigami.Units.smallSpacing
- }
- }
- }
- Rectangle {
- id: copyButton
- visible: copyButtonVisible
- height: diveListEntry.height - 2 * Kirigami.Units.smallSpacing
- width: height
- color: subsurfaceTheme.lightDrawerColor
- antialiasing: true
- radius: Kirigami.Units.smallSpacing
- anchors {
- left: diveListEntry.right
- verticalCenter: diveListEntry.verticalCenter
- verticalCenterOffset: Kirigami.Units.smallSpacing / 2
- rightMargin: horizontalPadding * 2
- leftMargin: horizontalPadding * 2
- }
- Kirigami.Icon {
+ text: visible ? tripTitle : ""
+ elide: Text.ElideRight
+ visible: headingBackground.visible
+ font.weight: Font.Medium
+ font.pointSize: subsurfaceTheme.regularPointSize
anchors {
- horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
+ left: dateBox.right
+ leftMargin: horizontalPadding * 2
+ right: parent.right
}
- source: ":/icons/edit-copy"
- width: parent.height
- height: width
- }
- MouseArea {
- anchors.fill: parent
- enabled: parent.visible
- onClicked: {
- deleteButtonVisible = false
- copyButtonVisible = false
- pasteButtonVisible = false
- timer.stop()
- manager.copyDiveData(id)
- }
- onPressAndHold: {
- globalDrawer.close()
- manager.copyDiveData(id)
- pageStack.push(settingsCopyWindow)
- }
+ color: subsurfaceTheme.lightPrimaryTextColor
}
}
Rectangle {
- id: pasteButton
- visible: pasteButtonVisible
- height: diveListEntry.height - 2 * Kirigami.Units.smallSpacing
- width: height
- color: subsurfaceTheme.lightDrawerColor
- antialiasing: true
- radius: Kirigami.Units.smallSpacing
+ id: headingBottomLine
+ height: visible ? Kirigami.Units.smallSpacing : 0
+ visible: headingBackground.visible
anchors {
- left: copyButton.right
- verticalCenter: diveListEntry.verticalCenter
- verticalCenterOffset: Kirigami.Units.smallSpacing / 2
- rightMargin: horizontalPadding * 2
- leftMargin: horizontalPadding * 2
- }
- Kirigami.Icon {
- anchors {
- horizontalCenter: parent.horizontalCenter
- verticalCenter: parent.verticalCenter
- }
- source: ":/icons/edit-paste"
- width: parent.height
- height: width
- }
- MouseArea {
- anchors.fill: parent
- enabled: parent.visible
- onClicked: {
- deleteButtonVisible = false
- copyButtonVisible = false
- pasteButtonVisible = false
- timer.stop()
- manager.pasteDiveData(id)
- }
+ left: parent.left
+ right: parent.right
+ top: headingBackground.bottom
}
+ color: "#B2B2B2"
}
+
Rectangle {
- id: deleteButton
- visible: deleteButtonVisible
- height: diveListEntry.height - 2 * Kirigami.Units.smallSpacing
- width: height
- color: subsurfaceTheme.contrastAccentColor
- antialiasing: true
- radius: Kirigami.Units.smallSpacing
+ id: diveBackground
+ height: visible ? diveListEntry.height + Kirigami.Units.smallSpacing : 0
anchors {
- left: pasteButton.right
+ left: parent.left
right: parent.right
- verticalCenter: diveListEntry.verticalCenter
- verticalCenterOffset: Kirigami.Units.smallSpacing / 2
- rightMargin: horizontalPadding * 2
- leftMargin: horizontalPadding * 2
}
- Kirigami.Icon {
- anchors {
- horizontalCenter: parent.horizontalCenter
- verticalCenter: parent.verticalCenter
- }
- source: ":/icons/trash-empty"
- width: parent.height
- height: width
- }
- MouseArea {
+ color: subsurfaceTheme.backgroundColor
+ visible: !isTrip
+ Item {
anchors.fill: parent
- enabled: parent.visible
- onClicked: {
- deleteButtonVisible = false
- copyButtonVisible = false
- pasteButtonVisible = false
- timer.stop()
- manager.deleteDive(id)
+ Rectangle {
+ id: leftBarDive
+ width: Kirigami.Units.smallSpacing
+ height: isTopLevel ? 0 : diveListEntry.height * 0.8
+ color: subsurfaceTheme.lightPrimaryColor
+ anchors {
+ left: parent.left
+ top: parent.top
+ leftMargin: Kirigami.Units.smallSpacing
+ topMargin: Kirigami.Units.smallSpacing * 2
+ bottomMargin: Kirigami.Units.smallSpacing * 2
+ }
+ }
+ Item {
+ id: diveListEntry
+ height: visible ? 10 * Kirigami.Units.smallSpacing : 0
+ anchors {
+ right: parent.right
+ left: leftBarDive.right
+ verticalCenter: parent.verticalCenter
+ }
+ Controls.Label {
+ id: locationText
+ text: (undefined !== location && "" != location) ? location : qsTr("<unnamed dive site>")
+ font.weight: Font.Medium
+ font.pointSize: subsurfaceTheme.smallPointSize
+ elide: Text.ElideRight
+ maximumLineCount: 1 // needed for elide to work at all
+ color: subsurfaceTheme.textColor
+ anchors {
+ left: parent.left
+ leftMargin: horizontalPadding * 2
+ topMargin: Kirigami.Units.smallSpacing / 2
+ top: parent.top
+ right: parent.right
+ }
+ }
+ Row {
+ anchors {
+ left: locationText.left
+ top: locationText.bottom
+ topMargin: Kirigami.Units.smallSpacing / 2
+ }
+
+ Controls.Label {
+ id: dateLabel
+ text: (undefined !== dateTime) ? dateTime : ""
+ width: Math.max(locationText.width * 0.45, paintedWidth) // helps vertical alignment throughout listview
+ font.pointSize: subsurfaceTheme.smallPointSize
+ color: diveOrTripDelegateItem.checked ? subsurfaceTheme.darkerPrimaryTextColor : subsurfaceTheme.secondaryTextColor
+ }
+ // spacer, just in case
+ Controls.Label {
+ text: " "
+ width: Kirigami.Units.largeSpacing
+ }
+ // let's try to show the depth / duration very compact
+ Controls.Label {
+ text: (undefined !== depthDuration) ? depthDuration : ""
+ width: Math.max(Kirigami.Units.gridUnit * 3, paintedWidth) // helps vertical alignment throughout listview
+ font.pointSize: subsurfaceTheme.smallPointSize
+ color: diveOrTripDelegateItem.checked ? subsurfaceTheme.darkerPrimaryTextColor : subsurfaceTheme.secondaryTextColor
+ }
+ }
+ Controls.Label {
+ id: numberText
+ text: "#" + number
+ font.pointSize: subsurfaceTheme.smallPointSize
+ color: diveOrTripDelegateItem.checked ? subsurfaceTheme.darkerPrimaryTextColor : subsurfaceTheme.secondaryTextColor
+ anchors {
+ right: parent.right
+ rightMargin: Kirigami.Units.smallSpacing
+ top: locationText.bottom
+ topMargin: Kirigami.Units.smallSpacing / 2
+ }
+ }
}
}
}
- Timer {
- id: timer
- interval: 4000
- onTriggered: {
- deleteButtonVisible = false
- copyButtonVisible = false
- pasteButtonVisible = false
- }
- }
+
}
}
}
- Component {
- id: tripHeading
- Item {
- width: page.width
- height: childrenRect.height
- Rectangle {
- id: headingBackground
- height: section == "" ? 0 : sectionText.height + Kirigami.Units.gridUnit
- anchors {
- left: parent.left
- right: parent.right
- }
- color: subsurfaceTheme.lightPrimaryColor
- visible: section != ""
- Rectangle {
- id: dateBox
- visible: section != ""
- height: section == "" ? 0 : parent.height - Kirigami.Units.smallSpacing
- width: section == "" ? 0 : 2.5 * Kirigami.Units.gridUnit * PrefDisplay.mobile_scale
- color: subsurfaceTheme.primaryColor
- radius: Kirigami.Units.smallSpacing * 2
- antialiasing: true
- anchors {
- verticalCenter: parent.verticalCenter
- left: parent.left
- leftMargin: Kirigami.Units.smallSpacing
- }
- Controls.Label {
- text: {
- diveListModel ? diveListModel.tripShortDate(section) : "no data model"
- }
- color: subsurfaceTheme.primaryTextColor
- font.pointSize: subsurfaceTheme.smallPointSize
- lineHeightMode: Text.FixedHeight
- lineHeight: Kirigami.Units.gridUnit *.9
- horizontalAlignment: Text.AlignHCenter
- anchors {
- horizontalCenter: parent.horizontalCenter
- verticalCenter: parent.verticalCenter
- }
- }
- }
- MouseArea {
- anchors.fill: headingBackground
- onClicked: {
- if (diveListModel) {
- if (diveListModel.activeTrip() === section)
- diveListModel.setActiveTrip("")
- else
- diveListModel.setActiveTrip(section)
- }
- }
- }
- Controls.Label {
- id: sectionText
- text: {
- diveListModel ? diveListModel.tripTitle(section) : "no data model"
- }
- wrapMode: Text.WrapAtWordBoundaryOrAnywhere
- visible: text !== ""
- font.weight: Font.Bold
- font.pointSize: subsurfaceTheme.regularPointSize
- anchors {
- top: parent.top
- left: dateBox.right
- topMargin: Math.max(2, Kirigami.Units.gridUnit / 2)
- leftMargin: horizontalPadding * 2
- right: parent.right
- }
- color: subsurfaceTheme.lightPrimaryTextColor
- }
- }
- Rectangle {
- height: section == "" ? 0 : 1
- width: parent.width
- anchors.top: headingBackground.bottom
- color: "#B2B2B2"
+ StartPage {
+ id: startPage
+ anchors.fill: parent
+ opacity: (Backend.cloud_verification_status === Enums.CS_NOCLOUD ||
+ Backend.cloud_verification_status === Enums.CS_VERIFIED) ? 0 : 1
+ visible: opacity > 0
+ Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration } }
+ function setupActions() {
+ if (Backend.cloud_verification_status === Enums.CS_VERIFIED ||
+ Backend.cloud_verification_status === Enums.CS_NOCLOUD) {
+ page.actions.main = page.downloadFromDCAction
+ page.actions.right = page.addDiveAction
+ page.actions.left = page.filterToggleAction
+ page.title = qsTr("Dive list")
+ if (diveListView.count === 0)
+ showPassiveNotification(qsTr("Please tap the '+' button to add a dive (or download dives from a supported dive computer)"), 3000)
+ } else {
+ page.actions.main = null
+ page.actions.right = null
+ page.actions.left = null
+ page.title = qsTr("Cloud credentials")
}
}
+ onVisibleChanged: {
+ setupActions();
+ }
+
+ Component.onCompleted: {
+ manager.finishSetup();
+ setupActions();
+ }
}
Controls.Label {
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
- text: diveListModel ? qsTr("No dives in dive list") : qsTr("Please wait, filtering dive list")
+ text: diveListModel ? qsTr("No dives in dive list") : qsTr("Please wait, updating the dive list")
visible: diveListView.visible && diveListView.count === 0
}
+
Component {
id: filterHeader
Rectangle {
@@ -434,11 +299,8 @@ Kirigami.ScrollablePage {
]
transitions: [
- Transition {
- NumberAnimation { property: "height"; duration: 400; easing.type: Easing.InOutQuad }
- }
+ Transition { NumberAnimation { property: "height"; duration: 400; easing.type: Easing.InOutQuad }}
]
-
anchors.left: parent.left
anchors.right: parent.right
anchors.leftMargin: Kirigami.Units.gridUnit / 2
@@ -489,22 +351,19 @@ Kirigami.ScrollablePage {
ListView {
id: diveListView
anchors.fill: parent
+ opacity: 1.0 - startPage.opacity
+ visible: opacity > 0
model: diveListModel
currentIndex: -1
- delegate: diveDelegate
+ delegate: diveOrTripDelegate
header: filterHeader
headerPositioning: ListView.OverlayHeader
boundsBehavior: Flickable.DragOverBounds
maximumFlickVelocity: parent.height * 5
bottomMargin: Kirigami.Units.iconSizes.medium + Kirigami.Units.gridUnit
cacheBuffer: 40 // this will increase memory use, but should help with scrolling
- section.property: "tripId"
- section.criteria: ViewSection.FullString
- section.delegate: tripHeading
- section.labelPositioning: ViewSection.CurrentLabelAtStart | ViewSection.InlineLabels
- Connections {
- target: detailsWindow
- onCurrentIndexChanged: diveListView.currentIndex = detailsWindow.currentIndex
+ Component.onCompleted: {
+ manager.appendTextToLog("finished setting up the diveListView")
}
}
@@ -541,11 +400,18 @@ Kirigami.ScrollablePage {
}
onBackRequested: {
- if (Qt.platform.os != "ios")
- manager.quit()
-
- // let's make sure Kirigami doesn't quit on our behalf
- event.accepted = true
+ if (startPage.visible && diveListView.count > 0 &&
+ Backend.cloud_verification_status !== Enums.CS_INCORRECT_USER_PASSWD) {
+ Backend.cloud_verification_status = oldStatus
+ event.accepted = true;
+ }
+ if (!startPage.visible) {
+ if (Qt.platform.os != "ios") {
+ manager.quit()
+ }
+ // let's make sure Kirigami doesn't quit on our behalf
+ event.accepted = true
+ }
}
function setCurrentDiveListIndex(idx, noScroll) {
diff --git a/mobile-widgets/qml/main.qml b/mobile-widgets/qml/main.qml
index 70c9de9fc..f80061a29 100644
--- a/mobile-widgets/qml/main.qml
+++ b/mobile-widgets/qml/main.qml
@@ -55,7 +55,7 @@ Kirigami.ApplicationWindow {
}
function showBusy(msg) {
- if (msg !== undefined)
+ if (msg !== undefined && msg !== "")
showPassiveNotification(msg, 15000) // show for 15 seconds
busy.running = true
}
@@ -282,7 +282,7 @@ Kirigami.ApplicationWindow {
pageStack.pop()
}
diveList.diveListModel = diveModel
- pageStack.push(diveList)
+ showDiveList()
hideBusy()
}
}