Move subsurface-core to core and qt-mobile to mobile-widgets

Having subsurface-core as a directory name really messes with
autocomplete and is obviously redundant. Simmilarly, qt-mobile caused an
autocomplete conflict and also was inconsistent with the desktop-widget
name for the directory containing the "other" UI.

And while cleaning up the resulting change in the path name for include
files, I decided to clean up those even more to make them consistent
overall.

This could have been handled in more commits, but since this requires a
make clean before the build, it seemed more sensible to do it all in one.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
Dirk Hohndel 2016-04-04 22:02:03 -07:00
parent 2d760a7bff
commit 7be962bfc2
254 changed files with 572 additions and 582 deletions

View file

@ -0,0 +1,59 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import org.kde.kirigami 1.0 as Kirigami
import org.subsurfacedivelog.mobile 1.0
Kirigami.ScrollablePage {
id: aboutPage
property int pageWidth: subsurfaceTheme.columnWidth - Kirigami.Units.smallSpacing
title: "About Subsurface-mobile"
ColumnLayout {
spacing: Kirigami.Units.largeSpacing
width: aboutPage.width
Layout.margins: Kirigami.Units.gridUnit / 2
Kirigami.Heading {
text: "About Subsurface-mobile"
Layout.topMargin: Kirigami.Units.gridUnit
Layout.alignment: Qt.AlignHCenter
Layout.maximumWidth: pageWidth
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
}
Image {
id: image
source: "qrc:/qml/subsurface-mobile-icon.png"
width: pageWidth / 2
height: width
fillMode: Image.Stretch
Layout.alignment: Qt.AlignCenter
horizontalAlignment: Image.AlignHCenter
}
Kirigami.Heading {
text: "A mobile version of the free Subsurface divelog software.\n" +
"View your dive logs while on the go."
level: 4
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: Kirigami.Units.largeSpacing * 3
Layout.maximumWidth: pageWidth
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
anchors.horizontalCenter: parent.Center
horizontalAlignment: Text.AlignHCenter
}
Kirigami.Heading {
text: "Version: " + manager.getVersion() + "\n\n© Subsurface developer team\n2011-2016"
level: 5
font.pointSize: subsurfaceTheme.smallPointSize + 1
Layout.alignment: Qt.AlignHCenter
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.maximumWidth: pageWidth
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
anchors.horizontalCenter: parent.Center
horizontalAlignment: Text.AlignHCenter
}
}
}

View file

@ -0,0 +1,84 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import org.kde.kirigami 1.0 as Kirigami
import org.subsurfacedivelog.mobile 1.0
Item {
id: loginWindow
height: outerLayout.height + 2 * Kirigami.Units.gridUnit
property string username: login.text;
property string password: password.text;
function saveCredentials() {
manager.cloudUserName = login.text
manager.cloudPassword = password.text
manager.saveCloudCredentials()
}
ColumnLayout {
id: outerLayout
width: subsurfaceTheme.columnWidth - 2 * Kirigami.Units.gridUnit
onVisibleChanged: {
if (visible && manager.accessingCloud < 0) {
manager.appendTextToLog("Credential scrn: show kbd was: " + (Qt.inputMethod.isVisible ? "visible" : "invisible"))
Qt.inputMethod.show()
login.forceActiveFocus()
} else {
manager.appendTextToLog("Credential scrn: hide kbd was: " + (Qt.inputMethod.isVisible ? "visible" : "invisible"))
Qt.inputMethod.hide()
}
}
Kirigami.Heading {
text: "Cloud credentials"
level: headingLevel
Layout.bottomMargin: Kirigami.Units.largeSpacing / 2
}
Kirigami.Label {
text: "Email"
}
TextField {
id: login
text: manager.cloudUserName
Layout.fillWidth: true
inputMethodHints: Qt.ImhEmailCharactersOnly |
Qt.ImhNoAutoUppercase
}
Kirigami.Label {
text: "Password"
}
TextField {
id: password
text: manager.cloudPassword
echoMode: TextInput.Password
inputMethodHints: Qt.ImhSensitiveData |
Qt.ImhHiddenText |
Qt.ImhNoAutoUppercase
Layout.fillWidth: true
}
GridLayout {
columns: 2
CheckBox {
checked: false
id: showPassword
onCheckedChanged: {
password.echoMode = checked ? TextInput.Normal : TextInput.Password
}
}
Kirigami.Label {
text: "Show password"
}
}
Item { width: Kirigami.Units.gridUnit; height: width }
}
}

View file

@ -0,0 +1,216 @@
import QtQuick 2.4
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.2
import org.subsurfacedivelog.mobile 1.0
import org.kde.kirigami 1.0 as Kirigami
Kirigami.Page {
id: diveDetailsPage
property alias currentIndex: diveDetailsListView.currentIndex
property alias dive_id: detailsEdit.dive_id
property alias number: detailsEdit.number
property alias date: detailsEdit.dateText
property alias airtemp: detailsEdit.airtempText
property alias watertemp: detailsEdit.watertempText
property alias buddy: detailsEdit.buddyText
property alias divemaster: detailsEdit.divemasterText
property alias depth: detailsEdit.depthText
property alias duration: detailsEdit.durationText
property alias location: detailsEdit.locationText
property alias notes: detailsEdit.notesText
property alias suit: detailsEdit.suitText
property alias weight: detailsEdit.weightText
property alias startpressure: detailsEdit.startpressureText
property alias endpressure: detailsEdit.endpressureText
property alias gasmix: detailsEdit.gasmixText
topPadding: applicationWindow().header.Layout.preferredHeight
leftPadding: 0
rightPadding: 0
bottomPadding: 0
title: diveDetailsListView.currentItem.modelData.dive.location
state: "view"
states: [
State {
name: "view"
PropertyChanges { target: diveDetailsPage; contextualActions: Qt.platform.os == "ios" ? [ deleteAction, backAction ] : [ deleteAction ] }
PropertyChanges { target: detailsEditScroll; opened: false }
},
State {
name: "edit"
PropertyChanges { target: diveDetailsPage; contextualActions: Qt.platform.os == "ios" ? [ cancelAction ] : null }
PropertyChanges { target: detailsEditScroll; opened: true }
},
State {
name: "add"
PropertyChanges { target: diveDetailsPage; contextualActions: Qt.platform.os == "ios" ? [ cancelAction ] : null }
PropertyChanges { target: detailsEditScroll; opened: true }
}
]
property QtObject deleteAction: Action {
text: "Delete dive"
iconName: "trash-empty"
onTriggered: {
contextDrawer.close()
var deletedId = diveDetailsListView.currentItem.modelData.dive.id
manager.deleteDive(deletedId)
stackView.pop()
showPassiveNotification("Dive deleted", 3000, "Undo",
function() {
manager.undoDelete(deletedId)
});
}
}
property QtObject cancelAction: Kirigami.Action {
text: state === "edit" ? "Cancel edit" : "Cancel dive add"
iconName: "dialog-cancel"
onTriggered: {
contextDrawer.close()
if (state === "add")
returnTopPage()
else
endEditMode()
}
}
property QtObject backAction: Action {
text: "Back to dive list"
iconName: "go-previous"
onTriggered: {
contextDrawer.close()
returnTopPage()
}
}
mainAction: Action {
iconName: state !== "view" ? "document-save" : "document-edit"
onTriggered: {
if (state === "edit" || state === "add") {
detailsEdit.saveData()
} else {
startEditMode()
}
}
}
onBackRequested: {
if (state === "edit") {
endEditMode()
event.accepted = true;
} else if (state === "add") {
endEditMode()
stackView.pop()
event.accepted = true;
}
// if we were in view mode, don't accept the event and pop the page
}
function showDiveIndex(index) {
currentIndex = index;
diveDetailsListView.positionViewAtIndex(index, ListView.Beginning);
}
function endEditMode() {
// if we were adding a dive, we need to remove it
if (state === "add")
manager.addDiveAborted(dive_id)
// just cancel the edit/add state
state = "view";
Qt.inputMethod.hide();
}
function startEditMode() {
// set things up for editing - so make sure that the detailsEdit has
// all the right data (using the property aliases set up above)
dive_id = diveDetailsListView.currentItem.modelData.dive.id
number = diveDetailsListView.currentItem.modelData.dive.number
date = diveDetailsListView.currentItem.modelData.dive.date + " " + diveDetailsListView.currentItem.modelData.dive.time
location = diveDetailsListView.currentItem.modelData.dive.location
duration = diveDetailsListView.currentItem.modelData.dive.duration
depth = diveDetailsListView.currentItem.modelData.dive.depth
airtemp = diveDetailsListView.currentItem.modelData.dive.airTemp
watertemp = diveDetailsListView.currentItem.modelData.dive.waterTemp
suit = diveDetailsListView.currentItem.modelData.dive.suit
buddy = diveDetailsListView.currentItem.modelData.dive.buddy
divemaster = diveDetailsListView.currentItem.modelData.dive.divemaster
notes = diveDetailsListView.currentItem.modelData.dive.notes
if (diveDetailsListView.currentItem.modelData.dive.singleWeight) {
// we have only one weight, go ahead, have fun and edit it
weight = diveDetailsListView.currentItem.modelData.dive.sumWeight
} else {
// careful when translating, this text is "magic" in DiveDetailsEdit.qml
weight = "cannot edit multiple weight systems"
}
if (diveDetailsListView.currentItem.modelData.dive.getCylinder != "Multiple" ) {
startpressure = diveDetailsListView.currentItem.modelData.dive.startPressure
endpressure = diveDetailsListView.currentItem.modelData.dive.endPressure
gasmix = diveDetailsListView.currentItem.modelData.dive.firstGas
} else {
// careful when translating, this text is "magic" in DiveDetailsEdit.qml
startpressure = "cannot edit multiple cylinders"
endpressure = "cannot edit multiple cylinders"
gasmix = "cannot edit multiple gases"
}
diveDetailsPage.state = "edit"
}
onWidthChanged: diveDetailsListView.positionViewAtIndex(diveDetailsListView.currentIndex, ListView.Beginning);
Item {
anchors.fill: parent
ScrollView {
id: diveDetailList
anchors.fill: parent
ListView {
id: diveDetailsListView
anchors.fill: parent
model: diveModel
currentIndex: -1
boundsBehavior: Flickable.StopAtBounds
maximumFlickVelocity: parent.width * 5
orientation: ListView.Horizontal
focus: true
clip: true
snapMode: ListView.SnapOneItem
onMovementEnded: {
currentIndex = indexAt(contentX+1, 1);
}
delegate: ScrollView {
id: internalScrollView
width: diveDetailsListView.width
height: diveDetailsListView.height
property var modelData: model
Flickable {
//contentWidth: parent.width
contentHeight: diveDetails.height
boundsBehavior: Flickable.StopAtBounds
DiveDetailsView {
id: diveDetails
width: internalScrollView.width
}
}
}
}
}
Kirigami.OverlaySheet {
id: detailsEditScroll
anchors.fill: parent
onOpenedChanged: {
if (!opened) {
endEditMode()
}
}
DiveDetailsEdit {
id: detailsEdit
}
}
}
}

View file

@ -0,0 +1,236 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import org.subsurfacedivelog.mobile 1.0
import org.kde.kirigami 1.0 as Kirigami
Item {
id: detailsEdit
property int dive_id
property int number
property alias dateText: txtDate.text
property alias locationText: txtLocation.text
property string gpsText
property alias airtempText: txtAirTemp.text
property alias watertempText: txtWaterTemp.text
property alias suitText: txtSuit.text
property alias buddyText: txtBuddy.text
property alias divemasterText: txtDiveMaster.text
property alias notesText: txtNotes.text
property alias durationText: txtDuration.text
property alias depthText: txtDepth.text
property alias weightText: txtWeight.text
property alias startpressureText: txtStartPressure.text
property alias endpressureText: txtEndPressure.text
property alias gasmixText: txtGasMix.text
function saveData() {
// apply the changes to the dive_table
manager.commitChanges(dive_id, detailsEdit.dateText, detailsEdit.locationText, detailsEdit.gpsText, detailsEdit.durationText,
detailsEdit.depthText, detailsEdit.airtempText, detailsEdit.watertempText, detailsEdit.suitText,
detailsEdit.buddyText, detailsEdit.divemasterText, detailsEdit.weightText, detailsEdit.notesText,
detailsEdit.startpressureText, detailsEdit.endpressureText, detailsEdit.gasmixText)
// trigger the profile to be redrawn
QMLProfile.diveId = dive_id
// apply the changes to the dive detail view - since the edit could have changed the order
// first make sure that we are looking at the correct dive - our model allows us to look
// up the index based on the unique dive_id
var newIdx = diveModel.getIdxForId(dive_id)
diveDetailsListView.currentIndex = newIdx
diveDetailsListView.currentItem.modelData.date = detailsEdit.dateText
diveDetailsListView.currentItem.modelData.location = detailsEdit.locationText
diveDetailsListView.currentItem.modelData.duration = detailsEdit.durationText
diveDetailsListView.currentItem.modelData.depth = detailsEdit.depthText
diveDetailsListView.currentItem.modelData.airtemp = detailsEdit.airtempText
diveDetailsListView.currentItem.modelData.watertemp = detailsEdit.watertempText
diveDetailsListView.currentItem.modelData.suit = detailsEdit.suitText
diveDetailsListView.currentItem.modelData.buddy = detailsEdit.buddyText
diveDetailsListView.currentItem.modelData.divemaster = detailsEdit.divemasterText
diveDetailsListView.currentItem.modelData.notes = detailsEdit.notesText
diveDetailsPage.state = "view"
Qt.inputMethod.hide()
// now make sure we directly show the saved dive (this may be a new dive, or it may have moved)
showDiveIndex(newIdx)
}
height: editArea.height
ColumnLayout {
id: editArea
spacing: Kirigami.Units.smallSpacing
width: subsurfaceTheme.columnWidth - 2 * Kirigami.Units.gridUnit
GridLayout {
id: editorDetails
width: parent.width
columns: 2
Kirigami.Heading {
Layout.columnSpan: 2
text: "Dive " + number
}
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "Date:"
}
TextField {
id: txtDate;
Layout.fillWidth: true
}
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "Location:"
}
TextField {
id: txtLocation;
Layout.fillWidth: true
}
// we should add a checkbox here that allows the user
// to add the current location as the dive location
// (think of someone adding a dive while on the boat or
// at the dive site)
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "Use current\nGPS location:"
}
CheckBox {
id: checkboxGPS
onCheckedChanged: {
if (checked)
gpsText = manager.getCurrentPosition()
}
}
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "Depth:"
}
TextField {
id: txtDepth
Layout.fillWidth: true
validator: RegExpValidator { regExp: /[^-]*/ }
}
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "Duration:"
}
TextField {
id: txtDuration
Layout.fillWidth: true
validator: RegExpValidator { regExp: /[^-]*/ }
}
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "Air Temp:"
}
TextField {
id: txtAirTemp
Layout.fillWidth: true
}
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "Water Temp:"
}
TextField {
id: txtWaterTemp
Layout.fillWidth: true
}
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "Suit:"
}
TextField {
id: txtSuit
Layout.fillWidth: true
}
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "Buddy:"
}
TextField {
id: txtBuddy
Layout.fillWidth: true
}
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "Dive Master:"
}
TextField {
id: txtDiveMaster
Layout.fillWidth: true
}
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "Weight:"
}
TextField {
id: txtWeight
readOnly: (text == "cannot edit multiple weight systems" ? true : false)
Layout.fillWidth: true
}
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "Gas mix:"
}
TextField {
id: txtGasMix
readOnly: (text == "cannot edit multiple gases" ? true : false)
Layout.fillWidth: true
validator: RegExpValidator { regExp: /(EAN100|EAN\d\d|AIR|100|\d{1,2}|\d{1,2}\/\d{1,2})/ }
}
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "Start Pressure:"
}
TextField {
id: txtStartPressure
readOnly: (text == "cannot edit multiple cylinders" ? true : false)
Layout.fillWidth: true
}
Kirigami.Label {
Layout.alignment: Qt.AlignRight
text: "End Pressure:"
}
TextField {
id: txtEndPressure
readOnly: (text == "cannot edit multiple cylinders" ? true : false)
Layout.fillWidth: true
}
Kirigami.Label {
Layout.columnSpan: 2
Layout.alignment: Qt.AlignLeft
text: "Notes:"
}
TextArea {
Layout.columnSpan: 2
width: parent.width
id: txtNotes
textFormat: TextEdit.RichText
focus: true
Layout.fillWidth: true
Layout.fillHeight: true
Layout.minimumHeight: Kirigami.Units.gridUnit * 6
selectByMouse: true
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
}
}
Item {
height: Kirigami.Units.gridUnit * 3
width: height // just to make sure the spacer doesn't produce scrollbars, but also isn't null
}
}
}

View file

@ -0,0 +1,303 @@
import QtQuick 2.3
/*
import QtWebView 1.0
*/
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import org.subsurfacedivelog.mobile 1.0
import org.kde.kirigami 1.0 as Kirigami
Item {
id: detailsView
property real gridWidth: subsurfaceTheme.columnWidth - 2 * Kirigami.Units.gridUnit
property real col1Width: gridWidth * 0.23
property real col2Width: gridWidth * 0.37
property real col3Width: gridWidth * 0.20
property real col4Width: gridWidth * 0.20
width: SubsurfaceTheme.columnWidth
height: mainLayout.implicitHeight + bottomLayout.implicitHeight + Kirigami.Units.iconSizes.large
Rectangle {
z: 99
color: Kirigami.Theme.textColor
opacity: 0.3
width: Kirigami.Units.smallSpacing/4
anchors {
right: parent.right
top: parent.top
bottom: parent.bottom
}
}
GridLayout {
id: mainLayout
anchors {
top: parent.top
left: parent.left
right: parent.right
margins: Math.round(Kirigami.Units.gridUnit / 2)
}
columns: 4
rowSpacing: Kirigami.Units.smallSpacing * 2
columnSpacing: Kirigami.Units.smallSpacing
Kirigami.Heading {
id: detailsViewHeading
Layout.fillWidth: true
text: dive.location
font.underline: dive.gps !== ""
Layout.columnSpan: 4
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
Layout.topMargin: Kirigami.Units.largeSpacing
MouseArea {
anchors.fill: parent
onClicked: {
if (dive.gps !== "")
showMap(dive.gps)
}
}
}
Kirigami.Label {
id: dateLabel
text: "Date: "
opacity: 0.6
Layout.alignment: Qt.AlignRight
}
Kirigami.Label {
text: dive.date + " " + dive.time
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
Layout.columnSpan: 2
}
Kirigami.Label {
id: numberText
text: "#" + dive.number
color: Kirigami.Theme.textColor
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
}
Kirigami.Label {
id: depthLabel
text: "Depth: "
opacity: 0.6
Layout.alignment: Qt.AlignRight
}
Kirigami.Label {
text: dive.depth
Layout.fillWidth: true
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
}
Kirigami.Label {
text: "Duration: "
opacity: 0.6
Layout.alignment: Qt.AlignRight
}
Kirigami.Label {
text: dive.duration
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
}
QMLProfile {
id: qmlProfile
visible: !dive.noDive
Layout.fillWidth: true
Layout.preferredHeight: Layout.minimumHeight
Layout.minimumHeight: width * 0.75
Layout.columnSpan: 4
clip: false
Rectangle {
color: "transparent"
opacity: 0.6
border.width: 1
border.color: Kirigami.Theme.textColor;
anchors.fill: parent
}
}
Kirigami.Label {
id: noProfile
visible: dive.noDive
Layout.fillWidth: true
Layout.columnSpan: 4
Layout.margins: Kirigami.Units.gridUnit
horizontalAlignment: Text.AlignHCenter
text: "No profile to show"
}
}
GridLayout {
id: bottomLayout
anchors {
top: mainLayout.bottom
left: parent.left
right: parent.right
margins: Math.round(Kirigami.Units.gridUnit / 2)
}
columns: 4
rowSpacing: Kirigami.Units.smallSpacing * 2
columnSpacing: Kirigami.Units.smallSpacing
Kirigami.Heading {
Layout.fillWidth: true
level: 3
text: "Dive Details"
Layout.columnSpan: 4
}
// first row - here we set up the column widths - total is 90% of width
Kirigami.Label {
text: "Suit:"
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
opacity: 0.6
Layout.maximumWidth: detailsView.col1Width
Layout.preferredWidth: detailsView.col1Width
Layout.alignment: Qt.AlignRight
}
Kirigami.Label {
id: txtSuit
text: dive.suit
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
Layout.maximumWidth: detailsView.col2Width
Layout.preferredWidth: detailsView.col2Width
}
Kirigami.Label {
text: "Air Temp:"
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
opacity: 0.6
Layout.maximumWidth: detailsView.col3Width
Layout.preferredWidth: detailsView.col3Width
Layout.alignment: Qt.AlignRight
}
Kirigami.Label {
id: txtAirTemp
text: dive.airTemp
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
Layout.maximumWidth: detailsView.col4Width
Layout.preferredWidth: detailsView.col4Width
}
Kirigami.Label {
text: "Cylinder:"
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
opacity: 0.6
Layout.maximumWidth: detailsView.col1Width
Layout.preferredWidth: detailsView.col1Width
Layout.alignment: Qt.AlignRight
}
Kirigami.Label {
id: txtCylinder
text: dive.getCylinder
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
Layout.maximumWidth: detailsView.col2Width
Layout.preferredWidth: detailsView.col2Width
}
Kirigami.Label {
text: "Water Temp:"
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
opacity: 0.6
Layout.maximumWidth: detailsView.col3Width
Layout.preferredWidth: detailsView.col3Width
Layout.alignment: Qt.AlignRight
}
Kirigami.Label {
id: txtWaterTemp
text: dive.waterTemp
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
Layout.maximumWidth: detailsView.col4Width
Layout.preferredWidth: detailsView.col4Width
}
Kirigami.Label {
text: "Dive Master:"
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
opacity: 0.6
Layout.maximumWidth: detailsView.col1Width
Layout.preferredWidth: detailsView.col1Width
Layout.alignment: Qt.AlignRight
}
Kirigami.Label {
id: txtDiveMaster
text: dive.divemaster
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
Layout.maximumWidth: detailsView.col2Width
Layout.preferredWidth: detailsView.col2Width
}
Kirigami.Label {
text: "Weight:"
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
opacity: 0.6
Layout.maximumWidth: detailsView.col3Width
Layout.preferredWidth: detailsView.col3Width
Layout.alignment: Qt.AlignRight
}
Kirigami.Label {
id: txtWeight
text: dive.sumWeight
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
Layout.maximumWidth: detailsView.col4Width
Layout.preferredWidth: detailsView.col4Width
}
Kirigami.Label {
text: "Buddy:"
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
opacity: 0.6
Layout.maximumWidth: detailsView.col1Width
Layout.preferredWidth: detailsView.col1Width
Layout.alignment: Qt.AlignRight
}
Kirigami.Label {
id: txtBuddy
text: dive.buddy
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
Layout.maximumWidth: detailsView.col2Width
Layout.preferredWidth: detailsView.col2Width
}
Kirigami.Label {
text: "SAC:"
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
opacity: 0.6
Layout.maximumWidth: detailsView.col3Width
Layout.preferredWidth: detailsView.col3Width
Layout.alignment: Qt.AlignRight
}
Kirigami.Label {
id: txtSAC
text: dive.sac
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
Layout.maximumWidth: detailsView.col4Width
Layout.preferredWidth: detailsView.col4Width
}
Kirigami.Heading {
Layout.fillWidth: true
level: 3
text: "Notes"
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
Layout.columnSpan: 4
}
Kirigami.Label {
id: txtNotes
text: dive.notes
focus: true
Layout.columnSpan: 4
Layout.fillWidth: true
Layout.fillHeight: true
//selectByMouse: true
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
}
Item {
Layout.columnSpan: 4
Layout.fillWidth: true
Layout.minimumHeight: Kirigami.Units.gridUnit * 3
}
Component.onCompleted: {
qmlProfile.setMargin(Kirigami.Units.smallSpacing)
qmlProfile.diveId = model.dive.id;
qmlProfile.update();
}
}
}

View file

@ -0,0 +1,302 @@
import QtQuick 2.4
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import org.kde.kirigami 1.0 as Kirigami
import org.subsurfacedivelog.mobile 1.0
Kirigami.ScrollablePage {
id: page
objectName: "DiveList"
title: "Subsurface-mobile"
background: Rectangle {
color: Kirigami.Theme.viewBackgroundColor
}
property int credentialStatus: manager.credentialStatus
property int numDives: diveListView.count
property color textColor: subsurfaceTheme.diveListTextColor
function scrollToTop() {
diveListView.positionViewAtBeginning()
}
Component {
id: diveDelegate
Kirigami.AbstractListItem {
enabled: true
supportsMouseEvents: true
checked: diveListView.currentIndex === model.index
width: parent.width
property real detailsOpacity : 0
property int horizontalPadding: Kirigami.Units.gridUnit / 2 - Kirigami.Units.smallSpacing + 1
// When clicked, the mode changes to details view
onClicked: {
if (detailsWindow.state === "view") {
diveListView.currentIndex = index
detailsWindow.showDiveIndex(index);
stackView.push(detailsWindow);
}
}
property bool deleteButtonVisible: false
onPressAndHold: {
deleteButtonVisible = true
timer.restart()
}
Row {
width: parent.width - Kirigami.Units.gridUnit
height: childrenRect.height - Kirigami.Units.smallSpacing
spacing: horizontalPadding
add: Transition {
NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 400 }
NumberAnimation { property: "scale"; from: 0; to: 1.0; duration: 400 }
}
Item {
id: diveListEntry
width: parent.width - Kirigami.Units.gridUnit
height: childrenRect.height - Kirigami.Units.smallSpacing
Kirigami.Label {
id: locationText
text: dive.location
font.weight: Font.Light
elide: Text.ElideRight
maximumLineCount: 1 // needed for elide to work at all
color: textColor
anchors {
left: parent.left
leftMargin: horizontalPadding
top: parent.top
right: dateLabel.left
}
}
Kirigami.Label {
id: dateLabel
text: dive.date + " " + dive.time
font.pointSize: subsurfaceTheme.smallPointSize
color: textColor
anchors {
right: parent.right
top: parent.top
}
}
Row {
anchors {
left: parent.left
leftMargin: horizontalPadding
right: parent.right
rightMargin: horizontalPadding
topMargin: - Kirigami.Units.smallSpacing * 2
bottom: numberText.bottom
}
Kirigami.Label {
text: 'Depth: '
font.pointSize: subsurfaceTheme.smallPointSize
color: textColor
}
Kirigami.Label {
text: dive.depth
width: Math.max(Kirigami.Units.gridUnit * 3, paintedWidth) // helps vertical alignment throughout listview
font.pointSize: subsurfaceTheme.smallPointSize
color: textColor
}
Kirigami.Label {
text: 'Duration: '
font.pointSize: subsurfaceTheme.smallPointSize
color: textColor
}
Kirigami.Label {
text: dive.duration
font.pointSize: subsurfaceTheme.smallPointSize
color: textColor
}
}
Kirigami.Label {
id: numberText
text: "#" + dive.number
font.pointSize: subsurfaceTheme.smallPointSize
color: textColor
anchors {
right: parent.right
top: locationText.bottom
topMargin: - Kirigami.Units.smallSpacing * 2
}
}
}
Rectangle {
visible: deleteButtonVisible
height: diveListEntry.height - Kirigami.Units.smallSpacing
width: height - 3 * Kirigami.Units.smallSpacing
color: "#FF3030"
antialiasing: true
radius: Kirigami.Units.smallSpacing
Kirigami.Icon {
anchors {
horizontalCenter: parent.horizontalCenter
verticalCenter: parent.verticalCenter
}
source: "trash-empty"
}
MouseArea {
anchors.fill: parent
enabled: parent.visible
onClicked: {
parent.visible = false
timer.stop()
manager.deleteDive(dive.id)
}
}
}
Item {
Timer {
id: timer
interval: 4000
onTriggered: {
deleteButtonVisible = false
}
}
}
}
}
}
Component {
id: tripHeading
Item {
width: page.width - Kirigami.Units.gridUnit
height: childrenRect.height + Kirigami.Units.smallSpacing * 2 + Math.max(2, Kirigami.Units.gridUnit / 2)
Kirigami.Heading {
id: sectionText
text: {
// if the tripMeta (which we get as "section") ends in ::-- we know
// that there's no trip -- otherwise strip the meta information before
// the :: and show the trip location
var shownText
var endsWithDoubleDash = /::--$/;
if (endsWithDoubleDash.test(section) || section === "--") {
shownText = ""
} else {
shownText = section.replace(/.*::/, "")
}
shownText
}
anchors {
top: parent.top
left: parent.left
topMargin: Math.max(2, Kirigami.Units.gridUnit / 2)
leftMargin: Kirigami.Units.gridUnit / 2
right: parent.right
}
color: textColor
level: 2
}
Rectangle {
height: Math.max(2, Kirigami.Units.gridUnit / 12) // we want a thicker line
anchors {
top: sectionText.bottom
left: parent.left
leftMargin: Kirigami.Units.gridUnit * -2
rightMargin: Kirigami.Units.gridUnit * -2
right: parent.right
}
color: subsurfaceTheme.accentColor
}
}
}
ScrollView {
id: startPageWrapper
anchors.fill: parent
opacity: (diveListView.count > 0 && (credentialStatus == QMLManager.VALID || credentialStatus == QMLManager.VALID_EMAIL)) ? 0 : 1
visible: opacity > 0
Behavior on opacity { NumberAnimation { duration: Kirigami.Units.shortDuration } }
onVisibleChanged: {
if (visible) {
page.mainAction = page.saveAction
} else {
page.mainAction = page.addDiveAction
}
}
StartPage {
id: startPage
}
}
ListView {
id: diveListView
anchors.fill: parent
opacity: 0.8 - startPageWrapper.opacity
visible: opacity > 0
model: diveModel
currentIndex: -1
delegate: diveDelegate
//boundsBehavior: Flickable.StopAtBounds
maximumFlickVelocity: parent.height * 5
bottomMargin: Kirigami.Units.iconSizes.medium + Kirigami.Units.gridUnit
cacheBuffer: 0 // seems to avoid empty rendered profiles
section.property: "dive.tripMeta"
section.criteria: ViewSection.FullString
section.delegate: tripHeading
header: Kirigami.Heading {
x: Kirigami.Units.gridUnit / 2
height: paintedHeight + Kirigami.Units.gridUnit / 2
verticalAlignment: Text.AlignBottom
text: "Dive Log"
}
Connections {
target: detailsWindow
onCurrentIndexChanged: diveListView.currentIndex = detailsWindow.currentIndex
}
Connections {
target: stackView
onDepthChanged: {
if (stackView.depth === 1) {
diveListView.currentIndex = -1;
}
}
}
Connections {
target: header
onTitleBarClicked: {
// if we can see the dive list and it's not at the top already, go to the top,
// otherwise have the title bar handle the click (for bread-crumb navigation)
if (stackView.currentItem.objectName === "DiveList" && diveListView.contentY > Kirigami.Units.gridUnit) {
diveListView.positionViewAtBeginning()
event.accepted = true
} else {
event.accepted = false
}
}
}
}
property QtObject addDiveAction: Action {
iconName: "list-add"
onTriggered: {
startAddDive()
}
}
property QtObject saveAction: Action {
iconName: "document-save"
onTriggered: {
startPage.saveCredentials();
}
}
onBackRequested: {
if (startPageWrapper.visible && diveListView.count > 0 && manager.credentialStatus != QMLManager.INVALID) {
manager.credentialStatus = oldStatus
event.accepted = true;
}
}
}

View file

