On Sun, Jun 14, 2015 at 11:55 PM, Tomaz Canabrava <[email protected]> wrote:
> Grace, always do a rebase from master so your work is not hard to merge > later. > I'm doing the review right now. > > > Here are patches containing the work done so far. To compile the mobile executable, call cmake with -DSUBSURFACE_MOBILE=True. This will result in a subsurface-mobile executable. -- -- Grace K
From faf064b4b7e8b7b931e84ff2f3995a5169e1ac61 Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Thu, 18 Jun 2015 09:13:30 +0300 Subject: [PATCH 21/22] Display more details Show more dive info in the extended view of the dive. Signed-off-by: Grace Karanja <[email protected]> --- qt-mobile/main.qml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/qt-mobile/main.qml b/qt-mobile/main.qml index e257477..8af0a9e 100644 --- a/qt-mobile/main.qml +++ b/qt-mobile/main.qml @@ -107,7 +107,13 @@ ApplicationWindow { contentHeight: detailsView.height clip: true Row { - Text { text: '<b>Notes:</b><br/>' + notes; wrapMode: Text.WordWrap; width: details.width } + Text { text: + '<b>Location: </b>' + location + + '<br><b>Air temp: </b>' + airtemp + ' <b> Water temp: </b>' + watertemp + + '<br><b>Suit: </b>' + suit + + '<br><b>Buddy: </b>' + buddy + + '<br><b>Dive Master: </b>' + divemaster + + '<br/><b>Notes:</b><br/>' + notes; wrapMode: Text.WordWrap; width: details.width } } } } -- 2.4.4
From 49d59bdf3d4f61fc45f9dcb994d18715705c08f6 Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Thu, 18 Jun 2015 09:12:52 +0300 Subject: [PATCH 20/22] Add more dive details to the DiveListModel Add some more details to the model. Signed-off-by: Grace Karanja <[email protected]> --- qt-models/divelistmodel.cpp | 80 +++++++++++++++++++++++++++++++++++++-------- qt-models/divelistmodel.h | 27 ++++++++++++--- 2 files changed, 88 insertions(+), 19 deletions(-) diff --git a/qt-models/divelistmodel.cpp b/qt-models/divelistmodel.cpp index ad36096..add5af5 100644 --- a/qt-models/divelistmodel.cpp +++ b/qt-models/divelistmodel.cpp @@ -17,13 +17,7 @@ Dive::Dive(dive *d) setDepth(get_depth_string(d->maxdepth)); setDuration(get_dive_duration_string(d->duration.seconds, "h:","min")); - if (!d->watertemp.mkelvin) - m_depth = ""; - - if (get_units()->temperature == units::CELSIUS) - m_depth = QString::number(mkelvin_to_C(d->watertemp.mkelvin), 'f', 1); - else - m_depth = QString::number(mkelvin_to_F(d->watertemp.mkelvin), 'f', 1); + setupDiveTempDetails(); weight_t tw = { total_weight(d) }; setWeight(weight_string(tw.grams)); @@ -33,6 +27,8 @@ Dive::Dive(dive *d) setSac(QString::number(d->sac)); setLocation(get_dive_location(d)); setNotes(d->notes); + setBuddy(d->buddy); + setDivemaster(d->divemaster); } QString Dive::date() const @@ -98,14 +94,14 @@ void Dive::setWeight(const QString &weight) { m_weight = weight; } -QString Dive::temp() const +QString Dive::airtemp() const { - return m_temp; + return m_airtemp; } -void Dive::setTemp(const QString &temp) +void Dive::setAirTemp(const QString &airtemp) { - m_temp = temp; + m_airtemp = airtemp; } QString Dive::duration() const { @@ -170,6 +166,53 @@ void Dive::setTrip(const QString &trip) { m_trip = trip; } +QString Dive::buddy() const +{ + return m_buddy; +} + +void Dive::setBuddy(const QString &buddy) +{ + m_buddy = buddy; +} +QString Dive::divemaster() const +{ + return m_divemaster; +} + +void Dive::setDivemaster(const QString &divemaster) +{ + m_divemaster = divemaster; +} +QString Dive::watertemp() const +{ + return m_watertemp; +} + +void Dive::setWatertemp(const QString &watertemp) +{ + m_watertemp = watertemp; +} + +void Dive::setupDiveTempDetails() +{ + const char *unit; + double d_airTemp, d_waterTemp; + + d_airTemp = get_temp_units(m_thisDive->airtemp.mkelvin, &unit); + d_waterTemp = get_temp_units(m_thisDive->watertemp.mkelvin, &unit); + + setAirTemp(QString::number(d_airTemp) + unit); + setWatertemp(QString::number(d_waterTemp) + unit); + + if (!m_thisDive->airtemp.mkelvin) + setAirTemp(""); + + if (!m_thisDive->watertemp.mkelvin) + setWatertemp(""); +} + + @@ -212,8 +255,10 @@ QVariant DiveListModel::data(const QModelIndex &index, int role) const return dive.depth(); else if (role == DiveDurationRole) return dive.duration(); - else if (role == DiveTemperatureRole) - return dive.temp(); + else if (role == DiveAirTemperatureRole) + return dive.airtemp(); + else if (role == DiveWaterTemperatureRole) + return dive.watertemp(); else if (role == DiveWeightRole) return dive.weight(); else if (role == DiveSuitRole) @@ -228,6 +273,10 @@ QVariant DiveListModel::data(const QModelIndex &index, int role) const return dive.location(); else if (role == DiveNotesRole) return dive.notes(); + else if (role == DiveBuddyRole) + return dive.buddy(); + else if (role == DiveMasterRole) + return dive.divemaster(); return QVariant(); @@ -242,7 +291,8 @@ QHash<int, QByteArray> DiveListModel::roleNames() const roles[DiveRatingRole] = "rating"; roles[DiveDepthRole] = "depth"; roles[DiveDurationRole] = "duration"; - roles[DiveTemperatureRole] = "temp"; + roles[DiveAirTemperatureRole] = "airtemp"; + roles[DiveWaterTemperatureRole] = "watertemp"; roles[DiveWeightRole] = "weight"; roles[DiveSuitRole] = "suit"; roles[DiveCylinderRole] = "cylinder"; @@ -250,6 +300,8 @@ QHash<int, QByteArray> DiveListModel::roleNames() const roles[DiveSacRole] = "sac"; roles[DiveLocationRole] = "location"; roles[DiveNotesRole] = "notes"; + roles[DiveBuddyRole] = "buddy"; + roles[DiveMasterRole] = "divemaster"; return roles; } diff --git a/qt-models/divelistmodel.h b/qt-models/divelistmodel.h index f580405..cb19188 100644 --- a/qt-models/divelistmodel.h +++ b/qt-models/divelistmodel.h @@ -29,8 +29,8 @@ public: QString weight() const; void setWeight(const QString &weight); - QString temp() const; - void setTemp(const QString &temp); + QString airtemp() const; + void setAirTemp(const QString &airtemp); QString duration() const; void setDuration(const QString &duration); @@ -53,14 +53,26 @@ public: QString trip() const; void setTrip(const QString &trip); + QString buddy() const; + void setBuddy(const QString &buddy); + + QString divemaster() const; + void setDivemaster(const QString &divemaster); + + QString watertemp() const; + void setWatertemp(const QString &watertemp); + private: + void setupDiveTempDetails(); + QString m_diveNumber; QString m_trip; QString m_date; QString m_rating; QString m_depth; QString m_duration; - QString m_temp; + QString m_airtemp; + QString m_watertemp; QString m_weight; QString m_suit; QString m_cylinder; @@ -68,6 +80,8 @@ private: QString m_sac; QString m_location; QString m_notes; + QString m_buddy; + QString m_divemaster; dive *m_thisDive; @@ -85,14 +99,17 @@ public: DiveRatingRole, DiveDepthRole, DiveDurationRole, - DiveTemperatureRole, + DiveWaterTemperatureRole, + DiveAirTemperatureRole, DiveWeightRole, DiveSuitRole, DiveCylinderRole, DiveGasRole, DiveSacRole, DiveLocationRole, - DiveNotesRole + DiveNotesRole, + DiveBuddyRole, + DiveMasterRole }; static DiveListModel *instance(); -- 2.4.4
From c8194ed8391946cf831da8c2052f9211c1855c07 Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Thu, 11 Jun 2015 09:56:18 +0300 Subject: [PATCH 19/22] Fix bug where dives are shown twice On the QML page, dives are repeated. Adding process_dives to QMLManager after calling parse_file solves this. Signed-off-by: Grace Karanja <[email protected]> --- qt-mobile/main.qml | 2 +- qt-mobile/qmlmanager.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/qt-mobile/main.qml b/qt-mobile/main.qml index bae117e..e257477 100644 --- a/qt-mobile/main.qml +++ b/qt-mobile/main.qml @@ -107,7 +107,7 @@ ApplicationWindow { contentHeight: detailsView.height clip: true Row { - Text { text: 'Notes: ' + notes; wrapMode: Text.WordWrap; width: details.width } + Text { text: '<b>Notes:</b><br/>' + notes; wrapMode: Text.WordWrap; width: details.width } } } } diff --git a/qt-mobile/qmlmanager.cpp b/qt-mobile/qmlmanager.cpp index 0f8ccbe..eeeada3 100644 --- a/qt-mobile/qmlmanager.cpp +++ b/qt-mobile/qmlmanager.cpp @@ -1,7 +1,8 @@ #include "qmlmanager.h" #include <QUrl> -#include "../qt-models/divelistmodel.h" +#include "qt-models/divelistmodel.h" +#include "divelist.h" QMLManager::QMLManager() { @@ -21,7 +22,6 @@ void QMLManager::setFilename(const QString &f) { m_fileName = f; loadFile(); - emit filenameChanged(); } void QMLManager::loadFile() @@ -30,7 +30,7 @@ void QMLManager::loadFile() QString strippedFileName = url.toLocalFile(); parse_file(strippedFileName.toUtf8().data()); - + process_dives(false, false); int i; struct dive *d; -- 2.4.4
From 950253526191e3617066c55e5ca60e6b55cf8667 Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Thu, 11 Jun 2015 09:39:32 +0300 Subject: [PATCH 18/22] Group dives by trips Group dives according to the allocated dive trips. Signed-off-by: Grace Karanja <[email protected]> --- qt-mobile/main.qml | 45 +++++++++++++++++++++++++-------------------- qt-models/divelistmodel.cpp | 21 +++++++++++++++++++++ qt-models/divelistmodel.h | 5 +++++ 3 files changed, 51 insertions(+), 20 deletions(-) diff --git a/qt-mobile/main.qml b/qt-mobile/main.qml index 20ea0c1..bae117e 100644 --- a/qt-mobile/main.qml +++ b/qt-mobile/main.qml @@ -72,21 +72,18 @@ ApplicationWindow { //And other details at the bottom. Row { id: topLayout - x: 10; y: 10; height: 50; width: parent.width + x: 10; y: 10; height: 60; width: parent.width spacing: 10 Column { - width: background.width; height: 50 + width: background.width; height: 60 spacing: 5 Text { text: diveNumber + ' (' + date + ')' - font.bold: true; font.pointSize: 16 - } - - Text { - text: location } + Text { text: location; width: details.width } + Text { text: '<b>Depth:</b> ' + depth + ' <b>Duration:</b>' + duration; width: details.width } } } @@ -109,19 +106,8 @@ ApplicationWindow { anchors { top: detailsTitle.bottom; bottom: parent.bottom } contentHeight: detailsView.height clip: true - - Column { - Row { - Text { text: 'Duration: ' + duration; width: details.width } - } - - Row { - Text { text: 'Depth: ' + depth; width: details.width } - } - - Row { - Text { text: 'Notes: ' + notes; wrapMode: Text.WordWrap; width: details.width } - } + Row { + Text { text: 'Notes: ' + notes; wrapMode: Text.WordWrap; width: details.width } } } } @@ -179,12 +165,31 @@ ApplicationWindow { } } + Component { + id: tripHeading + Rectangle { + width: page.width + height: childrenRect.height + color: "lightsteelblue" + + Text { + text: section + font.bold: true + font.pointSize: 16 + } + } + } + ListView { id: diveListView anchors.fill: parent model: diveModel delegate: diveDelegate focus: true + + section.property: "trip" + section.criteria: ViewSection.FullString + section.delegate: tripHeading } } } diff --git a/qt-models/divelistmodel.cpp b/qt-models/divelistmodel.cpp index c1862b8..ad36096 100644 --- a/qt-models/divelistmodel.cpp +++ b/qt-models/divelistmodel.cpp @@ -5,6 +5,14 @@ Dive::Dive(dive *d) { m_thisDive = d; setDiveNumber(QString::number(d->number)); + + dive_trip *trip = d->divetrip; + + if(trip) { + //trip is valid + setTrip(trip->location); + } + setDate(get_dive_date_string(d->when)); setDepth(get_depth_string(d->maxdepth)); setDuration(get_dive_duration_string(d->duration.seconds, "h:","min")); @@ -153,6 +161,16 @@ void Dive::setNotes(const QString ¬es) { m_notes = notes; } +QString Dive::trip() const +{ + return m_trip; +} + +void Dive::setTrip(const QString &trip) +{ + m_trip = trip; +} + @@ -184,6 +202,8 @@ QVariant DiveListModel::data(const QModelIndex &index, int role) const if (role == DiveNumberRole) return dive.diveNumber(); + else if (role == DiveTripRole) + return dive.trip(); else if (role == DiveDateRole) return dive.date(); else if (role == DiveRatingRole) @@ -217,6 +237,7 @@ QHash<int, QByteArray> DiveListModel::roleNames() const { QHash<int, QByteArray> roles; roles[DiveNumberRole] = "diveNumber"; + roles[DiveTripRole] = "trip"; roles[DiveDateRole] = "date"; roles[DiveRatingRole] = "rating"; roles[DiveDepthRole] = "depth"; diff --git a/qt-models/divelistmodel.h b/qt-models/divelistmodel.h index 307008c..f580405 100644 --- a/qt-models/divelistmodel.h +++ b/qt-models/divelistmodel.h @@ -50,8 +50,12 @@ public: QString notes() const; void setNotes(const QString ¬es); + QString trip() const; + void setTrip(const QString &trip); + private: QString m_diveNumber; + QString m_trip; QString m_date; QString m_rating; QString m_depth; @@ -76,6 +80,7 @@ public: enum DiveListRoles { DiveNumberRole = Qt::UserRole + 1, + DiveTripRole, DiveDateRole, DiveRatingRole, DiveDepthRole, -- 2.4.4
From 7e72062986fba14a78bfcd2c860fe70bcc041a98 Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Wed, 10 Jun 2015 21:39:43 +0300 Subject: [PATCH 17/22] Show dive details when a dive is clicked When a dive is clicked, show the dive details on the QML page. This contains basic details, and will be expanded further. Signed-off-by: Grace Karanja <[email protected]> --- qt-mobile/main.qml | 168 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 125 insertions(+), 43 deletions(-) diff --git a/qt-mobile/main.qml b/qt-mobile/main.qml index ee36b9c..20ea0c1 100644 --- a/qt-mobile/main.qml +++ b/qt-mobile/main.qml @@ -39,70 +39,152 @@ ApplicationWindow { } Rectangle { + id: page width: parent.width; height: parent.height - anchors.fill: parent Component { id: diveDelegate + Item { - id: wrapper - width: parent.width; height: 55 - Column { - Text { text: '#:' + diveNumber + "(" + date + ")" } - Text { text: 'Duration: ' + duration } - Text { text: 'Depth: ' + depth } + id: dive + + property real detailsOpacity : 0 + + width: diveListView.width + height: 70 + + //Bounded rect for the background + Rectangle { + id: background + x: 2; y: 2; width: parent.width - x*2; height: parent.height - y*2; + color: "ivory" + border.color: "orange" + radius: 5 } - MouseArea { anchors.fill: parent; onClicked: diveListView.currentIndex = index } - states: State { - name: "Current" - when: wrapper.ListView.isCurrentItem - PropertyChanges { target: wrapper; x:20 } + //Mouse region: When clicked, the mode changes to details view + MouseArea { + anchors.fill: parent + onClicked: dive.state = 'Details' } - transitions: Transition { - NumberAnimation { properties: "x"; duration: 200 } + + //Layout of the page: (mini profile, dive no, date at the tio + //And other details at the bottom. + Row { + id: topLayout + x: 10; y: 10; height: 50; width: parent.width + spacing: 10 + + Column { + width: background.width; height: 50 + spacing: 5 + + Text { + text: diveNumber + ' (' + date + ')' + font.bold: true; font.pointSize: 16 + } + + Text { + text: location + } + } } - } - } - Component { - id: highlightBar - Rectangle { - width: parent.width; height: 50 - color: "lightsteelblue" - radius: 5 - y: diveListView.currentItem.y; - Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } } - } - } + Item { + id: details + x: 10; width: parent.width - 20 + anchors { top: topLayout.bottom; topMargin: 10; bottom:parent.bottom; bottomMargin: 10 } + opacity: dive.detailsOpacity - Component { - id: tripHeading - Rectangle { - width: container.width - height: childrenRect.height - color: "lightgreen" - - Text { - text: section - font.bold: true + Text { + id: detailsTitle + anchors.top: parent.top + text: "Dive Details" + font.pointSize: 12; font.bold: true + } + + Flickable { + id: flick + width: parent.width + anchors { top: detailsTitle.bottom; bottom: parent.bottom } + contentHeight: detailsView.height + clip: true + + Column { + Row { + Text { text: 'Duration: ' + duration; width: details.width } + } + + Row { + Text { text: 'Depth: ' + depth; width: details.width } + } + + Row { + Text { text: 'Notes: ' + notes; wrapMode: Text.WordWrap; width: details.width } + } + } + } + } + + TextButton { + y: 10 + anchors { right: background.right; rightMargin: 10 } + opacity: dive.detailsOpacity + text: "Close" + + onClicked: dive.state = ''; + } + + states: State { + name: "Details" + + PropertyChanges { + target: background + color: "white" + } + + PropertyChanges { + target: dive + detailsOpacity: 1; x:0 //Make details visible + height: diveListView.height //Fill entire list area with the details + } + + //Move the list so that this item is at the top + PropertyChanges { + target: dive.ListView.view + explicit: true + contentY: dive.y + } + + //Disable flicking while we are in detailed view + PropertyChanges { + target: dive.ListView.view + interactive: false + } + } + + transitions: Transition { + //make the state changes smooth + ParallelAnimation { + ColorAnimation { + property: "color" + duration: 500 + } + NumberAnimation { + duration: 300 + properties: "detailsOpacity,x,contentY,height,width" + } + } } } } ListView { id: diveListView - width: parent.width; height: parent.height anchors.fill: parent model: diveModel delegate: diveDelegate focus: true - highlight: highlightBar - highlightFollowsCurrentItem: false - - section.property: "location" - section.criteria: ViewSection.FullString - section.delegate: tripHeading } } } -- 2.4.4
From fa10db87d8f15449fe597ab1214ce3c2e2eb378e Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Wed, 10 Jun 2015 21:39:03 +0300 Subject: [PATCH 16/22] Add TextButton.qml file This file contains a styled button for use in QML Signed-off-by: Grace Karanja <[email protected]> --- qt-mobile/TextButton.qml | 38 ++++++++++++++++++++++++++++++++++++++ qt-mobile/mobile-resources.qrc | 1 + 2 files changed, 39 insertions(+) create mode 100644 qt-mobile/TextButton.qml diff --git a/qt-mobile/TextButton.qml b/qt-mobile/TextButton.qml new file mode 100644 index 0000000..cc497f4 --- /dev/null +++ b/qt-mobile/TextButton.qml @@ -0,0 +1,38 @@ +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 } + } +} + diff --git a/qt-mobile/mobile-resources.qrc b/qt-mobile/mobile-resources.qrc index 59d301c..2cee851 100644 --- a/qt-mobile/mobile-resources.qrc +++ b/qt-mobile/mobile-resources.qrc @@ -1,5 +1,6 @@ <RCC> <qresource prefix="/qml"> <file>main.qml</file> + <file>TextButton.qml</file> </qresource> </RCC> -- 2.4.4
From 59a00e55ee5a30ad2d9fdd6edf8e2481743e366d Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Wed, 10 Jun 2015 21:38:14 +0300 Subject: [PATCH 15/22] Add dive notes to the divelistmodel Add the dive notes field into the DiveListModel class. Signed-off-by: Grace Karanja <[email protected]> --- qt-models/divelistmodel.cpp | 14 ++++++++++++++ qt-models/divelistmodel.h | 7 ++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/qt-models/divelistmodel.cpp b/qt-models/divelistmodel.cpp index 1786c85..c1862b8 100644 --- a/qt-models/divelistmodel.cpp +++ b/qt-models/divelistmodel.cpp @@ -24,6 +24,7 @@ Dive::Dive(dive *d) setCylinder(QString(d->cylinder[0].type.description)); setSac(QString::number(d->sac)); setLocation(get_dive_location(d)); + setNotes(d->notes); } QString Dive::date() const @@ -143,6 +144,16 @@ void Dive::setDiveNumber(const QString &diveNumber) { m_diveNumber = diveNumber; } +QString Dive::notes() const +{ + return m_notes; +} + +void Dive::setNotes(const QString ¬es) +{ + m_notes = notes; +} + DiveListModel *DiveListModel::m_instance = NULL; @@ -195,6 +206,8 @@ QVariant DiveListModel::data(const QModelIndex &index, int role) const return dive.sac(); else if (role == DiveLocationRole) return dive.location(); + else if (role == DiveNotesRole) + return dive.notes(); return QVariant(); @@ -215,6 +228,7 @@ QHash<int, QByteArray> DiveListModel::roleNames() const roles[DiveGasRole] = "gas"; roles[DiveSacRole] = "sac"; roles[DiveLocationRole] = "location"; + roles[DiveNotesRole] = "notes"; return roles; } diff --git a/qt-models/divelistmodel.h b/qt-models/divelistmodel.h index 96f1691..307008c 100644 --- a/qt-models/divelistmodel.h +++ b/qt-models/divelistmodel.h @@ -47,6 +47,9 @@ public: QString diveNumber() const; void setDiveNumber(const QString &diveNumber); + QString notes() const; + void setNotes(const QString ¬es); + private: QString m_diveNumber; QString m_date; @@ -60,6 +63,7 @@ private: QString m_gas; QString m_sac; QString m_location; + QString m_notes; dive *m_thisDive; @@ -82,7 +86,8 @@ public: DiveCylinderRole, DiveGasRole, DiveSacRole, - DiveLocationRole + DiveLocationRole, + DiveNotesRole }; static DiveListModel *instance(); -- 2.4.4
From 282f69b178a34901d17e4896f64334b3945cde06 Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Wed, 10 Jun 2015 18:49:55 +0300 Subject: [PATCH 14/22] Group dives by location Group dives on the QML page by location. Signed-off-by: Grace Karanja <[email protected]> --- qt-mobile/main.qml | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/qt-mobile/main.qml b/qt-mobile/main.qml index 914f51b..ee36b9c 100644 --- a/qt-mobile/main.qml +++ b/qt-mobile/main.qml @@ -48,9 +48,9 @@ ApplicationWindow { id: wrapper width: parent.width; height: 55 Column { - Text { text: '#:' + diveNumber + "(" + location + ")" } - Text { text: date } - Text { text: duration + " " + depth } + Text { text: '#:' + diveNumber + "(" + date + ")" } + Text { text: 'Duration: ' + duration } + Text { text: 'Depth: ' + depth } } MouseArea { anchors.fill: parent; onClicked: diveListView.currentIndex = index } @@ -76,6 +76,20 @@ ApplicationWindow { } } + Component { + id: tripHeading + Rectangle { + width: container.width + height: childrenRect.height + color: "lightgreen" + + Text { + text: section + font.bold: true + } + } + } + ListView { id: diveListView width: parent.width; height: parent.height @@ -85,6 +99,10 @@ ApplicationWindow { focus: true highlight: highlightBar highlightFollowsCurrentItem: false + + section.property: "location" + section.criteria: ViewSection.FullString + section.delegate: tripHeading } } } -- 2.4.4
From 8ff67dffd43481ddfbb56ea64c88149814d71afe Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Wed, 10 Jun 2015 18:19:19 +0300 Subject: [PATCH 13/22] Better theme for dive list view Set a rounded blue rectangle on the selected item. Signed-off-by: Grace Karanja <[email protected]> --- qt-mobile/main.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qt-mobile/main.qml b/qt-mobile/main.qml index 66a81e3..914f51b 100644 --- a/qt-mobile/main.qml +++ b/qt-mobile/main.qml @@ -69,7 +69,8 @@ ApplicationWindow { id: highlightBar Rectangle { width: parent.width; height: 50 - color: "#FFFF88" + color: "lightsteelblue" + radius: 5 y: diveListView.currentItem.y; Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } } } -- 2.4.4
From a3dd4606a01d411c5c3e742015d5c9e92cd393ae Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Tue, 9 Jun 2015 22:20:44 +0300 Subject: [PATCH 12/22] Add DiveListModel This model will be used to show the dives in QML. This commit adds the model, and the means to link it to QML. Signed-off-by: Grace Karanja <[email protected]> --- CMakeLists.txt | 2 +- qt-gui.cpp | 5 + qt-mobile/main.qml | 49 ++++++++++ qt-mobile/qmlmanager.cpp | 15 ++- qt-models/divelistmodel.cpp | 225 ++++++++++++++++++++++++++++++++++++++++++++ qt-models/divelistmodel.h | 100 ++++++++++++++++++++ 6 files changed, 392 insertions(+), 4 deletions(-) create mode 100644 qt-models/divelistmodel.cpp create mode 100644 qt-models/divelistmodel.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a326a5a..79196b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -420,7 +420,7 @@ endif() # create the executables if(SUBSURFACE_MOBILE) - set(MOBILE_SRC qt-mobile/qmlmanager.cpp) + set(MOBILE_SRC qt-mobile/qmlmanager.cpp qt-models/divelistmodel.cpp) add_definitions(-DSUBSURFACE_MOBILE) qt5_add_resources(MOBILE_RESOURCES qt-mobile/mobile-resources.qrc) add_executable(subsurface-mobile ${MOBILE_SRC} ${SUBSURFACE_PKG} ${SUBSURFACE_APP} ${SUBSURFACE_RESOURCES} ${MOBILE_RESOURCES}) diff --git a/qt-gui.cpp b/qt-gui.cpp index d415910..518f271 100644 --- a/qt-gui.cpp +++ b/qt-gui.cpp @@ -16,7 +16,9 @@ #ifdef SUBSURFACE_MOBILE #include <QQuickWindow> #include <QQmlApplicationEngine> + #include <QQmlContext> #include "qt-mobile/qmlmanager.h" + #include "qt-models/divelistmodel.h" #endif static MainWindow *window = NULL; @@ -38,6 +40,9 @@ void run_ui() window->hide(); qmlRegisterType<QMLManager>("com.subsurface.mobile", 1, 0, "QMLManager"); QQmlApplicationEngine engine; + DiveListModel diveListModel; + QQmlContext *ctxt = engine.rootContext(); + ctxt->setContextProperty("diveModel", &diveListModel); engine.load(QUrl(QStringLiteral("qrc:///qml/main.qml"))); QObject *mainWindow = engine.rootObjects().value(0); QQuickWindow *qml_window = qobject_cast<QQuickWindow *>(mainWindow); diff --git a/qt-mobile/main.qml b/qt-mobile/main.qml index 99298bb..66a81e3 100644 --- a/qt-mobile/main.qml +++ b/qt-mobile/main.qml @@ -37,4 +37,53 @@ ApplicationWindow { } } } + + Rectangle { + width: parent.width; height: parent.height + anchors.fill: parent + + Component { + id: diveDelegate + Item { + id: wrapper + width: parent.width; height: 55 + Column { + Text { text: '#:' + diveNumber + "(" + location + ")" } + Text { text: date } + Text { text: duration + " " + depth } + } + MouseArea { anchors.fill: parent; onClicked: diveListView.currentIndex = index } + + states: State { + name: "Current" + when: wrapper.ListView.isCurrentItem + PropertyChanges { target: wrapper; x:20 } + } + transitions: Transition { + NumberAnimation { properties: "x"; duration: 200 } + } + } + } + + Component { + id: highlightBar + Rectangle { + width: parent.width; height: 50 + color: "#FFFF88" + y: diveListView.currentItem.y; + Behavior on y { SpringAnimation { spring: 2; damping: 0.1 } } + } + } + + ListView { + id: diveListView + width: parent.width; height: parent.height + anchors.fill: parent + model: diveModel + delegate: diveDelegate + focus: true + highlight: highlightBar + highlightFollowsCurrentItem: false + } + } } diff --git a/qt-mobile/qmlmanager.cpp b/qt-mobile/qmlmanager.cpp index 6a770b2..0f8ccbe 100644 --- a/qt-mobile/qmlmanager.cpp +++ b/qt-mobile/qmlmanager.cpp @@ -1,15 +1,15 @@ #include "qmlmanager.h" #include <QUrl> +#include "../qt-models/divelistmodel.h" + QMLManager::QMLManager() { - } QMLManager::~QMLManager() { - } QString QMLManager::filename() @@ -20,12 +20,21 @@ QString QMLManager::filename() void QMLManager::setFilename(const QString &f) { m_fileName = f; - emit filenameChanged(); loadFile(); + emit filenameChanged(); } void QMLManager::loadFile() { QUrl url(m_fileName); QString strippedFileName = url.toLocalFile(); + + parse_file(strippedFileName.toUtf8().data()); + + int i; + struct dive *d; + + for_each_dive(i, d) { + DiveListModel::instance()->addDive(d); + } } diff --git a/qt-models/divelistmodel.cpp b/qt-models/divelistmodel.cpp new file mode 100644 index 0000000..1786c85 --- /dev/null +++ b/qt-models/divelistmodel.cpp @@ -0,0 +1,225 @@ +#include "divelistmodel.h" +#include "helpers.h" + +Dive::Dive(dive *d) +{ + m_thisDive = d; + setDiveNumber(QString::number(d->number)); + setDate(get_dive_date_string(d->when)); + setDepth(get_depth_string(d->maxdepth)); + setDuration(get_dive_duration_string(d->duration.seconds, "h:","min")); + + if (!d->watertemp.mkelvin) + m_depth = ""; + + if (get_units()->temperature == units::CELSIUS) + m_depth = QString::number(mkelvin_to_C(d->watertemp.mkelvin), 'f', 1); + else + m_depth = QString::number(mkelvin_to_F(d->watertemp.mkelvin), 'f', 1); + + weight_t tw = { total_weight(d) }; + setWeight(weight_string(tw.grams)); + + setSuit(QString(d->suit)); + setCylinder(QString(d->cylinder[0].type.description)); + setSac(QString::number(d->sac)); + setLocation(get_dive_location(d)); +} + +QString Dive::date() const +{ + return m_date; +} + +void Dive::setDate(const QString &date) +{ + m_date = date; +} +QString Dive::location() const +{ + return m_location; +} + +void Dive::setLocation(const QString &location) +{ + m_location = location; +} +QString Dive::sac() const +{ + return m_sac; +} + +void Dive::setSac(const QString &sac) +{ + m_sac = sac; +} +QString Dive::gas() const +{ + return m_gas; +} + +void Dive::setGas(const QString &gas) +{ + m_gas = gas; +} +QString Dive::cylinder() const +{ + return m_cylinder; +} + +void Dive::setCylinder(const QString &cylinder) +{ + m_cylinder = cylinder; +} +QString Dive::suit() const +{ + return m_suit; +} + +void Dive::setSuit(const QString &suit) +{ + m_suit = suit; +} +QString Dive::weight() const +{ + return m_weight; +} + +void Dive::setWeight(const QString &weight) +{ + m_weight = weight; +} +QString Dive::temp() const +{ + return m_temp; +} + +void Dive::setTemp(const QString &temp) +{ + m_temp = temp; +} +QString Dive::duration() const +{ + return m_duration; +} + +void Dive::setDuration(const QString &duration) +{ + m_duration = duration; +} +QString Dive::depth() const +{ + return m_depth; +} + +void Dive::setDepth(const QString &depth) +{ + m_depth = depth; +} +QString Dive::rating() const +{ + return m_rating; +} + +void Dive::setRating(const QString &rating) +{ + m_rating = rating; +} +dive *Dive::thisDive() const +{ + return m_thisDive; +} + +void Dive::setThisDive(dive *thisDive) +{ + m_thisDive = thisDive; +} +QString Dive::diveNumber() const +{ + return m_diveNumber; +} + +void Dive::setDiveNumber(const QString &diveNumber) +{ + m_diveNumber = diveNumber; +} + + +DiveListModel *DiveListModel::m_instance = NULL; + +DiveListModel::DiveListModel(QObject *parent) : QAbstractListModel(parent) +{ + m_instance = this; +} + +void DiveListModel::addDive(dive *d) +{ + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + m_dives.append(Dive(d)); + endInsertRows(); +} + +int DiveListModel::rowCount(const QModelIndex &) const +{ + return m_dives.count(); +} + +QVariant DiveListModel::data(const QModelIndex &index, int role) const +{ + if(index.row() < 0 || index.row() > m_dives.count()) + return QVariant(); + + const Dive &dive = m_dives[index.row()]; + + if (role == DiveNumberRole) + return dive.diveNumber(); + else if (role == DiveDateRole) + return dive.date(); + else if (role == DiveRatingRole) + return dive.rating(); + else if (role == DiveDepthRole) + return dive.depth(); + else if (role == DiveDurationRole) + return dive.duration(); + else if (role == DiveTemperatureRole) + return dive.temp(); + else if (role == DiveWeightRole) + return dive.weight(); + else if (role == DiveSuitRole) + return dive.suit(); + else if (role == DiveCylinderRole) + return dive.cylinder(); + else if (role == DiveGasRole) + return dive.gas(); + else if (role == DiveSacRole) + return dive.sac(); + else if (role == DiveLocationRole) + return dive.location(); + return QVariant(); + + +} + +QHash<int, QByteArray> DiveListModel::roleNames() const +{ + QHash<int, QByteArray> roles; + roles[DiveNumberRole] = "diveNumber"; + roles[DiveDateRole] = "date"; + roles[DiveRatingRole] = "rating"; + roles[DiveDepthRole] = "depth"; + roles[DiveDurationRole] = "duration"; + roles[DiveTemperatureRole] = "temp"; + roles[DiveWeightRole] = "weight"; + roles[DiveSuitRole] = "suit"; + roles[DiveCylinderRole] = "cylinder"; + roles[DiveGasRole] = "gas"; + roles[DiveSacRole] = "sac"; + roles[DiveLocationRole] = "location"; + + return roles; +} + +DiveListModel *DiveListModel::instance() +{ + return m_instance; +} diff --git a/qt-models/divelistmodel.h b/qt-models/divelistmodel.h new file mode 100644 index 0000000..96f1691 --- /dev/null +++ b/qt-models/divelistmodel.h @@ -0,0 +1,100 @@ +#ifndef DIVELISTMODEL_H +#define DIVELISTMODEL_H + +#include <QAbstractListModel> +#include "dive.h" + +class Dive { +public: + Dive(dive* d); + + QString date() const; + void setDate(const QString &date); + + QString location() const; + void setLocation(const QString &location); + + QString sac() const; + void setSac(const QString &sac); + + QString gas() const; + void setGas(const QString &gas); + + QString cylinder() const; + void setCylinder(const QString &cylinder); + + QString suit() const; + void setSuit(const QString &suit); + + QString weight() const; + void setWeight(const QString &weight); + + QString temp() const; + void setTemp(const QString &temp); + + QString duration() const; + void setDuration(const QString &duration); + + QString depth() const; + void setDepth(const QString &depth); + + QString rating() const; + void setRating(const QString &rating); + + dive *thisDive() const; + void setThisDive(dive *thisDive); + + QString diveNumber() const; + void setDiveNumber(const QString &diveNumber); + +private: + QString m_diveNumber; + QString m_date; + QString m_rating; + QString m_depth; + QString m_duration; + QString m_temp; + QString m_weight; + QString m_suit; + QString m_cylinder; + QString m_gas; + QString m_sac; + QString m_location; + + + dive *m_thisDive; +}; + +class DiveListModel : public QAbstractListModel +{ + Q_OBJECT +public: + + enum DiveListRoles { + DiveNumberRole = Qt::UserRole + 1, + DiveDateRole, + DiveRatingRole, + DiveDepthRole, + DiveDurationRole, + DiveTemperatureRole, + DiveWeightRole, + DiveSuitRole, + DiveCylinderRole, + DiveGasRole, + DiveSacRole, + DiveLocationRole + }; + + static DiveListModel *instance(); + DiveListModel(QObject *parent = 0); + void addDive(dive *d); + int rowCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QHash<int, QByteArray> roleNames() const; + +private: + QList<Dive> m_dives; + static DiveListModel *m_instance; +}; + +#endif // DIVELISTMODEL_H -- 2.4.4
From 9c47d31d246b4bb55b129396f219a90811e3f521 Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Fri, 5 Jun 2015 07:46:24 +0300 Subject: [PATCH 11/22] Only include Qt Quick when on mobile In qt-gui.cpp, move the Qt Quick includes so that they will only be used when on cmake SUBSURFACE_MOBILE is True. Signed-off-by: Grace Karanja <[email protected]> --- qt-gui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qt-gui.cpp b/qt-gui.cpp index 85367c2..d415910 100644 --- a/qt-gui.cpp +++ b/qt-gui.cpp @@ -10,12 +10,12 @@ #include <QNetworkProxy> #include <QLibraryInfo> -#include <QQuickWindow> -#include <QQmlApplicationEngine> #include "qt-gui.h" #ifdef SUBSURFACE_MOBILE + #include <QQuickWindow> + #include <QQmlApplicationEngine> #include "qt-mobile/qmlmanager.h" #endif -- 2.4.4
From 56e7bbbc5a63abaa22468a257b231129369b5d64 Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Thu, 4 Jun 2015 13:36:36 +0300 Subject: [PATCH 10/22] Link QMLManager to the main.qml file Add a link between the C++ and QML parts of the app using the qmlRegisterType function. Signed-off-by: Grace Karanja <[email protected]> --- qt-gui.cpp | 5 +++++ qt-mobile/main.qml | 9 +++++++++ qt-mobile/qmlmanager.cpp | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/qt-gui.cpp b/qt-gui.cpp index 6bc2e1e..85367c2 100644 --- a/qt-gui.cpp +++ b/qt-gui.cpp @@ -15,6 +15,10 @@ #include "qt-gui.h" +#ifdef SUBSURFACE_MOBILE + #include "qt-mobile/qmlmanager.h" +#endif + static MainWindow *window = NULL; void init_ui() @@ -32,6 +36,7 @@ void run_ui() { #ifdef SUBSURFACE_MOBILE window->hide(); + qmlRegisterType<QMLManager>("com.subsurface.mobile", 1, 0, "QMLManager"); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:///qml/main.qml"))); QObject *mainWindow = engine.rootObjects().value(0); diff --git a/qt-mobile/main.qml b/qt-mobile/main.qml index a98fb14..99298bb 100644 --- a/qt-mobile/main.qml +++ b/qt-mobile/main.qml @@ -2,6 +2,7 @@ import QtQuick 2.3 import QtQuick.Controls 1.2 import QtQuick.Window 2.2 import QtQuick.Dialogs 1.2 +import com.subsurface.mobile 1.0 ApplicationWindow { title: qsTr("Subsurface") @@ -12,6 +13,14 @@ ApplicationWindow { id: fileOpen selectExisting: true selectMultiple: true + + onAccepted: { + manager.setFilename(fileUrl) + } + } + + QMLManager { + id: manager } menuBar: MenuBar { diff --git a/qt-mobile/qmlmanager.cpp b/qt-mobile/qmlmanager.cpp index 2de94e8..6a770b2 100644 --- a/qt-mobile/qmlmanager.cpp +++ b/qt-mobile/qmlmanager.cpp @@ -1,5 +1,5 @@ #include "qmlmanager.h" - +#include <QUrl> QMLManager::QMLManager() { -- 2.4.4
From 7362c2b18363a713c850834c0f86775a81e6499d Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Thu, 4 Jun 2015 13:31:03 +0300 Subject: [PATCH 09/22] Add QMLManager to the cmake Build the QMLManager class when compiling for mobile. Signed-off-by: Grace Karanja <[email protected]> --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b75219..a326a5a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -420,9 +420,10 @@ endif() # create the executables if(SUBSURFACE_MOBILE) + set(MOBILE_SRC qt-mobile/qmlmanager.cpp) add_definitions(-DSUBSURFACE_MOBILE) qt5_add_resources(MOBILE_RESOURCES qt-mobile/mobile-resources.qrc) - add_executable(subsurface-mobile ${SUBSURFACE_PKG} ${SUBSURFACE_APP} ${SUBSURFACE_RESOURCES} ${MOBILE_RESOURCES}) + add_executable(subsurface-mobile ${MOBILE_SRC} ${SUBSURFACE_PKG} ${SUBSURFACE_APP} ${SUBSURFACE_RESOURCES} ${MOBILE_RESOURCES}) target_link_libraries( subsurface-mobile subsurface_generated_ui -- 2.4.4
From 1e40a1e887c203267e623935f110e4b619459bcd Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Thu, 4 Jun 2015 13:29:50 +0300 Subject: [PATCH 08/22] Add QMLManager class Add a QMLManager class. This class will be used as a link between the C++ and QML aspects of the mobile application. Signed-off-by: Grace Karanja <[email protected]> --- qt-mobile/qmlmanager.cpp | 31 +++++++++++++++++++++++++++++++ qt-mobile/qmlmanager.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 qt-mobile/qmlmanager.cpp create mode 100644 qt-mobile/qmlmanager.h diff --git a/qt-mobile/qmlmanager.cpp b/qt-mobile/qmlmanager.cpp new file mode 100644 index 0000000..2de94e8 --- /dev/null +++ b/qt-mobile/qmlmanager.cpp @@ -0,0 +1,31 @@ +#include "qmlmanager.h" + + +QMLManager::QMLManager() +{ + +} + + +QMLManager::~QMLManager() +{ + +} + +QString QMLManager::filename() +{ + return m_fileName; +} + +void QMLManager::setFilename(const QString &f) +{ + m_fileName = f; + emit filenameChanged(); + loadFile(); +} + +void QMLManager::loadFile() +{ + QUrl url(m_fileName); + QString strippedFileName = url.toLocalFile(); +} diff --git a/qt-mobile/qmlmanager.h b/qt-mobile/qmlmanager.h new file mode 100644 index 0000000..e74db0b --- /dev/null +++ b/qt-mobile/qmlmanager.h @@ -0,0 +1,31 @@ +#ifndef QMLMANAGER_H +#define QMLMANAGER_H + +#include <QObject> +#include <QString> + +class QMLManager : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString filename READ filename WRITE setFilename NOTIFY filenameChanged) +public: + QMLManager(); + ~QMLManager(); + + QString filename(); + + void getFile(); + + +public slots: + void setFilename(const QString &f); + +private: + QString m_fileName; + void loadFile(); + +signals: + void filenameChanged(); +}; + +#endif -- 2.4.4
From 9e2bfbc312828a9c956a68fda508f3c709e2fff8 Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Thu, 4 Jun 2015 11:27:38 +0300 Subject: [PATCH 07/22] Add FileOpen dialog to QML Add a dialog to select dive files in the QML interface, and also add a menu entry to open the dialog. Signed-off-by: Grace Karanja <[email protected]> --- qt-mobile/main.qml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/qt-mobile/main.qml b/qt-mobile/main.qml index 52cfd98..a98fb14 100644 --- a/qt-mobile/main.qml +++ b/qt-mobile/main.qml @@ -1,15 +1,28 @@ import QtQuick 2.3 import QtQuick.Controls 1.2 import QtQuick.Window 2.2 +import QtQuick.Dialogs 1.2 ApplicationWindow { title: qsTr("Subsurface") width: 500; height: 700 + + FileDialog { + id: fileOpen + selectExisting: true + selectMultiple: true + } + menuBar: MenuBar { Menu { title: qsTr("File") MenuItem { + text: qsTr("Open") + onTriggered: fileOpen.open() + } + + MenuItem { text: qsTr("Exit") onTriggered: Qt.quit(); } -- 2.4.4
From 2993f1dfcb106bf5ffe529cfe0eb09d20e8e138e Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Wed, 3 Jun 2015 17:19:01 +0300 Subject: [PATCH 06/22] Hide MainWindow when running under mobile When compiling the mobile version, hide the Qt MainWindow. Signed-off-by: Grace Karanja <[email protected]> --- qt-gui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/qt-gui.cpp b/qt-gui.cpp index fdcae2c..6bc2e1e 100644 --- a/qt-gui.cpp +++ b/qt-gui.cpp @@ -31,6 +31,7 @@ void init_ui() void run_ui() { #ifdef SUBSURFACE_MOBILE + window->hide(); QQmlApplicationEngine engine; engine.load(QUrl(QStringLiteral("qrc:///qml/main.qml"))); QObject *mainWindow = engine.rootObjects().value(0); -- 2.4.4
From 1a7c61dfe0f33579612319e1c38e6d9b4beca83c Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Wed, 27 May 2015 15:36:39 +0300 Subject: [PATCH 05/22] Load main.qml on startup for mobile builds When cmake is run with -DSUBSURFACE_MOBILE=True, the initial window will be main.qml, instead of the MainWindow used when cmake is run with -DSUBSURFACE_MOBILE=False Signed-off-by: Grace Karanja <[email protected]> --- qt-gui.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/qt-gui.cpp b/qt-gui.cpp index 713fd53..fdcae2c 100644 --- a/qt-gui.cpp +++ b/qt-gui.cpp @@ -9,7 +9,9 @@ #include <QDesktopWidget> #include <QNetworkProxy> #include <QLibraryInfo> -#include <QTextCodec> + +#include <QQuickWindow> +#include <QQmlApplicationEngine> #include "qt-gui.h" @@ -28,7 +30,15 @@ void init_ui() void run_ui() { +#ifdef SUBSURFACE_MOBILE + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:///qml/main.qml"))); + QObject *mainWindow = engine.rootObjects().value(0); + QQuickWindow *qml_window = qobject_cast<QQuickWindow *>(mainWindow); + qml_window->show(); +#else window->show(); +#endif qApp->exec(); } -- 2.4.4
From 00071313ad62e32f5ba0c4b8c4eb45a94e8e3e7a Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Wed, 27 May 2015 15:33:23 +0300 Subject: [PATCH 04/22] Add subsurface-mobile app to cmake Add a subsurface-mobile entry to the CMakeLists.txt file. When cmake is run with -DSUBSURFACE_MOBILE=True, the compiled app will be named subsurface-mobile, and the initial page (main.qml) will automatically be loaded. This will ensure that the mobile app will be linked to QtQuick. Signed-off-by: Grace Karanja <[email protected]> --- CMakeLists.txt | 49 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d1b59c8..6b75219 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -132,8 +132,14 @@ if(NOT (insource OR insourcedir)) endif() # configure Qt. -find_package(Qt5 REQUIRED COMPONENTS Core Concurrent Widgets Network WebKitWidgets PrintSupport Svg Test LinguistTools) +if(SUBSURFACE_MOBILE) + set(QT_QUICK Quick) +endif() +find_package(Qt5 REQUIRED COMPONENTS Core Concurrent Widgets Network WebKitWidgets PrintSupport Svg Test LinguistTools ${QT_QUICK}) set(QT_LIBRARIES Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network Qt5::WebKitWidgets Qt5::PrintSupport Qt5::Svg) +if(SUBSURFACE_MOBILE) + set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::Quick) +endif() set(QT_TEST_LIBRARIES ${QT_LIBRARIES} Qt5::Test) # Generate the ssrf-config.h every 'make' @@ -413,17 +419,32 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") endif() # create the executables -add_executable(${SUBSURFACE_TARGET} MACOSX_BUNDLE WIN32 ${SUBSURFACE_PKG} ${SUBSURFACE_APP} ${SUBSURFACE_RESOURCES}) -target_link_libraries( - ${SUBSURFACE_TARGET} - subsurface_generated_ui - subsurface_interface - subsurface_profile - subsurface_statistics - subsurface_models - subsurface_corelib - ${SUBSURFACE_LINK_LIBRARIES} +if(SUBSURFACE_MOBILE) + add_definitions(-DSUBSURFACE_MOBILE) + qt5_add_resources(MOBILE_RESOURCES qt-mobile/mobile-resources.qrc) + add_executable(subsurface-mobile ${SUBSURFACE_PKG} ${SUBSURFACE_APP} ${SUBSURFACE_RESOURCES} ${MOBILE_RESOURCES}) + target_link_libraries( + subsurface-mobile + subsurface_generated_ui + subsurface_interface + subsurface_profile + subsurface_statistics + subsurface_models + subsurface_corelib + ${SUBSURFACE_LINK_LIBRARIES}) +else() + add_executable(${SUBSURFACE_TARGET} MACOSX_BUNDLE WIN32 ${SUBSURFACE_PKG} ${SUBSURFACE_APP} ${SUBSURFACE_RESOURCES}) + target_link_libraries( + ${SUBSURFACE_TARGET} + subsurface_generated_ui + subsurface_interface + subsurface_profile + subsurface_statistics + subsurface_models + subsurface_corelib + ${SUBSURFACE_LINK_LIBRARIES} ) +endif() add_dependencies(subsurface_statistics subsurface_generated_ui) add_dependencies(subsurface_profile subsurface_generated_ui) @@ -634,7 +655,11 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux") install(DIRECTORY theme DESTINATION share/subsurface) install(DIRECTORY printing_templates DESTINATION share/subsurface) install(FILES ${TRANSLATIONS} DESTINATION share/subsurface/translations) - install(TARGETS ${SUBSURFACE_TARGET} DESTINATION bin) + if(SUBSURFACE_MOBILE) + install(TARGETS subsurface-mobile DESTINATION bin) + else() + install(TARGETS ${SUBSURFACE_TARGET} DESTINATION bin) + endif() if(DEFINED LIBMARBLEDEVEL) install( CODE "file(GLOB SSRFMARBLE_SHLIBS \"${LIBMARBLEDEVEL}/lib/libssrfmarblewidget.so*\")" -- 2.4.4
From 670db136e266772db4b3a4ff040ec00eae930ab2 Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Wed, 27 May 2015 13:34:55 +0300 Subject: [PATCH 03/22] Add a menu to main.qml Add a menu with an Exit submenu in the main.qml file. This closes the application when clicked. Signed-off-by: Grace Karanja <[email protected]> --- qt-mobile/main.qml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/qt-mobile/main.qml b/qt-mobile/main.qml index e69de29..52cfd98 100644 --- a/qt-mobile/main.qml +++ b/qt-mobile/main.qml @@ -0,0 +1,18 @@ +import QtQuick 2.3 +import QtQuick.Controls 1.2 +import QtQuick.Window 2.2 + +ApplicationWindow { + title: qsTr("Subsurface") + width: 500; + height: 700 + menuBar: MenuBar { + Menu { + title: qsTr("File") + MenuItem { + text: qsTr("Exit") + onTriggered: Qt.quit(); + } + } + } +} -- 2.4.4
From 5caec56b493d372812ad78b5b7c879f197c43e2b Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Wed, 27 May 2015 13:07:50 +0300 Subject: [PATCH 02/22] Add resource file to hold QML files Add a resource file to hold any QML files that will be used in the mobile port. Signed-off-by: Grace Karanja <[email protected]> --- qt-mobile/mobile-resources.qrc | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 qt-mobile/mobile-resources.qrc diff --git a/qt-mobile/mobile-resources.qrc b/qt-mobile/mobile-resources.qrc new file mode 100644 index 0000000..59d301c --- /dev/null +++ b/qt-mobile/mobile-resources.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/qml"> + <file>main.qml</file> + </qresource> +</RCC> -- 2.4.4
From bdd916077b017e4d486cb4ac30e28423f20a0d39 Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Thu, 18 Jun 2015 10:45:26 +0300 Subject: [PATCH 22/22] Rename dive class to avoid conflict Rename the Dive class in divelistmodel.h to a void a conflict with the Dive class in templatelayout.h Signed-off-by: Grace Karanja <[email protected]> --- qt-models/divelistmodel.cpp | 96 ++++++++++++++++++++------------------------- qt-models/divelistmodel.h | 6 +-- 2 files changed, 45 insertions(+), 57 deletions(-) diff --git a/qt-models/divelistmodel.cpp b/qt-models/divelistmodel.cpp index add5af5..dfc175a 100644 --- a/qt-models/divelistmodel.cpp +++ b/qt-models/divelistmodel.cpp @@ -1,7 +1,7 @@ #include "divelistmodel.h" #include "helpers.h" -Dive::Dive(dive *d) +MobileDive::MobileDive(dive *d) { m_thisDive = d; setDiveNumber(QString::number(d->number)); @@ -31,185 +31,173 @@ Dive::Dive(dive *d) setDivemaster(d->divemaster); } -QString Dive::date() const +QString MobileDive::date() const { return m_date; } -void Dive::setDate(const QString &date) +void MobileDive::setDate(const QString &date) { m_date = date; } -QString Dive::location() const +QString MobileDive::location() const { return m_location; } -void Dive::setLocation(const QString &location) +void MobileDive::setLocation(const QString &location) { m_location = location; } -QString Dive::sac() const +QString MobileDive::sac() const { return m_sac; } -void Dive::setSac(const QString &sac) +void MobileDive::setSac(const QString &sac) { m_sac = sac; } -QString Dive::gas() const +QString MobileDive::gas() const { return m_gas; } -void Dive::setGas(const QString &gas) +void MobileDive::setGas(const QString &gas) { m_gas = gas; } -QString Dive::cylinder() const +QString MobileDive::cylinder() const { return m_cylinder; } -void Dive::setCylinder(const QString &cylinder) +void MobileDive::setCylinder(const QString &cylinder) { m_cylinder = cylinder; } -QString Dive::suit() const +QString MobileDive::suit() const { return m_suit; } -void Dive::setSuit(const QString &suit) +void MobileDive::setSuit(const QString &suit) { m_suit = suit; } -QString Dive::weight() const +QString MobileDive::weight() const { return m_weight; } -void Dive::setWeight(const QString &weight) +void MobileDive::setWeight(const QString &weight) { m_weight = weight; } -QString Dive::airtemp() const +QString MobileDive::airtemp() const { return m_airtemp; } -void Dive::setAirTemp(const QString &airtemp) +void MobileDive::setAirTemp(const QString &airtemp) { m_airtemp = airtemp; } -QString Dive::duration() const +QString MobileDive::duration() const { return m_duration; } -void Dive::setDuration(const QString &duration) +void MobileDive::setDuration(const QString &duration) { m_duration = duration; } -QString Dive::depth() const +QString MobileDive::depth() const { return m_depth; } -void Dive::setDepth(const QString &depth) +void MobileDive::setDepth(const QString &depth) { m_depth = depth; } -QString Dive::rating() const +QString MobileDive::rating() const { return m_rating; } -void Dive::setRating(const QString &rating) +void MobileDive::setRating(const QString &rating) { m_rating = rating; } -dive *Dive::thisDive() const +dive *MobileDive::thisDive() const { return m_thisDive; } -void Dive::setThisDive(dive *thisDive) +void MobileDive::setThisDive(dive *thisDive) { m_thisDive = thisDive; } -QString Dive::diveNumber() const +QString MobileDive::diveNumber() const { return m_diveNumber; } -void Dive::setDiveNumber(const QString &diveNumber) +void MobileDive::setDiveNumber(const QString &diveNumber) { m_diveNumber = diveNumber; } -QString Dive::notes() const +QString MobileDive::notes() const { return m_notes; } -void Dive::setNotes(const QString ¬es) +void MobileDive::setNotes(const QString ¬es) { m_notes = notes; } -QString Dive::trip() const +QString MobileDive::trip() const { return m_trip; } -void Dive::setTrip(const QString &trip) +void MobileDive::setTrip(const QString &trip) { m_trip = trip; } -QString Dive::buddy() const +QString MobileDive::buddy() const { return m_buddy; } -void Dive::setBuddy(const QString &buddy) +void MobileDive::setBuddy(const QString &buddy) { m_buddy = buddy; } -QString Dive::divemaster() const +QString MobileDive::divemaster() const { return m_divemaster; } -void Dive::setDivemaster(const QString &divemaster) +void MobileDive::setDivemaster(const QString &divemaster) { m_divemaster = divemaster; } -QString Dive::watertemp() const +QString MobileDive::watertemp() const { return m_watertemp; } -void Dive::setWatertemp(const QString &watertemp) +void MobileDive::setWatertemp(const QString &watertemp) { m_watertemp = watertemp; } -void Dive::setupDiveTempDetails() +void MobileDive::setupDiveTempDetails() { - const char *unit; - double d_airTemp, d_waterTemp; - - d_airTemp = get_temp_units(m_thisDive->airtemp.mkelvin, &unit); - d_waterTemp = get_temp_units(m_thisDive->watertemp.mkelvin, &unit); - - setAirTemp(QString::number(d_airTemp) + unit); - setWatertemp(QString::number(d_waterTemp) + unit); - - if (!m_thisDive->airtemp.mkelvin) - setAirTemp(""); - - if (!m_thisDive->watertemp.mkelvin) - setWatertemp(""); + setWatertemp(get_temperature_string(m_thisDive->watertemp, true)); + setAirTemp(get_temperature_string(m_thisDive->airtemp, true)); } @@ -227,7 +215,7 @@ DiveListModel::DiveListModel(QObject *parent) : QAbstractListModel(parent) void DiveListModel::addDive(dive *d) { beginInsertRows(QModelIndex(), rowCount(), rowCount()); - m_dives.append(Dive(d)); + m_dives.append(MobileDive(d)); endInsertRows(); } @@ -241,7 +229,7 @@ QVariant DiveListModel::data(const QModelIndex &index, int role) const if(index.row() < 0 || index.row() > m_dives.count()) return QVariant(); - const Dive &dive = m_dives[index.row()]; + const MobileDive &dive = m_dives[index.row()]; if (role == DiveNumberRole) return dive.diveNumber(); diff --git a/qt-models/divelistmodel.h b/qt-models/divelistmodel.h index cb19188..68f0c6f 100644 --- a/qt-models/divelistmodel.h +++ b/qt-models/divelistmodel.h @@ -4,9 +4,9 @@ #include <QAbstractListModel> #include "dive.h" -class Dive { +class MobileDive { public: - Dive(dive* d); + MobileDive(dive* d); QString date() const; void setDate(const QString &date); @@ -120,7 +120,7 @@ public: QHash<int, QByteArray> roleNames() const; private: - QList<Dive> m_dives; + QList<MobileDive> m_dives; static DiveListModel *m_instance; }; -- 2.4.4
From cadd4614a9f9cff753b02e8d5afe55cab8574afc Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Wed, 27 May 2015 12:12:31 +0300 Subject: [PATCH 01/22] Create empty qt-mobile directory Create a qt-mobile directory, with a blank main.qml file. This file will be built up-on to come up with a usable mobile interface. Signed-off-by: Grace Karanja <[email protected]> --- qt-mobile/main.qml | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 qt-mobile/main.qml diff --git a/qt-mobile/main.qml b/qt-mobile/main.qml new file mode 100644 index 0000000..e69de29 -- 2.4.4
_______________________________________________ subsurface mailing list [email protected] http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface
