see changelog
This commit is contained in:
parent
7255fe6cd7
commit
4b09f2a8e7
15 changed files with 561 additions and 81 deletions
|
@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- cancel button during start sequence
|
||||
- new screen in landscape mode
|
||||
- buttons for settings and profiles
|
||||
|
||||
## [0.02] - 2018-07-18
|
||||
### Fixed
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0"?>
|
||||
<manifest package="com.itsblue.speedclimbing_stopwatch" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.02" android:versionCode="2" android:installLocation="auto">
|
||||
<manifest package="com.itsblue.speedclimbing_stopwatchtest" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.02" android:versionCode="2" android:installLocation="auto">
|
||||
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="speedclimbing stw" android:icon="@drawable/icon">
|
||||
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="speedclimbing stw" android:screenOrientation="unspecified" android:launchMode="singleTop">
|
||||
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="com.itsblue.StayAwake" android:label="speedclimbing stw" android:screenOrientation="unspecified" android:launchMode="singleTop">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
|
@ -59,6 +59,7 @@
|
|||
-->
|
||||
<meta-data android:name="android.app.extract_android_style" android:value="full"/>
|
||||
<!-- extract android style -->
|
||||
|
||||
</activity>
|
||||
|
||||
<!-- For adding service(s) please check: https://wiki.qt.io/AndroidServices -->
|
||||
|
|
8
android-sources/src/StayAwake.java
Normal file
8
android-sources/src/StayAwake.java
Normal file
|
@ -0,0 +1,8 @@
|
|||
package com.itsblue;
|
||||
public class StayAwake extends org.qtproject.qt5.android.bindings.QtActivity {
|
||||
@Override
|
||||
public void onCreate(android.os.Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
this.getWindow().addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
}
|
BIN
graphics/icons/settings.png
Normal file
BIN
graphics/icons/settings.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 324 KiB |
BIN
graphics/icons/user.png
Normal file
BIN
graphics/icons/user.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
graphics/screenshots/photo_2018-07-17_17-36-30.jpg
Normal file
BIN
graphics/screenshots/photo_2018-07-17_17-36-30.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
BIN
graphics/screenshots/photo_2018-07-17_17-50-50.jpg
Normal file
BIN
graphics/screenshots/photo_2018-07-17_17-50-50.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 35 KiB |
43
main.cpp
43
main.cpp
|
@ -1,5 +1,41 @@
|
|||
#include <QGuiApplication>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QSqlDatabase>
|
||||
#include <QSqlError>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
#include <QtAndroidExtras>
|
||||
|
||||
#include "sqlstoragemodel.h"
|
||||
#include "sqlprofilemodel.h"
|
||||
|
||||
static void connectToDatabase()
|
||||
{
|
||||
QSqlDatabase database = QSqlDatabase::database();
|
||||
if (!database.isValid()) {
|
||||
database = QSqlDatabase::addDatabase("QSQLITE");
|
||||
if (!database.isValid())
|
||||
qFatal("Cannot add database: %s", qPrintable(database.lastError().text()));
|
||||
}
|
||||
|
||||
const QDir writeDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||
qDebug() << writeDir;
|
||||
if (!writeDir.mkpath("."))
|
||||
qFatal("Failed to create writable directory at %s", qPrintable(writeDir.absolutePath()));
|
||||
|
||||
// Ensure that we have a writable location on all devices.
|
||||
const QString fileName = writeDir.absolutePath() + "/chat-database.sqlite3";
|
||||
//QFile::remove(fileName);
|
||||
// When using the SQLite driver, open() will create the SQLite database if it doesn't exist.
|
||||
database.setDatabaseName(fileName);
|
||||
if (!database.open()) {
|
||||
QFile::remove(fileName);
|
||||
qFatal("Cannot open database: %s", qPrintable(database.lastError().text()));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
@ -7,6 +43,13 @@ int main(int argc, char *argv[])
|
|||
|
||||
QGuiApplication app(argc, argv);
|
||||
|
||||
|
||||
connectToDatabase();
|
||||
|
||||
//setup the sql storage model as a qml model
|
||||
qmlRegisterType<SqlProfileModel>("com.itsblue.speedclimbingstopwatch", 1, 0, "SqlProfileModel");
|
||||
qmlRegisterType<SqlStorageModel>("com.itsblue.speedclimbingstopwatch", 1, 0, "SqlStorageModel");
|
||||
|
||||
QQmlApplicationEngine engine;
|
||||
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
|
||||
if (engine.rootObjects().isEmpty())
|
||||
|
|
399
main.qml
399
main.qml
|
@ -2,6 +2,9 @@ import QtQuick 2.9
|
|||
import QtMultimedia 5.8
|
||||
import QtQuick.Window 2.2
|
||||
import QtQuick.Controls 2.2
|
||||
import QtQuick.Layouts 1.11
|
||||
|
||||
import com.itsblue.speedclimbingstopwatch 1.0
|
||||
|
||||
Window {
|
||||
visible: true
|
||||
|
@ -20,7 +23,10 @@ Window {
|
|||
property double stoppedTime: 0
|
||||
property double currTime: new Date().getTime()
|
||||
|
||||
state: "IDLE"
|
||||
|
||||
Timer {
|
||||
//timer that updates the currTime variable
|
||||
running: true
|
||||
repeat: true
|
||||
interval: 1
|
||||
|
@ -29,36 +35,11 @@ Window {
|
|||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: time_container
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
}
|
||||
height: parent.height * 0.15
|
||||
|
||||
Label {
|
||||
id: time
|
||||
text: "Click start to start"
|
||||
|
||||
anchors.centerIn: parent
|
||||
font.pixelSize: parent.height * 0.3
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
width: parent.width
|
||||
height: 1
|
||||
color: "grey"
|
||||
anchors.left: parent.left
|
||||
anchors.top: time_container.bottom
|
||||
}
|
||||
|
||||
SoundEffect {
|
||||
//start sound
|
||||
id: startSound
|
||||
source: "OFFICAL_IFSC_STARTIGNAL.wav"
|
||||
|
||||
onPlayingChanged: {
|
||||
if(!playing){
|
||||
root.startTime = new Date().getTime()
|
||||
|
@ -69,18 +50,56 @@ Window {
|
|||
}
|
||||
}
|
||||
|
||||
/*------------------------
|
||||
Timer text an upper line
|
||||
------------------------*/
|
||||
Item {
|
||||
id: time_container
|
||||
anchors {
|
||||
top: parent.top
|
||||
left: parent.left
|
||||
right: root.landscape() ? startButt.left:parent.right
|
||||
bottom: root.landscape() ? parent.bottom:startButt.top
|
||||
bottomMargin: root.landscape() ? undefined:parent.height * 0.1
|
||||
rightMargin: root.landscape() ? parent.width * 0.05:0
|
||||
}
|
||||
//height: root.landscape() ? undefined:parent.height * 0.15
|
||||
Label {
|
||||
id: time
|
||||
text: "Click start to start"
|
||||
|
||||
anchors.centerIn: parent
|
||||
//font.pixelSize: root.landscape() ? parent.width * 0.1:parent.height * 0.3
|
||||
elide: "ElideRight"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: root.landscape() ? 1:parent.width
|
||||
height: root.landscape() ? parent.height:1
|
||||
color: "grey"
|
||||
anchors.left: root.landscape() ? time_container.right:parent.left
|
||||
anchors.top: root.landscape() ? parent.top:time_container.bottom
|
||||
anchors.bottom: root.landscape() ? parent.bottom:undefined
|
||||
}
|
||||
|
||||
/*----------------------
|
||||
Start button
|
||||
----------------------*/
|
||||
Rectangle {
|
||||
id: startButt
|
||||
|
||||
property string text: "start"
|
||||
property int size: root.landscape() ? parent.width * 0.5:parent.height * 0.5
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
bottom: parent.bottom
|
||||
bottomMargin: parent.height * 0.5 - height * 0.5
|
||||
right: parent.right
|
||||
rightMargin: parent.width * 0.5 - width * 0.5
|
||||
}
|
||||
|
||||
height: parent.height - (parent.height * 0.5)
|
||||
width: height > parent.width ? parent.width * 0.8:height
|
||||
height: root.landscape() ? size > parent.height * 0.9 ? parent.height * 0.9:size : size
|
||||
width: root.landscape() ? size : size > parent.width * 0.9 ? parent.width * 0.9:size
|
||||
color: "white"
|
||||
border.color: "grey"
|
||||
border.width: 1
|
||||
|
@ -119,48 +138,333 @@ Window {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------
|
||||
Cancel button
|
||||
----------------------*/
|
||||
Rectangle {
|
||||
id: cancelButt
|
||||
|
||||
property string text: "cancel"
|
||||
anchors {
|
||||
right: startButt.right
|
||||
bottom: startButt.bottom
|
||||
}
|
||||
height: startButt.height * 0.3
|
||||
scale: 0
|
||||
width: height
|
||||
color: "white"
|
||||
border.color: "grey"
|
||||
border.width: 1
|
||||
radius: width / 2
|
||||
|
||||
Label {
|
||||
id: cancelButt_text
|
||||
text: parent.text
|
||||
anchors.centerIn: parent
|
||||
font.pixelSize: parent.height * 0.16
|
||||
font.family: "Helvetica"
|
||||
}
|
||||
MouseArea {
|
||||
enabled: startSound.playing
|
||||
anchors.fill: parent
|
||||
onPressed: parent.color = "lightgrey"
|
||||
onReleased: parent.color = "white"
|
||||
onClicked: {
|
||||
startSound.stop()
|
||||
root.stoppedTime = 0
|
||||
time.text = "false start"
|
||||
root.state = "STOPPED"
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
PropertyAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------
|
||||
lower line and menu
|
||||
-------------------*/
|
||||
Rectangle {
|
||||
width: root.landscape() ? 1:parent.width
|
||||
height: root.landscape() ? parent.height:1
|
||||
color: "grey"
|
||||
anchors.right: root.landscape() ? menu_container.left:parent.right
|
||||
anchors.bottom: root.landscape() ? parent.bottom:menu_container.top
|
||||
anchors.top: root.landscape() ? parent.top:undefined
|
||||
}
|
||||
|
||||
Item {
|
||||
id: menu_container
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
left: root.landscape() ? startButt.right:parent.left
|
||||
top: root.landscape() ? parent.top:startButt.bottom
|
||||
topMargin: root.landscape() ? undefined:parent.height * 0.1
|
||||
leftMargin: root.landscape() ? parent.width * 0.05:0
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: settingsButt
|
||||
|
||||
property string text: "cancel"
|
||||
anchors {
|
||||
//center
|
||||
verticalCenter: root.landscape() ? undefined:parent.verticalCenter
|
||||
horizontalCenter: root.landscape() ? parent.horizontalCenter:undefined
|
||||
//set anchors
|
||||
left: root.landscape() ? undefined:parent.left
|
||||
top: root.landscape() ? parent.top:undefined
|
||||
//align in landscape mode
|
||||
topMargin: root.landscape() ? (parent.height - (height * 2)) / 3:undefined
|
||||
//align in portrait mode
|
||||
leftMargin: root.landscape() ? undefined:(parent.width - width * 2) / 3
|
||||
|
||||
|
||||
}
|
||||
height: root.landscape() ? parent.width * 0.7:parent.height * 0.7
|
||||
width: height
|
||||
color: "white"
|
||||
border.color: "grey"
|
||||
border.width: 1
|
||||
radius: width / 2
|
||||
|
||||
|
||||
Image {
|
||||
id: settungsButt_Image
|
||||
source: "qrc:/graphics/icons/settings.png"
|
||||
anchors.centerIn: parent
|
||||
height: parent.height * 0.7
|
||||
width: parent.width * 0.7
|
||||
mipmap: true
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
enabled: root.state === "IDLE"
|
||||
anchors.fill: parent
|
||||
onPressed: parent.color = "lightgrey"
|
||||
onReleased: parent.color = "white"
|
||||
onClicked: {
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
PropertyAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
}
|
||||
Rectangle {
|
||||
id: profilesButt
|
||||
|
||||
property string text: "cancel"
|
||||
anchors {
|
||||
verticalCenter: root.landscape() ? undefined:parent.verticalCenter
|
||||
horizontalCenter: root.landscape() ? parent.horizontalCenter:undefined
|
||||
left: root.landscape() ? undefined:settingsButt.right
|
||||
top: root.landscape() ? settingsButt.bottom:undefined
|
||||
topMargin: root.landscape() ? (parent.height - (height * 2)) / 3:undefined
|
||||
leftMargin: root.landscape() ? undefined:(parent.width - width * 2) / 3
|
||||
}
|
||||
height: root.landscape() ? parent.width * 0.7:parent.height * 0.7
|
||||
|
||||
width: height
|
||||
color: "white"
|
||||
border.color: "grey"
|
||||
border.width: 1
|
||||
radius: width / 2
|
||||
|
||||
Image {
|
||||
id: profilesButt_Image
|
||||
source: "qrc:/graphics/icons/user.png"
|
||||
anchors.centerIn: parent
|
||||
height: parent.height * 0.5
|
||||
width: parent.width * 0.5
|
||||
mipmap: true
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
enabled: root.state === "IDLE"
|
||||
anchors.fill: parent
|
||||
onPressed: parent.color = "lightgrey"
|
||||
onReleased: parent.color = "white"
|
||||
onClicked: {
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on scale {
|
||||
PropertyAnimation {
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// ComboBox {
|
||||
// id: profileBox
|
||||
// property int profileIndex: -1
|
||||
// model: SqlProfileModel{}
|
||||
// textRole: "name"
|
||||
// width: parent.width
|
||||
// anchors {
|
||||
// bottom: parent.bottom
|
||||
// horizontalCenter: parent.horizontalCenter
|
||||
// }
|
||||
// height: parent.height * 0.05
|
||||
// background: Rectangle {
|
||||
// color: profileBox.down ? "lightgrey":"white"
|
||||
// border.width: 1
|
||||
// border.color: "grey"
|
||||
// }
|
||||
// popup: Popup {
|
||||
// id: profileBox_popup
|
||||
// property bool popup_open: false
|
||||
// y: profileBox.height - 1
|
||||
// width: profileBox.width
|
||||
// implicitHeight: contentItem.implicitHeight
|
||||
// padding: 1
|
||||
|
||||
// contentItem: ListView {
|
||||
// clip: true
|
||||
// implicitHeight: contentHeight
|
||||
// model: profileBox.popup.visible ? profileBox.delegateModel : null
|
||||
// currentIndex: profileBox.highlightedIndex
|
||||
|
||||
// ScrollIndicator.vertical: ScrollIndicator { }
|
||||
// }
|
||||
// onVisibleChanged: {
|
||||
// if(visible){
|
||||
// if(popup_open){
|
||||
// popup_open = false
|
||||
// return
|
||||
// }
|
||||
// popup_open = true
|
||||
// height=implicitHeight
|
||||
// }
|
||||
// else {
|
||||
// height = 0
|
||||
// visible = true
|
||||
// }
|
||||
// }
|
||||
|
||||
// background: Rectangle {
|
||||
// border.color: "grey"
|
||||
// radius: 2
|
||||
// }
|
||||
|
||||
// Behavior on height {
|
||||
// NumberAnimation
|
||||
// {
|
||||
// onRunningChanged: {
|
||||
// if(!running && !profileBox_popup.popup_pen){
|
||||
// profileBox_popup.popup_open = false
|
||||
// profileBox_popup.visible = false
|
||||
// }
|
||||
// }
|
||||
|
||||
// duration: 200
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// onDownChanged: {
|
||||
// if(profileIndex !== currentIndex)
|
||||
// profileIndex = currentIndex
|
||||
// }
|
||||
// }
|
||||
*/
|
||||
|
||||
|
||||
/*----------------------
|
||||
Timer states
|
||||
----------------------*/
|
||||
states: [
|
||||
State {
|
||||
name: "IDLE"
|
||||
//state for the start page
|
||||
PropertyChanges { target: time; text: "Click start to start"; font.pixelSize: parent.height * 0.3 }
|
||||
PropertyChanges { target: time_container; height: parent.height * 0.15 }
|
||||
PropertyChanges { target: startButt; enabled: true; text: "start"; height: parent.height - (parent.height * 0.5); anchors.bottomMargin: parent.height * 0.5 - startButt.height * 0.5 }
|
||||
PropertyChanges { target: time; text: "Click start to start"; font.pixelSize: root.landscape() ? parent.width * 0.1:parent.height * 0.3; scale: 1 }
|
||||
PropertyChanges {
|
||||
target: time_container;
|
||||
anchors.bottomMargin: root.landscape() ? undefined:parent.height * 0.1;
|
||||
anchors.rightMargin: root.landscape() ? parent.height * 0.05:0
|
||||
}
|
||||
|
||||
PropertyChanges {
|
||||
target: startButt;
|
||||
enabled: true; text: "start";
|
||||
size: root.landscape() ? parent.width * 0.5:parent.height * 0.5
|
||||
anchors.bottomMargin: parent.height * 0.5 - startButt.height * 0.5
|
||||
anchors.rightMargin: parent.width * 0.5 - startButt.width * 0.5
|
||||
}
|
||||
|
||||
},
|
||||
State {
|
||||
name: "STARTING"
|
||||
//state for the start sequence
|
||||
PropertyChanges { target: startButt; enabled: false; text: "starting..." }
|
||||
PropertyChanges { target: time; text: "0.000 sec" }
|
||||
PropertyChanges { target: startButt; enabled: false; text: "starting...";
|
||||
anchors.rightMargin: root.landscape() ? parent.width * 0.05:none //put the button more to the right to hide the menu (only in landscape mode)
|
||||
anchors.bottomMargin: root.landscape() ? none:parent.height * 0.1 //put the button lower to hide the menu (only in portrait mode)
|
||||
}
|
||||
PropertyChanges { target: time; text: "0.000 sec"; font.pixelSize: root.landscape() ? parent.width * 0.2:parent.height * 0.3; scale: 1 }
|
||||
PropertyChanges { target: cancelButt; scale: 1}
|
||||
PropertyChanges { target: menu_container; }
|
||||
},
|
||||
State {
|
||||
name: "RUNNING"
|
||||
//state when the timer is running
|
||||
PropertyChanges { target: time; text: ( ( root.currTime - root.startTime ) / 1000 ).toFixed(3) + " sec" }
|
||||
PropertyChanges { target: startButt; enabled: true; text: "stop" }
|
||||
PropertyChanges { target: time; text: ( ( root.currTime - root.startTime ) / 1000 ).toFixed(3) + " sec"; font.pixelSize: root.landscape() ? parent.width * 0.2:parent.height * 0.3; scale: 1 }
|
||||
PropertyChanges { target: startButt; enabled: true;
|
||||
text: "stop"
|
||||
anchors.rightMargin: root.landscape() ? parent.width * 0.05:none //put the button more to the right to hide the menu (only in landscape mode)
|
||||
anchors.bottomMargin: root.landscape() ? none:parent.height * 0.1 //put the button lower to hide the menu (only in portrait mode)
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
State {
|
||||
name: "STOPPED"
|
||||
//state when the meassuring is over
|
||||
PropertyChanges { target: time; text: ( root.stoppedTime / 1000 ).toFixed(3) + " sec"; font.pixelSize: parent.height * 0.1 }
|
||||
PropertyChanges { target: startButt; enabled: true; text: "reset"; height: parent.height - (parent.height * 0.8); anchors.bottomMargin: parent.height * 0.2 - startButt.height * 0.5 }
|
||||
PropertyChanges { target: time_container; height: parent.height * 0.8 }
|
||||
PropertyChanges {
|
||||
target: time; text: root.stoppedTime > 0 ? ( root.stoppedTime / 1000 ).toFixed(3) + " sec":"false start";
|
||||
font.pixelSize: root.landscape() ? parent.width * 0.15:parent.height * 0.1;
|
||||
scale: 1
|
||||
}
|
||||
PropertyChanges {
|
||||
target: startButt;
|
||||
enabled: true; text: "reset";
|
||||
size: root.landscape() ? parent.height * 0.35:parent.height * 0.2;
|
||||
anchors.bottomMargin: root.landscape() ? parent.height * 0.5 - startButt.height * 0.5:parent.height * 0.2 - startButt.height * 0.5
|
||||
anchors.rightMargin: root.landscape() ? parent.height * 0.2 - startButt.height * 0.5:parent.width * 0.5 - startButt.width * 0.5
|
||||
}
|
||||
PropertyChanges {
|
||||
target: time_container;
|
||||
anchors.rightMargin: root.landscape() ? 0-startButt.width/2:undefined
|
||||
anchors.bottomMargin: root.landscape() ? undefined:0-startButt.height/2
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
/*----------------------
|
||||
Timer animations
|
||||
----------------------*/
|
||||
transitions: [
|
||||
Transition {
|
||||
NumberAnimation { properties: "height,width,bottomMargin,font.pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
|
||||
FadeAnimation { target: time; fadeDuration_in: 0; fadeDuration_out: 0 }
|
||||
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
|
||||
},
|
||||
Transition {
|
||||
to: "STOPPED"
|
||||
NumberAnimation { properties: "height,width,bottomMargin,font.pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
|
||||
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
|
||||
},
|
||||
Transition {
|
||||
to: "IDLE"
|
||||
NumberAnimation { properties: "height,width,bottomMargin,font.pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
|
||||
NumberAnimation { properties: "size,rightMargin,height,width,bottomMargin,font.pixelSize"; easing.type: Easing.InOutQuad; duration: 700 }
|
||||
FadeAnimation { target: time; fadeDuration_out: 1000; fadeDuration_in: 0}
|
||||
},
|
||||
|
||||
|
@ -169,5 +473,12 @@ Window {
|
|||
//disable transitions for the RUNNING state
|
||||
}
|
||||
]
|
||||
|
||||
/*----------------------
|
||||
Timer functions
|
||||
----------------------*/
|
||||
function landscape(){
|
||||
return(root.height < root.width)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>OFFICAL_IFSC_STARTIGNAL.wav</file>
|
||||
<file>graphics/icons/settings.png</file>
|
||||
<file>graphics/icons/user.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
QT += quick
|
||||
QT += quick sql androidextras
|
||||
CONFIG += c++11
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
|
@ -15,7 +15,9 @@ DEFINES += QT_DEPRECATED_WARNINGS
|
|||
TARGET = speedclimbing_stw
|
||||
|
||||
SOURCES += \
|
||||
main.cpp
|
||||
main.cpp \
|
||||
sqlstoragemodel.cpp \
|
||||
sqlprofilemodel.cpp
|
||||
|
||||
RESOURCES += qml.qrc \
|
||||
shared.qrc
|
||||
|
@ -35,8 +37,13 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin
|
|||
!isEmpty(target.path): INSTALLS += target
|
||||
|
||||
DISTFILES += \
|
||||
android-sources/AndroidManifest.xml
|
||||
android-sources/AndroidManifest.xml \
|
||||
android-sources/src/StayAwake.java
|
||||
|
||||
android {
|
||||
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android-sources
|
||||
}
|
||||
|
||||
HEADERS += \
|
||||
sqlstoragemodel.h \
|
||||
sqlprofilemodel.h
|
||||
|
|
56
sqlprofilemodel.cpp
Normal file
56
sqlprofilemodel.cpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
#include "sqlprofilemodel.h"
|
||||
|
||||
static void createTable()
|
||||
{
|
||||
if (QSqlDatabase::database().tables().contains(QStringLiteral("Contacts"))) {
|
||||
// The table already exists; we don't need to do anything.
|
||||
return;
|
||||
}
|
||||
|
||||
QSqlQuery query;
|
||||
|
||||
//creat eth etable to store the profiles
|
||||
if (!query.exec(
|
||||
"CREATE TABLE IF NOT EXISTS `profiles` ( "
|
||||
" `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,"
|
||||
" `name` TEXT NOT NULL "
|
||||
" );")) {
|
||||
qFatal("Failed to query database: %s", qPrintable(query.lastError().text()));
|
||||
}
|
||||
|
||||
//create the table to store the times
|
||||
if (!query.exec(
|
||||
"CREATE TABLE IF NOT EXISTS `times` ("
|
||||
" `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,"
|
||||
" `profileid` INTEGER NOT NULL,"
|
||||
" `time` INTEGER NOT NULL"
|
||||
" );")) {
|
||||
qFatal("Failed to query database: %s", qPrintable(query.lastError().text()));
|
||||
}
|
||||
}
|
||||
|
||||
SqlProfileModel::SqlProfileModel(QObject *parent) : QSqlTableModel(parent)
|
||||
{
|
||||
qDebug("ProfileModel constructor");
|
||||
createTable();
|
||||
setTable("profiles");
|
||||
select();
|
||||
}
|
||||
|
||||
QVariant SqlProfileModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (role < Qt::UserRole)
|
||||
return QSqlTableModel::data(index, role);
|
||||
|
||||
const QSqlRecord sqlRecord = record(index.row());
|
||||
return sqlRecord.value(role - Qt::UserRole);
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> SqlProfileModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> names;
|
||||
names[Qt::UserRole + 0] = "id";
|
||||
names[Qt::UserRole + 1] = "name";
|
||||
|
||||
return names;
|
||||
}
|
25
sqlprofilemodel.h
Normal file
25
sqlprofilemodel.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef SQLPROFILEMODEL_H
|
||||
#define SQLPROFILEMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <QSqlError>
|
||||
#include <QSqlQuery>
|
||||
#include <QDateTime>
|
||||
#include <QSqlRecord>
|
||||
#include <QSqlTableModel>
|
||||
|
||||
class SqlProfileModel : public QSqlTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SqlProfileModel(QObject *parent = nullptr);
|
||||
|
||||
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
|
||||
QHash<int, QByteArray> roleNames() const Q_DECL_OVERRIDE;
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
};
|
||||
|
||||
#endif // SQLPROFILEMODEL_H
|
6
sqlstoragemodel.cpp
Normal file
6
sqlstoragemodel.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "sqlstoragemodel.h"
|
||||
|
||||
SqlStorageModel::SqlStorageModel(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
17
sqlstoragemodel.h
Normal file
17
sqlstoragemodel.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef SQLSTORAGEMODEL_H
|
||||
#define SQLSTORAGEMODEL_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class SqlStorageModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SqlStorageModel(QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
};
|
||||
|
||||
#endif // SQLSTORAGEMODEL_H
|
Reference in a new issue