@ -0,0 +1,125 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import org.subsurfacedivelog.mobile 1.0
import org.kde.kirigami 1.0 as Kirigami
Kirigami.Page {
id: diveComputerDownloadWindow
anchors.top:parent.top
width: parent.width
height: parent.height
Layout.fillWidth: true;
title: "Dive Computer"
/* this can be done by hitting the back key
contextualActions: [
Action {
text: "Close Preferences"
iconName: "dialog-cancel"
onTriggered: {
stackView.pop()
contextDrawer.close()
}
}
]
*/
ColumnLayout {
anchors.top: parent.top
height: parent.height
width: parent.width
Layout.fillWidth: true
RowLayout {
anchors.top:parent.top
Layout.fillWidth: true
Text { text: " Vendor name : " }
ComboBox { Layout.fillWidth: true }
}
RowLayout {
Text { text: " Dive Computer:" }
ComboBox { Layout.fillWidth: true }
}
RowLayout {
Text { text: " Progress:" }
Layout.fillWidth: true
ProgressBar { Layout.fillWidth: true }
}
RowLayout {
SubsurfaceButton {
text: "Download"
onClicked: {
text: "Retry"
stackView.pop();
}
}
SubsurfaceButton {
id:quitbutton
text: "Quit"
onClicked: {
stackView.pop();
}
}
}
RowLayout {
Text {
text: " Downloaded dives"
}
}
TableView {
width: parent.width
Layout.fillWidth: true // The tableview should fill
Layout.fillHeight: true // all remaining vertical space
height: parent.height // on this screen
TableViewColumn {
width: parent.width / 2
role: "datetime"
title: "Date / Time"
}
TableViewColumn {
width: parent.width / 4
role: "duration"
title: "Duration"
}
TableViewColumn {
width: parent.width / 4
role: "depth"
title: "Depth"
}
}
RowLayout {
Layout.fillWidth: true
SubsurfaceButton {
text: "Accept"
onClicked: {
stackView.pop();
}
}
SubsurfaceButton {
text: "Quit"
onClicked: {
stackView.pop();
}
}
Text {
text: "" // Spacer between 2 button groups
Layout.fillWidth: true
}
SubsurfaceButton {
text: "Select All"
}
SubsurfaceButton {
id: unselectbutton
text: "Unselect All"
}
}
RowLayout { // spacer to make space for silly button
Layout.minimumHeight: 1.2 * unselectbutton.height
Text {
text:""
}
}
}
}

View file

@ -0,0 +1,128 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import org.subsurfacedivelog.mobile 1.0
import org.kde.kirigami 1.0 as Kirigami
Kirigami.ScrollablePage {
id: gpsListWindow
width: parent.width - Kirigami.Units.gridUnit
anchors.margins: Kirigami.Units.gridUnit / 2
objectName: "gpsList"
title: "GPS Fixes"
/* this can be done by hitting the back key
contextualActions: [
Action {
text: "Close GPS list"
iconName: "dialog-cancel"
onTriggered: {
stackView.pop()
contextDrawer.close()
}
}
]
*/
Component {
id: gpsDelegate
Kirigami.SwipeListItem {
id: gpsFix
enabled: true
width: parent.width
property int horizontalPadding: Kirigami.Units.gridUnit / 2 - Kirigami.Units.smallSpacing + 1
Kirigami.BasicListItem {
supportsMouseEvents: true
width: parent.width - Kirigami.Units.gridUnit
height: childrenRect.height - Kirigami.Units.smallSpacing
GridLayout {
columns: 4
id: timeAndName
anchors {
left: parent.left
leftMargin: horizontalPadding
right: parent.right
rightMargin: horizontalPadding
}
Kirigami.Label {
text: 'Date: '
opacity: 0.6
font.pointSize: subsurfaceTheme.smallPointSize
}
Kirigami.Label {
text: date
Layout.preferredWidth: Math.max(parent.width / 5, paintedWidth)
font.pointSize: subsurfaceTheme.smallPointSize
}
Kirigami.Label {
text: 'Name: '
opacity: 0.6
font.pointSize: subsurfaceTheme.smallPointSize
}
Kirigami.Label {
text: name
Layout.preferredWidth: Math.max(parent.width / 5, paintedWidth)
font.pointSize: subsurfaceTheme.smallPointSize
}
Kirigami.Label {
text: 'Latitude: '
opacity: 0.6
font.pointSize: subsurfaceTheme.smallPointSize
}
Kirigami.Label {
text: latitude
font.pointSize: subsurfaceTheme.smallPointSize
}
Kirigami.Label {
text: 'Longitude: '
opacity: 0.6
font.pointSize: subsurfaceTheme.smallPointSize
}
Kirigami.Label {
text: longitude
font.pointSize: subsurfaceTheme.smallPointSize
}
}
}
actions: [
Kirigami.Action {
iconName: "trash-empty"
onTriggered: {
print("delete this!")
manager.deleteGpsFix(when)
}
},
Kirigami.Action {
iconName: "gps"
onTriggered: {
showMap(latitude + " " + longitude)
}
}
]
}
}
ListView {
id: gpsListView
anchors.fill: parent
model: gpsModel
currentIndex: -1
delegate: gpsDelegate
boundsBehavior: Flickable.StopAtBounds
maximumFlickVelocity: parent.height * 5
cacheBuffer: Math.max(5000, parent.height * 5)
focus: true
clip: true
header: Kirigami.Heading {
x: Kirigami.Units.gridUnit / 2
height: paintedHeight + Kirigami.Units.gridUnit / 2
verticalAlignment: Text.AlignBottom
text: "List of stored GPS fixes"
}
}
}

View file

@ -0,0 +1,40 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import org.subsurfacedivelog.mobile 1.0
import org.kde.kirigami 1.0 as Kirigami
Kirigami.ScrollablePage {
id: logWindow
width: parent.width - Kirigami.Units.gridUnit
anchors.margins: Kirigami.Units.gridUnit / 2
objectName: "Log"
title: "Application Log"
property int pageWidth: subsurfaceTheme.columnWidth - Kirigami.Units.smallSpacing
ColumnLayout {
width: pageWidth
spacing: Kirigami.Units.smallSpacing
Kirigami.Heading {
text: "Application Log"
}
Kirigami.Label {
id: logContent
width: parent.width
Layout.preferredWidth: parent.width
Layout.maximumWidth: parent.width
wrapMode: TextEdit.WrapAtWordBoundaryOrAnywhere
text: manager.logText
}
Rectangle {
color: "transparent"
height: Kirigami.Units.gridUnit * 2
width: pageWidth
}
}
}

View file

@ -0,0 +1,74 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import org.kde.kirigami 1.0 as Kirigami
import org.subsurfacedivelog.mobile 1.0
Kirigami.Page {
title: "Preferences"
mainAction: Action {
text: "Save"
iconName: "document-save"
onTriggered: {
manager.distanceThreshold = distanceThreshold.text
manager.timeThreshold = timeThreshold.text
manager.savePreferences()
stackView.pop()
}
}
GridLayout {
signal accept
columns: 2
width: parent.width - Kirigami.Units.gridUnit
anchors {
fill: parent
margins: Kirigami.Units.gridUnit / 2
}
Kirigami.Heading {
text: "Preferences"
Layout.bottomMargin: Kirigami.Units.largeSpacing / 2
Layout.columnSpan: 2
}
Kirigami.Heading {
text: "Subsurface GPS data webservice"
level: 3
Layout.topMargin: Kirigami.Units.largeSpacing
Layout.bottomMargin: Kirigami.Units.largeSpacing / 2
Layout.columnSpan: 2
}
Kirigami.Label {
text: "Distance threshold (meters)"
Layout.alignment: Qt.AlignRight
}
TextField {
id: distanceThreshold
text: manager.distanceThreshold
Layout.fillWidth: true
}
Kirigami.Label {
text: "Time threshold (minutes)"
Layout.alignment: Qt.AlignRight
}
TextField {
id: timeThreshold
text: manager.timeThreshold
Layout.fillWidth: true
}
Item {
Layout.fillHeight: true
}
}
}

View file

