mirror of
				https://github.com/subsurface/subsurface.git
				synced 2025-02-19 22:16:15 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			614 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			QML
		
	
	
	
	
	
			
		
		
	
	
			614 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			QML
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0
 | |
| import QtQuick 2.6
 | |
| import QtQuick.Controls 2.2 as Controls
 | |
| import QtQuick.Layouts 1.2
 | |
| import QtQuick.Window 2.2
 | |
| import QtQuick.Dialogs 1.2
 | |
| import org.kde.kirigami 2.5 as Kirigami
 | |
| import org.subsurfacedivelog.mobile 1.0
 | |
| 
 | |
| Kirigami.ScrollablePage {
 | |
| 	id: page
 | |
| 	objectName: "DiveList"
 | |
| 	title: qsTr("Dive list")
 | |
| 	verticalScrollBarPolicy: Qt.ScrollBarAlwaysOff
 | |
| 	width: subsurfaceTheme.columnWidth
 | |
| 	property int credentialStatus: prefs.credentialStatus
 | |
| 	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 string activeTrip
 | |
| 	property QtObject diveListModel: diveModel
 | |
| 	property string numShownText
 | |
| 
 | |
| 	supportsRefreshing: true
 | |
| 	onRefreshingChanged: {
 | |
| 		if (refreshing) {
 | |
| 			if (prefs.credentialStatus === CloudStatus.CS_VERIFIED) {
 | |
| 				detailsWindow.endEditMode()
 | |
| 				manager.saveChangesCloud(true)
 | |
| 				refreshing = false
 | |
| 			} else {
 | |
| 				console.log("sync with cloud storage requested, but credentialStatus is " + prefs.credentialStatus)
 | |
| 				console.log("no syncing, turn off spinner")
 | |
| 				refreshing = false
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	Component {
 | |
| 		id: diveDelegate
 | |
| 		Kirigami.AbstractListItem {
 | |
| 			// this looks weird, but it's how we can tell that this dive isn't in a trip
 | |
| 			property bool diveOutsideTrip: dive.tripNrDives === 0
 | |
| 			leftPadding: 0
 | |
| 			topPadding: 0
 | |
| 			id: innerListItem
 | |
| 			enabled: true
 | |
| 			supportsMouseEvents: true
 | |
| 			checked: diveListView.currentIndex === model.index
 | |
| 			width: parent.width
 | |
| 			height: diveOutsideTrip ? diveListEntry.height + Kirigami.Units.smallSpacing : 0
 | |
| 			visible: diveOutsideTrip
 | |
| 			backgroundColor: checked ? subsurfaceTheme.primaryColor : subsurfaceTheme.backgroundColor
 | |
| 			activeBackgroundColor: subsurfaceTheme.primaryColor
 | |
| 			textColor: checked ? subsurfaceTheme.primaryTextColor : subsurfaceTheme.textColor
 | |
| 
 | |
| 			states: [
 | |
| 				State {
 | |
| 					name: "isHidden";
 | |
| 					when: dive.tripId !== activeTrip && ! diveOutsideTrip
 | |
| 					PropertyChanges {
 | |
| 						target: innerListItem
 | |
| 						height: 0
 | |
| 						visible: false
 | |
| 					}
 | |
| 				},
 | |
| 				State {
 | |
| 					name: "isVisible";
 | |
| 					when: dive.tripId === activeTrip || diveOutsideTrip
 | |
| 					PropertyChanges {
 | |
| 						target: innerListItem
 | |
| 						height: diveListEntry.height + Kirigami.Units.smallSpacing
 | |
| 						visible: true
 | |
| 					}
 | |
| 				}
 | |
| 			]
 | |
| 			transitions: [
 | |
| 				Transition {
 | |
| 					from: "isHidden"
 | |
| 					to: "isVisible"
 | |
| 					SequentialAnimation {
 | |
| 						NumberAnimation {
 | |
| 							property: "visible"
 | |
| 							duration: 1
 | |
| 						}
 | |
| 						NumberAnimation {
 | |
| 							property: "height"
 | |
| 							duration: 200 + 20 * dive.tripNrDives
 | |
| 							easing.type: Easing.InOutQuad
 | |
| 						}
 | |
| 					}
 | |
| 				},
 | |
| 				Transition {
 | |
| 					from: "isVisible"
 | |
| 					to: "isHidden"
 | |
| 					SequentialAnimation {
 | |
| 						NumberAnimation {
 | |
| 							property: "height"
 | |
| 							duration: 200 + 20 * dive.tripNrDives
 | |
| 							easing.type: Easing.InOutQuad
 | |
| 						}
 | |
| 						NumberAnimation {
 | |
| 							property: "visible"
 | |
| 							duration: 1
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 			]
 | |
| 
 | |
| 			// When clicked, the mode changes to details view
 | |
| 			onClicked: {
 | |
| 				if (detailsWindow.state === "view") {
 | |
| 					diveListView.currentIndex = index
 | |
| 					detailsWindow.showDiveIndex(index);
 | |
| 					pageStack.push(detailsWindow);
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			property bool deleteButtonVisible: false
 | |
| 			property bool copyButtonVisible: false
 | |
| 			property bool pasteButtonVisible: false
 | |
| 
 | |
| 			onPressAndHold: {
 | |
| 				deleteButtonVisible = true
 | |
| 				copyButtonVisible = true
 | |
| 				pasteButtonVisible = true
 | |
| 				timer.restart()
 | |
| 			}
 | |
| 			Item {
 | |
| 				Rectangle {
 | |
| 					id: leftBarDive
 | |
| 					width: dive.tripId == "" ? 0 : Kirigami.Units.smallSpacing
 | |
| 					height: 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
 | |
| 					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: dive.location
 | |
| 						font.weight: Font.Bold
 | |
| 						font.pointSize: subsurfaceTheme.regularPointSize
 | |
| 						elide: Text.ElideRight
 | |
| 						maximumLineCount: 1 // needed for elide to work at all
 | |
| 						color: textColor
 | |
| 						anchors {
 | |
| 							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
 | |
| 						}
 | |
| 
 | |
| 						Controls.Label {
 | |
| 							id: dateLabel
 | |
| 							text: dive.date + " " + dive.time
 | |
| 							width: Math.max(locationText.width * 0.45, paintedWidth) // helps vertical alignment throughout listview
 | |
| 							font.pointSize: subsurfaceTheme.smallPointSize
 | |
| 							color: innerListItem.checked ? subsurfaceTheme.darkerPrimaryTextColor : secondaryTextColor
 | |
| 						}
 | |
| 						// let's try to show the depth / duration very compact
 | |
| 						Controls.Label {
 | |
| 							text: dive.depth + ' / ' + dive.duration
 | |
| 							width: Math.max(Kirigami.Units.gridUnit * 3, paintedWidth) // helps vertical alignment throughout listview
 | |
| 							font.pointSize: subsurfaceTheme.smallPointSize
 | |
| 							color: innerListItem.checked ? subsurfaceTheme.darkerPrimaryTextColor : secondaryTextColor
 | |
| 						}
 | |
| 					}
 | |
| 					Controls.Label {
 | |
| 						id: numberText
 | |
| 						text: "#" + dive.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 {
 | |
| 						anchors {
 | |
| 							horizontalCenter: parent.horizontalCenter
 | |
| 							verticalCenter: parent.verticalCenter
 | |
| 						}
 | |
| 						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(dive.id)
 | |
| 						}
 | |
| 						onPressAndHold: {
 | |
| 								globalDrawer.close()
 | |
| 								manager.copyDiveData(dive.id)
 | |
| 								pageStack.push(settingsCopyWindow)
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 				Rectangle {
 | |
| 					id: pasteButton
 | |
| 					visible: pasteButtonVisible
 | |
| 					height: diveListEntry.height - 2 * Kirigami.Units.smallSpacing
 | |
| 					width: height
 | |
| 					color: subsurfaceTheme.lightDrawerColor
 | |
| 					antialiasing: true
 | |
| 					radius: Kirigami.Units.smallSpacing
 | |
| 					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(dive.id)
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 				Rectangle {
 | |
| 					id: deleteButton
 | |
| 					visible: deleteButtonVisible
 | |
| 					height: diveListEntry.height - 2 * Kirigami.Units.smallSpacing
 | |
| 					width: height
 | |
| 					color: subsurfaceTheme.contrastAccentColor
 | |
| 					antialiasing: true
 | |
| 					radius: Kirigami.Units.smallSpacing
 | |
| 					anchors {
 | |
| 						left: pasteButton.right
 | |
| 						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 {
 | |
| 						anchors.fill: parent
 | |
| 						enabled: parent.visible
 | |
| 						onClicked: {
 | |
| 							deleteButtonVisible = false
 | |
| 							copyButtonVisible = false
 | |
| 							pasteButtonVisible = false
 | |
| 							timer.stop()
 | |
| 							manager.deleteDive(dive.id)
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 				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: {
 | |
| 							var trip = diveListView.model.tripIdToObject(section);
 | |
| 							diveListView.model.tripShortDate(trip);
 | |
| 						}
 | |
| 						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 (activeTrip === section)
 | |
| 							activeTrip = ""
 | |
| 						else
 | |
| 							activeTrip = section
 | |
| 					}
 | |
| 				}
 | |
| 				Controls.Label {
 | |
| 					id: sectionText
 | |
| 					text: {
 | |
| 						var trip = diveListView.model.tripIdToObject(section);
 | |
| 						diveListView.model.tripTitle(trip);
 | |
| 					}
 | |
| 					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: credentialStatus === CloudStatus.CS_NOCLOUD ||
 | |
| 									(credentialStatus === CloudStatus.CS_VERIFIED) ? 0 : 1
 | |
| 		visible: opacity > 0
 | |
| 		Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration } }
 | |
| 		function setupActions() {
 | |
| 			if (prefs.credentialStatus === CloudStatus.CS_VERIFIED ||
 | |
| 					prefs.credentialStatus === CloudStatus.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.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")
 | |
| 		visible: diveListView.visible && diveListView.count === 0
 | |
| 	}
 | |
| 	Component {
 | |
| 		id: filterHeader
 | |
| 		Rectangle {
 | |
| 			id: filterRectangle
 | |
| 			visible: filterBar.height > 0
 | |
| 			implicitHeight: filterBar.implicitHeight
 | |
| 			implicitWidth: filterBar.implicitWidth
 | |
| 			height: filterBar.height
 | |
| 			anchors.left: parent.left
 | |
| 			anchors.right: parent.right
 | |
| 			color: subsurfaceTheme.backgroundColor
 | |
| 			enabled: rootItem.filterToggle
 | |
| 			RowLayout {
 | |
| 				id: filterBar
 | |
| 				z: 5 //make sure it sits on top
 | |
| 				states: [
 | |
| 					State {
 | |
| 						name: "isVisible"
 | |
| 						when: rootItem.filterToggle
 | |
| 						PropertyChanges { target: filterBar; height: sitefilter.implicitHeight }
 | |
| 					},
 | |
| 					State {
 | |
| 						name: "isHidden"
 | |
| 						when: !rootItem.filterToggle
 | |
| 						PropertyChanges { target: filterBar; height: 0 }
 | |
| 					}
 | |
| 
 | |
| 				]
 | |
| 				transitions: [
 | |
| 					Transition {
 | |
| 						NumberAnimation { property: "height"; duration: 400; easing.type: Easing.InOutQuad }
 | |
| 					}
 | |
| 				]
 | |
| 
 | |
| 				anchors.left: parent.left
 | |
| 				anchors.right: parent.right
 | |
| 				anchors.leftMargin: Kirigami.Units.gridUnit / 2
 | |
| 				anchors.rightMargin: Kirigami.Units.gridUnit / 2
 | |
| 				Controls.TextField  {
 | |
| 					id: sitefilter
 | |
| 					z: 10
 | |
| 					verticalAlignment: TextInput.AlignVCenter
 | |
| 					Layout.fillWidth: true
 | |
| 					text: ""
 | |
| 					placeholderText: "Full text search"
 | |
| 					onAccepted: {
 | |
| 						manager.setFilter(text)
 | |
| 					}
 | |
| 					onEnabledChanged: {
 | |
| 						// reset the filter when it gets toggled
 | |
| 						text = ""
 | |
| 						if (visible) {
 | |
| 							forceActiveFocus()
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 				Controls.Label {
 | |
| 					id: numShown
 | |
| 					z: 10
 | |
| 					verticalAlignment: Text.AlignVCenter
 | |
| 					text: numShownText
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	ListView {
 | |
| 		id: diveListView
 | |
| 		anchors.fill: parent
 | |
| 		opacity: 1.0 - startPage.opacity
 | |
| 		visible: opacity > 0
 | |
| 		model: page.diveListModel
 | |
| 		currentIndex: -1
 | |
| 		delegate: diveDelegate
 | |
| 		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: "dive.tripId"
 | |
| 		section.criteria: ViewSection.FullString
 | |
| 		section.delegate: tripHeading
 | |
| 		section.labelPositioning: ViewSection.CurrentLabelAtStart | ViewSection.InlineLabels
 | |
| 		onModelChanged: {
 | |
| 			numShownText = diveModel.shown()
 | |
| 		}
 | |
| 		Connections {
 | |
| 			target: detailsWindow
 | |
| 			onCurrentIndexChanged: diveListView.currentIndex = detailsWindow.currentIndex
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	function showDownloadPage(vendor, product, connection) {
 | |
| 		downloadFromDc.dcImportModel.clearTable()
 | |
| 		pageStack.push(downloadFromDc)
 | |
| 		if (vendor !== undefined && product !== undefined && connection !== undefined) {
 | |
| 			/* set up the correct values on the download page */
 | |
| 			if (vendor !== -1)
 | |
| 				downloadFromDc.vendor = vendor
 | |
| 			if (product !== -1)
 | |
| 				downloadFromDc.product = product
 | |
| 			if (connection !== -1)
 | |
| 				downloadFromDc.connection = connection
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	property QtObject downloadFromDCAction: Kirigami.Action {
 | |
| 		icon {
 | |
| 			name: ":/icons/downloadDC"
 | |
| 			color: subsurfaceTheme.primaryColor
 | |
| 		}
 | |
| 		text: qsTr("Download dives")
 | |
| 		onTriggered: {
 | |
| 			showDownloadPage()
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	property QtObject addDiveAction: Kirigami.Action {
 | |
| 		icon {
 | |
| 			name: ":/icons/list-add"
 | |
| 		}
 | |
| 		text: qsTr("Add dive")
 | |
| 		onTriggered: {
 | |
| 			startAddDive()
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	property QtObject filterToggleAction: Kirigami.Action {
 | |
| 		icon {
 | |
| 			name: ":icons/ic_filter_list"
 | |
| 		}
 | |
| 		text: qsTr("Filter dives")
 | |
| 		onTriggered: {
 | |
| 			rootItem.filterToggle = !rootItem.filterToggle
 | |
| 			diveModel.resetFilter()
 | |
| 			numShownText = diveModel.shown()
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	onBackRequested: {
 | |
| 		if (startPage.visible && diveListView.count > 0 &&
 | |
| 			prefs.credentialStatus !== CloudStatus.CS_INCORRECT_USER_PASSWD) {
 | |
| 			prefs.credentialStatus = 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) {
 | |
| 		diveListView.currentIndex = idx
 | |
| 		// updating the index of the ListView triggers a non-linear scroll
 | |
| 		// animation that can be very slow. the fix is to stop this animation
 | |
| 		// by setting contentY to itself and then using positionViewAtIndex().
 | |
| 		// the downside is that the view jumps to the index immediately.
 | |
| 		if (noScroll) {
 | |
| 			diveListView.contentY = diveListView.contentY
 | |
| 			diveListView.positionViewAtIndex(idx, ListView.Center)
 | |
| 		}
 | |
| 	}
 | |
| }
 |