@ -0,0 +1,42 @@
import QtQuick 2.5
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Layouts 1.1
import org.kde.kirigami 1.0 as Kirigami
import org.subsurfacedivelog.mobile 1.0
ColumnLayout {
id: startpage
width: subsurfaceTheme.columnWidth
function saveCredentials() { cloudCredentials.saveCredentials() }
Kirigami.Heading {
Layout.margins: Kirigami.Units.gridUnit
text: "Subsurface-mobile"
}
Kirigami.Label {
id: explanationText
Layout.fillWidth: true
Layout.margins: Kirigami.Units.gridUnit
Layout.topMargin: 0
text: "In order to use Subsurface-mobile you need to have a Subsurface cloud storage account " +
"(which can be created with the Subsurface desktop application)."
wrapMode: Text.WordWrap
}
Kirigami.Label {
id: messageArea
Layout.fillWidth: true
Layout.margins: Kirigami.Units.gridUnit
Layout.topMargin: 0
text: manager.startPageText
wrapMode: Text.WordWrap
}
CloudCredentials {
id: cloudCredentials
Layout.fillWidth: true
Layout.margins: Kirigami.Units.gridUnit
Layout.topMargin: 0
property int headingLevel: 3
}
}

View file

@ -0,0 +1,26 @@
import QtQuick 2.5
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import org.kde.kirigami 1.0 as Kirigami
Button {
style: ButtonStyle {
padding {
top: Kirigami.Units.smallSpacing * 2
left: Kirigami.Units.smallSpacing * 4
right: Kirigami.Units.smallSpacing * 4
bottom: Kirigami.Units.smallSpacing * 2
}
background: Rectangle {
border.width: 1
radius: height / 3
color: control.pressed ? subsurfaceTheme.shadedColor : subsurfaceTheme.accentColor
}
label: Text{
text: control.text
color: subsurfaceTheme.accentTextColor
verticalAlignment: Text.AlignVCenter
horizontalAlignment: Text.AlignHCenter
}
}
}

View file

@ -0,0 +1,37 @@
import QtQuick 2.3
Rectangle {
id: container
property alias text: label.text
signal clicked
width: label.width + 20; height: label.height + 6
smooth: true
radius: 10
gradient: Gradient {
GradientStop { id: gradientStop; position: 0.0; color: palette.light }
GradientStop { position: 1.0; color: palette.button }
}
SystemPalette { id: palette }
MouseArea {
id: mouseArea
anchors.fill: parent
onClicked: { container.clicked() }
}
Text {
id: label
anchors.centerIn: parent
}
states: State {
name: "pressed"
when: mouseArea.pressed
PropertyChanges { target: gradientStop; color: palette.dark }
}
}

View file

@ -0,0 +1,115 @@
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import org.kde.kirigami 1.0 as Kirigami
Kirigami.Page {
title: "Theme Information"
/* this can be done by hitting the back key
contextualActions: [
Action {
text: "Close Theme info"
iconName: "dialog-cancel"
onTriggered: {
stackView.pop()
contextDrawer.close()
}
}
]
*/
GridLayout {
id: themetest
columns: 2
anchors.margins: Kirigami.Units.gridUnit / 2
Kirigami.Heading {
Layout.columnSpan: 2
text: "Theme Information"
}
Kirigami.Heading {
text: "Screen"
Layout.columnSpan: 2
level: 3
}
FontMetrics {
id: fm
}
Kirigami.Label {
text: "Geometry (pixels):"
}
Kirigami.Label {
text: rootItem.width + "x" + rootItem.height
}
Kirigami.Label {
text: "Geometry (gridUnits):"
}
Kirigami.Label {
text: Math.round(rootItem.width / Kirigami.Units.gridUnit) + "x" + Math.round(rootItem.height / Kirigami.Units.gridUnit)
}
Kirigami.Label {
text: "Units.gridUnit:"
}
Kirigami.Label {
text: Kirigami.Units.gridUnit
}
Kirigami.Label {
text: "Units.devicePixelRatio:"
}
Kirigami.Label {
text: Screen.devicePixelRatio
}
Kirigami.Heading {
text: "Font Metrics"
level: 3
Layout.columnSpan: 2
}
Kirigami.Label {
text: "FontMetrics pointSize:"
}
Kirigami.Label {
text: fm.font.pointSize
}
Kirigami.Label {
text: "FontMetrics pixelSize:"
}
Kirigami.Label {
text: fm.height
}
Kirigami.Label {
text: "FontMetrics devicePixelRatio:"
}
Kirigami.Label {
text: fm.height / fm.font.pointSize
}
Kirigami.Label {
text: "Text item pixelSize:"
}
Text {
text: font.pixelSize
}
Kirigami.Label {
text: "Text item pointSize:"
}
Text {
text: font.pointSize
}
Kirigami.Label {
Layout.columnSpan: 2
Layout.fillHeight: true
}
}
}

View file

@ -0,0 +1,59 @@
import QtQuick 2.3
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import org.kde.kirigami 1.0 as Kirigami
import org.subsurfacedivelog.mobile 1.0
Rectangle {
id: topPart
color: subsurfaceTheme.accentColor
Layout.minimumHeight: Math.round(Kirigami.Units.gridUnit * 1.5)
Layout.fillWidth: true
Layout.margins: 0
RowLayout {
anchors.verticalCenter: topPart.verticalCenter
Item {
Layout.preferredHeight: subsurfaceLogo.height
Layout.leftMargin: Kirigami.Units.gridUnit / 4
Image {
id: subsurfaceLogo
source: "qrc:/qml/subsurface-mobile-icon.png"
anchors {
verticalCenter: parent.Center
left: parent.left
}
width: Math.round(Kirigami.Units.gridUnit)
height: width
}
Kirigami.Label {
text: qsTr("Subsurface-mobile")
font.pointSize: Math.round(Kirigami.Theme.defaultFont.pointSize)
height: subsurfaceLogo.height
anchors {
left: subsurfaceLogo.right
leftMargin: Math.round(Kirigami.Units.gridUnit / 2)
}
font.weight: Font.Light
verticalAlignment: Text.AlignVCenter
Layout.fillWidth: false
color: subsurfaceTheme.accentTextColor
}
}
Item {
Layout.fillWidth: true
}
}
MouseArea {
anchors.fill: topPart
onClicked: {
if (stackView.depth == 1 && showingDiveList) {
scrollToTop()
}
}
}
}

BIN
mobile-widgets/qml/dive.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48"><path d="M24 16c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 4c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 12c-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4z"/></svg>

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 48 48"><path d="M6 36h36v-4H6v4zm0-10h36v-4H6v4zm0-14v4h36v-4H6z"/></svg>

After

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

360
mobile-widgets/qml/main.qml Normal file
View file

@ -0,0 +1,360 @@
import QtQuick 2.4
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.2
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.2
import org.subsurfacedivelog.mobile 1.0
import org.kde.kirigami 1.0 as Kirigami
Kirigami.ApplicationWindow {
id: rootItem
title: qsTr("Subsurface-mobile")
header.minimumHeight: 0
header.preferredHeight: Kirigami.Units.gridUnit
header.maximumHeight: Kirigami.Units.gridUnit * 2
property bool fullscreen: true
property int oldStatus: -1
property alias accessingCloud: manager.accessingCloud
property QtObject notification: null
property bool showingDiveList: false
property alias syncToCloud: manager.syncToCloud
onAccessingCloudChanged: {
if (accessingCloud >= 0) {
// we now keep updating this to show progress, so timing out after 30 seconds is more useful
// but should still be very conservative
showPassiveNotification("Accessing Subsurface Cloud Storage " + accessingCloud +"%", 30000);
} else {
hidePassiveNotification();
}
}
FontMetrics {
id: fontMetrics
}
visible: false
opacity: 0
function returnTopPage() {
for (var i=stackView.depth; i>1; i--) {
stackView.pop()
}
detailsWindow.endEditMode()
}
function scrollToTop() {
diveList.scrollToTop()
}
function showMap(location) {
var urlPrefix = "https://www.google.com/maps/place/"
var locationPair = location + "/@" + location
var urlSuffix = ",5000m/data=!3m1!1e3!4m2!3m1!1s0x0:0x0"
Qt.openUrlExternally(urlPrefix + locationPair + urlSuffix)
}
function startAddDive() {
detailsWindow.state = "add"
detailsWindow.dive_id = manager.addDive();
detailsWindow.number = manager.getNumber(detailsWindow.dive_id)
detailsWindow.date = manager.getDate(detailsWindow.dive_id)
detailsWindow.airtemp = ""
detailsWindow.watertemp = ""
detailsWindow.buddy = ""
detailsWindow.depth = ""
detailsWindow.divemaster = ""
detailsWindow.notes = ""
detailsWindow.location = ""
detailsWindow.duration = ""
detailsWindow.suit = ""
detailsWindow.weight = ""
detailsWindow.gasmix = ""
detailsWindow.startpressure = ""
detailsWindow.endpressure = ""
stackView.push(detailsWindow)
}
globalDrawer: Kirigami.GlobalDrawer {
title: "Subsurface"
titleIcon: "qrc:/qml/subsurface-mobile-icon.png"
bannerImageSource: "dive.jpg"
actions: [
Kirigami.Action {
text: "Dive list"
onTriggered: {
manager.appendTextToLog("requested dive list with credential status " + manager.credentialStatus)
if (manager.credentialStatus == QMLManager.UNKNOWN) {
// the user has asked to change credentials - if the credentials before that
// were valid, go back to dive list
if (oldStatus == QMLManager.VALID || oldStatus == QMLManager.VALID_EMAIL) {
manager.credentialStatus = oldStatus
}
}
returnTopPage()
globalDrawer.close()
}
},
Kirigami.Action {
text: "Cloud credentials"
onTriggered: {
returnTopPage()
oldStatus = manager.credentialStatus
if (diveList.numDives > 0) {
manager.startPageText = "Enter different credentials or return to dive list"
} else {
manager.startPageText = "Enter valid cloud storage credentials"
}
manager.credentialStatus = QMLManager.UNKNOWN
}
},
Kirigami.Action {
text: "Manage dives"
enabled: manager.credentialStatus === QMLManager.VALID || manager.credentialStatus === QMLManager.VALID_EMAIL
/*
* disable for the beta to avoid confusion
Action {
text: "Download from computer"
onTriggered: {
detailsWindow.endEditMode()
stackView.push(downloadDivesWindow)
}
}
*/
Kirigami.Action {
text: "Add dive manually"
onTriggered: {
returnTopPage() // otherwise odd things happen with the page stack
startAddDive()
}
}
Kirigami.Action {
text: "Manual sync with cloud"
onTriggered: {
globalDrawer.close()
detailsWindow.endEditMode()
manager.saveChanges();
}
}
Kirigami.Action {
text: syncToCloud ? "Disable auto cloud sync" : "Enable auto cloud sync"
onTriggered: {
syncToCloud = !syncToCloud
if (!syncToCloud) {
var alertText = "Turning off automatic sync to cloud causes all data to only be stored locally.\n"
alertText += "This can be very useful in situations with limited or no network access.\n"
alertText += "Please chose 'Manual sync with cloud' if you have network connectivity\n"
alertText += "and want to sync your data to cloud storage."
showPassiveNotification(alertText, 10000)
}
}
}
},
Kirigami.Action {
text: "GPS"
enabled: manager.credentialStatus === QMLManager.VALID || manager.credentialStatus === QMLManager.VALID_EMAIL
Kirigami.Action {
text: "GPS-tag dives"
onTriggered: {
manager.applyGpsData();
}
}
Kirigami.Action {
text: "Upload GPS data"
onTriggered: {
manager.sendGpsData();
}
}
Kirigami.Action {
text: "Download GPS data"
onTriggered: {
manager.downloadGpsData();
}
}
Kirigami.Action {
text: "Show GPS fixes"
onTriggered: {
returnTopPage()
manager.populateGpsData();
stackView.push(gpsWindow)
}
}
Kirigami.Action {
text: "Clear GPS cache"
onTriggered: {
manager.clearGpsData();
}
}
Kirigami.Action {
text: "Preferences"
onTriggered: {
stackView.push(prefsWindow)
detailsWindow.endEditMode()
}
}
},
Kirigami.Action {
text: "Developer"
Kirigami.Action {
text: "App log"
onTriggered: {
stackView.push(logWindow)
}
}
Kirigami.Action {
text: "Theme information"
onTriggered: {
stackView.push(themetest)
}
}
},
Kirigami.Action {
text: "User manual"
onTriggered: {
Qt.openUrlExternally("https://subsurface-divelog.org/documentation/subsurface-mobile-user-manual/")
}
},
Kirigami.Action {
text: "About"
onTriggered: {
stackView.push(aboutWindow)
detailsWindow.endEditMode()
}
}
] // end actions
MouseArea {
height: childrenRect.height
width: Kirigami.Units.gridUnit * 10
CheckBox {
//text: "Run location service"
id: locationCheckbox
anchors {
left: parent.left
top: parent.top
}
checked: manager.locationServiceEnabled
onCheckedChanged: {
manager.locationServiceEnabled = checked;
}
}
Kirigami.Label {
x: Kirigami.Units.gridUnit * 1.5
anchors {
left: locationCheckbox.right
//leftMargin: units.smallSpacing
verticalCenter: locationCheckbox.verticalCenter
}
text: "Run location service"
}
onClicked: {
print("Click.")
locationCheckbox.checked = !locationCheckbox.checked
}
}
}
contextDrawer: Kirigami.ContextDrawer {
id: contextDrawer
actions: rootItem.pageStack.currentPage ? rootItem.pageStack.currentPage.contextualActions : null
title: "Actions"
}
QtObject {
id: subsurfaceTheme
property int titlePointSize: Math.round(fontMetrics.font.pointSize * 1.5)
property int smallPointSize: Math.round(fontMetrics.font.pointSize * 0.8)
property color accentColor: "#2d5b9a"
property color shadedColor: "#132744"
property color accentTextColor: "#ececec"
property color diveListTextColor: "#000000" // the Kirigami theme text color is too light
property int columnWidth: Math.round(rootItem.width/(Kirigami.Units.gridUnit*30)) > 0 ? Math.round(rootItem.width / Math.round(rootItem.width/(Kirigami.Units.gridUnit*30))) : rootItem.width
}
/*
toolBar: TopBar {
width: parent.width
height: Layout.minimumHeight
}
*/
property Item stackView: pageStack
pageStack.initialPage: DiveList {
anchors.fill: detailsPage
id: diveList
opacity: 0
Behavior on opacity {
NumberAnimation {
duration: 200
easing.type: Easing.OutQuad
}
}
}
QMLManager {
id: manager
}
Preferences {
id: prefsWindow
visible: false
}
About {
id: aboutWindow
visible: false
}
DiveDetails {
id: detailsWindow
visible: false
width: parent.width
height: parent.height
}
DownloadFromDiveComputer {
id: downloadDivesWindow
visible: false
}
Log {
id: logWindow
visible: false
}
GpsList {
id: gpsWindow
visible: false
}
ThemeTest {
id: themetest
visible: false
}
Component.onCompleted: {
Kirigami.Theme.highlightColor = subsurfaceTheme.accentColor
manager.finishSetup();
rootItem.visible = true
diveList.opacity = 1
rootItem.opacity = 1
}
Behavior on opacity {
NumberAnimation {
duration: 200
easing.type: Easing.OutQuad
}
}
}

View file

@ -0,0 +1,66 @@
<RCC>
<qresource prefix="/qml">
<file>main.qml</file>
<file>TextButton.qml</file>
<file>Preferences.qml</file>
<file>About.qml</file>
<file>CloudCredentials.qml</file>
<file>DiveList.qml</file>
<file>DiveDetails.qml</file>
<file>DiveDetailsEdit.qml</file>
<file>DiveDetailsView.qml</file>
<file>DownloadFromDiveComputer.qml</file>
<file>GpsList.qml</file>
<file>Log.qml</file>
<file>TopBar.qml</file>
<file>ThemeTest.qml</file>
<file>StartPage.qml</file>
<file>dive.jpg</file>
<file>SubsurfaceButton.qml</file>
<file alias="subsurface-mobile-icon.png">../../icons/subsurface-mobile-icon.png</file>
<file alias="main-menu.png">icons/main-menu.png</file>
<file alias="context-menu.png">icons/context-menu.png</file>
<file alias="menu-edit.png">icons/menu-edit.png</file>
<file alias="menu-back.png">icons/menu-back.png</file>
</qresource>
<qresource prefix="/imports">
<file alias="org/kde/kirigami/qmldir">kirigami/qmldir</file>
<file alias="org/kde/kirigami/Action.qml">kirigami/Action.qml</file>
<file alias="org/kde/kirigami/ApplicationWindow.qml">kirigami/ApplicationWindow.qml</file>
<file alias="org/kde/kirigami/BasicListItem.qml">kirigami/BasicListItem.qml</file>
<file alias="org/kde/kirigami/GlobalDrawer.qml">kirigami/GlobalDrawer.qml</file>
<file alias="org/kde/kirigami/ContextDrawer.qml">kirigami/ContextDrawer.qml</file>
<file alias="org/kde/kirigami/Page.qml">kirigami/Page.qml</file>
<file alias="org/kde/kirigami/ScrollablePage.qml">kirigami/ScrollablePage.qml</file>
<file alias="org/kde/kirigami/Icon.qml">kirigami/Icon.qml</file>
<file alias="org/kde/kirigami/Heading.qml">kirigami/Heading.qml</file>
<file alias="org/kde/kirigami/OverlaySheet.qml">kirigami/OverlaySheet.qml</file>
<file alias="org/kde/kirigami/ApplicationHeader.qml">kirigami/ApplicationHeader.qml</file>
<file alias="org/kde/kirigami/private/PageRow.qml">kirigami/private/PageRow.qml</file>
<file alias="org/kde/kirigami/Label.qml">kirigami/Label.qml</file>
<file alias="org/kde/kirigami/AbstractListItem.qml">kirigami/AbstractListItem.qml</file>
<file alias="org/kde/kirigami/SwipeListItem.qml">kirigami/SwipeListItem.qml</file>
<file alias="org/kde/kirigami/OverlayDrawer.qml">kirigami/OverlayDrawer.qml</file>
<file alias="org/kde/kirigami/Theme.qml">kirigami/Theme.qml</file>
<file alias="org/kde/kirigami/Units.qml">kirigami/Units.qml</file>
<file alias="org/kde/kirigami/private/RefreshableScrollView.qml">kirigami/private/RefreshableScrollView.qml</file>
<file alias="org/kde/kirigami/private/ActionButton.qml">kirigami/private/ActionButton.qml</file>
<file alias="org/kde/kirigami/private/BackButton.qml">kirigami/private/BackButton.qml</file>
<file alias="org/kde/kirigami/private/MenuIcon.qml">kirigami/private/MenuIcon.qml</file>
<file alias="org/kde/kirigami/private/ContextIcon.qml">kirigami/private/ContextIcon.qml</file>
<file alias="org/kde/kirigami/private/AbstractDrawer.qml">kirigami/private/AbstractDrawer.qml</file>
<file alias="org/kde/kirigami/private/PageStack.js">kirigami/private/PageStack.js</file>
<file alias="org/kde/kirigami/private/PassiveNotification.qml">kirigami/private/PassiveNotification.qml</file>
<file alias="org/kde/kirigami/icons/go-next.svg">kirigami/icons/go-next.svg</file>
<file alias="org/kde/kirigami/icons/go-previous.svg">kirigami/icons/go-previous.svg</file>
<file alias="org/kde/kirigami/icons/distribute-horizontal-x.svg">kirigami/icons/distribute-horizontal-x.svg</file>
<file alias="org/kde/kirigami/icons/document-edit.svg">kirigami/icons/document-edit.svg</file>
<file alias="org/kde/kirigami/icons/document-save.svg">kirigami/icons/document-save.svg</file>
<file alias="org/kde/kirigami/icons/view-readermode.svg">kirigami/icons/view-readermode.svg</file>
<file alias="org/kde/kirigami/icons/dialog-cancel.svg">kirigami/icons/dialog-cancel.svg</file>
<file alias="org/kde/kirigami/icons/application-menu.svg">kirigami/icons/application-menu.svg</file>
<file alias="org/kde/kirigami/icons/gps.svg">kirigami/icons/gps.svg</file>
<file alias="org/kde/kirigami/icons/trash-empty.svg">kirigami/icons/trash-empty.svg</file>
<file alias="org/kde/kirigami/icons/list-add.svg">kirigami/icons/list-add.svg</file>
</qresource>
</RCC>

View file

@ -0,0 +1,57 @@
/*
* Copyright 2015 Marco Martin <mart@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.0
//pragma Singleton
/*!
\qmltype Theme
\inqmlmodule Material 0.1
\brief Provides access to standard colors that follow the Material Design specification.
See \l {http://www.google.com/design/spec/style/color.html#color-ui-color-application} for
details about choosing a color scheme for your application.
*/
QtObject {
id: theme
property color textColor: Qt.rgba(0,0,0, 0.54)
property color highlightColor: "#2196F3"
property color backgroundColor: "#f3f3f3"
property color linkColor: "#2196F3"
property color visitedLinkColor: "#2196F3"
property color buttonTextColor: Qt.rgba(0,0,0, 0.54)
property color buttonBackgroundColor: "#f3f3f3"
property color buttonHoverColor: "#2196F3"
property color buttonFocusColor: "#2196F3"
property color viewTextColor: Qt.rgba(0,0,0, 0.54)
property color viewBackgroundColor: "#f3f3f3"
property color viewHoverColor: "#2196F3"
property color viewFocusColor: "#2196F3"
property color complementaryTextColor: "#f3f3f3"
property color complementaryBackgroundColor: Qt.rgba(0,0,0, 0.54)
property color complementaryHoverColor: "#2196F3"
property color complementaryFocusColor: "#2196F3"
}

View file

@ -0,0 +1,99 @@
/*
* Copyright 2015 Marco Martin <mart@kde.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Library General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import QtQuick 2.5
import QtQuick.Window 2.2
//pragma Singleton
QtObject {
id: units
/**
* The fundamental unit of space that should be used for sizes, expressed in pixels.
* Given the screen has an accurate DPI settings, it corresponds to a width of
* the capital letter M
*/
property int gridUnit: fontMetrics.height
/**
* units.iconSizes provides access to platform-dependent icon sizing
*
* The icon sizes provided are normalized for different DPI, so icons
* will scale depending on the DPI.
*
* Icon sizes from KIconLoader, adjusted to devicePixelRatio:
* * small
* * smallMedium
* * medium
* * large
* * huge
* * enormous
*
* Not devicePixelRation-adjusted::
* * desktop
*/
property QtObject iconSizes: QtObject {
property int small: 16 * devicePixelRatio
property int smallMedium: 22 * devicePixelRatio
property int medium: 32 * devicePixelRatio
property int large: 48 * devicePixelRatio
property int huge: 64 * devicePixelRatio
property int enormous: 128 * devicePixelRatio
}
/**
* units.smallSpacing is the amount of spacing that should be used around smaller UI elements,
* for example as spacing in Columns. Internally, this size depends on the size of
* the default font as rendered on the screen, so it takes user-configured font size and DPI
* into account.
*/
property int smallSpacing: gridUnit/4
/**
* units.largeSpacing is the amount of spacing that should be used inside bigger UI elements,
* for example between an icon and the corresponding text. Internally, this size depends on
* the size of the default font as rendered on the screen, so it takes user-configured font
* size and DPI into account.
*/
property int largeSpacing: gridUnit
/**
* The ratio between physical and device-independent pixels. This value does not depend on the \
* size of the configured font. If you want to take font sizes into account when scaling elements,
* use theme.mSize(theme.defaultFont), units.smallSpacing and units.largeSpacing.
* The devicePixelRatio follows the definition of "device independent pixel" by Microsoft.
*/
property real devicePixelRatio: Screen.devicePixelRatio
/**
* units.longDuration should be used for longer, screen-covering animations, for opening and
* closing of dialogs and other "not too small" animations
*/
property int longDuration: 250
/**
* units.shortDuration should be used for short animations, such as accentuating a UI event,
* hover events, etc..
*/
property int shortDuration: 150
property QtObject fontMetrics: FontMetrics {}
}

View file

@ -0,0 +1,2 @@
#singleton Units Units.qml
#//singleton Theme Theme.qml