added stuff

This commit is contained in:
Dorian Zedler 2018-08-02 12:50:55 +02:00
parent 27500bfe7f
commit 51e3e543d9
15 changed files with 313 additions and 137 deletions

View file

@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]
### Added
- added profiles dialog
### Fixed
- start seqnece continues in a buggy way when cancel is being pressed while 'at your marks' or 'ready'
- bug that made the start sequence freeze if a delay of zero or lower or a non valid number was set as delay
## [0.03 - BETA] - 2018-07-29
### Added
- cancel button during start sequence
- new screen in landscape mode
- buttons for settings and profiles

View file

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<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">
<manifest package="com.itsblue.speedclimbing_stopwatchtest" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.03" android:versionCode="3" 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="com.itsblue.StayAwake" android:label="speedclimbing stw" android:screenOrientation="unspecified" android:launchMode="singleTop">
<intent-filter>

BIN
graphics/Buzzer.xcf Normal file

Binary file not shown.

View file

@ -14,12 +14,14 @@ public:
Q_INVOKABLE QString loadSetting(const QString &key);
Q_INVOKABLE void writeSetting(const QString &key, const QVariant &variant);
Q_INVOKABLE void setDefaultSetting(const QString &key, const QVariant &defaultVariant);
QSettings *settingsManager;
signals:
public slots:
};
extern AppSettings * pGlobalAppSettings;

View file

@ -35,8 +35,8 @@ private:
signals:
public slots:
ReturnData_t senddata(QUrl serviceUrl);
Q_INVOKABLE QList<double> gettimes();
ReturnData_t senddata(QUrl serviceUrl, int timeout);
Q_INVOKABLE QList<double> gettimes(int timeout);
Q_INVOKABLE bool connect();
Q_INVOKABLE bool calcoffset();
Q_INVOKABLE bool buzzer_triggered();

View file

@ -2,14 +2,22 @@
#define SQLSTORAGEMODEL_H
#include <QObject>
#include <QDebug>
#include <QSqlError>
#include <QSqlQuery>
#include <QDateTime>
#include <QSqlRecord>
#include <QSqlTableModel>
class SqlStorageModel : public QObject
class SqlStorageModel : public QSqlTableModel
{
Q_OBJECT
public:
explicit SqlStorageModel(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:

182
qml/ProfilesDialog.qml Normal file
View file

@ -0,0 +1,182 @@
import QtQuick 2.9
import QtMultimedia 5.8
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import com.itsblue.speedclimbingstopwatch 1.0
Popup {
id: root
x: startButt.x
y: startButt.y
width: startButt.width
height: startButt.height
modal: true
dim: false
enter: Transition {
NumberAnimation { properties: "scale"; from: 0; to: 1; duration: 300; easing.type: Easing.Linear }
}
exit: Transition {
NumberAnimation { properties: "scale"; from: 1; to: 0; duration: 300; easing.type: Easing.Linear }
}
background: Rectangle {
radius: width * 0.5
color: "white"
border.color: "grey"
border.width: 1
Label {
id: head_text
text: options_stack.currentItem.title
font.pixelSize: headlineUnderline.width * 0.1
anchors {
horizontalCenter: parent.horizontalCenter
top: parent.top
topMargin: headlineUnderline.anchors.topMargin / 2 - height / 2
}
}
Rectangle {
id: headlineUnderline
height: 1
width: parent.width
color: "grey"
anchors {
top: parent.top
left: parent.left
right: parent.right
topMargin: parent.height * 0.15
rightMargin: parent.radius - Math.sqrt(Math.pow(parent.radius,2)-Math.pow(parent.radius-anchors.topMargin,2))
leftMargin: parent.radius - Math.sqrt(Math.pow(parent.radius,2)-Math.pow(parent.radius-anchors.topMargin,2))
}
}
ProgressCircle {
id: prog
property string text: "connecting.."
anchors.fill: parent
opacity: 0
lineWidth: 5
arcBegin: 0
arcEnd: 0
Timer {
id: prog_refresh
running: false
interval: 1
repeat: true
onTriggered: {
prog.arcEnd = 360 * ( _cppBuzzerConn.get("connection_progress") / 100 )
}
}
Label {
id: content
text: parent.text
anchors.centerIn: parent
font.pixelSize: parent.width * 0.1
}
}
Button {
id: head_back
anchors {
left: parent.left
leftMargin: parent.width * 0.17
top:parent.top
topMargin: parent.height * 0.025
}
height: parent.height * 0.1
width:height
background: Rectangle {
radius: width * 0.5
color: "white"
border.color: "grey"
border.width: 1
Image {
anchors.fill: parent
anchors.margins: parent.width * 0.2
source: "qrc:/graphics/icons/back_black.png"
}
}
onClicked: {
options_stack.depth > 1 ? options_stack.pop():root.close()
}
onPressedChanged: {
if(pressed){
background.color = "lightgrey"
}
else {
background.color = "white"
}
}
Behavior on opacity {
NumberAnimation {
duration: 100
}
}
}
}
ListView {
id: profileList
anchors {
top: parent.top
left: parent.left
leftMargin: ( parent.width - headlineUnderline.width ) / 2
right: parent.right
rightMargin: headlineUnderline.anchors.rightMargin
topMargin: headlineUnderline.anchors.topMargin
bottom: parent.bottom
}
model:SqlProfileModel{}
delegate: SwipeDelegate {
id: swipeDelegate
text: model.name
width: profileList.width
Component {
id: component
Rectangle {
color: mouse.pressed ? "#333" : "#444"
width: parent.width
height: parent.height
clip: true
Label {
text: qsTr("Press me!")
color: "#21be2b"
anchors.centerIn: parent
}
MouseArea {
id: mouseAr
anchors.fill: parent
onClicked: {
model.remove(index)
}
}
}
}
swipe.left: component
swipe.right: component
}
ScrollIndicator.vertical: ScrollIndicator { }
}
}

View file

@ -53,6 +53,35 @@ Popup {
}
}
ProgressCircle {
id: prog
property string text: "connecting.."
anchors.fill: parent
opacity: 0
lineWidth: 5
arcBegin: 0
arcEnd: 0
Timer {
id: prog_refresh
running: false
interval: 1
repeat: true
onTriggered: {
prog.arcEnd = 360 * ( _cppBuzzerConn.get("connection_progress") / 100 )
}
}
Label {
id: content
text: parent.text
anchors.centerIn: parent
font.pixelSize: parent.width * 0.1
}
}
Button {
id: head_back
@ -98,36 +127,6 @@ Popup {
}
}
ProgressCircle {
id: prog
property string text: "connecting.."
anchors.centerIn: parent
size: parent.height * 1.03
opacity: 0
lineWidth: 5
arcBegin: 0
arcEnd: 0
Timer {
id: prog_refresh
running: false
interval: 1
repeat: true
onTriggered: {
prog.arcEnd = 360 * ( _cppBuzzerConn.get("connection_progress") / 100 )
}
}
Label {
id: content
text: parent.text
anchors.centerIn: parent
font.pixelSize: parent.width * 0.1
}
}
StackView {
id: options_stack
property int text_pixelSize: headlineUnderline.width * 0.08

View file

@ -118,12 +118,11 @@ Window {
source: "qrc:/sounds/at_marks_1.wav"
onPlayingChanged: {
if(!playing){
if(!playing && root.state==="STARTING"){
if(_cppAppSettings.loadSetting("ready_en") === "true"){
next_actionTimer.action = "ready"
next_actionTimer.interval = _cppAppSettings.loadSetting("ready_delay")
next_actionTimer.interval = _cppAppSettings.loadSetting("ready_delay")>0 ? _cppAppSettings.loadSetting("ready_delay"):1
next_actionTimer.start()
//readySound.play()
}
else{
startSound.play()
@ -136,7 +135,7 @@ Window {
id: readySound
source: "qrc:/sounds/ready_1.wav"
onPlayingChanged: {
if(!playing){
if(!playing && root.state==="STARTING"){
startSound.play()
}
}
@ -148,7 +147,7 @@ Window {
source: "qrc:/sounds/OFFICAL_IFSC_STARTIGNAL.wav"
onPlayingChanged: {
if(!playing){
if(!playing && root.state==="STARTING"){
root.startTime = _cppBuzzerConn.get("currtime")
_cppBuzzerConn.start()
root.currTime = _cppBuzzerConn.get("currtime")
@ -183,6 +182,20 @@ Window {
}
Rectangle {
anchors {
top: parent.top
topMargin: 10
left: parent.left
leftMargin: 10
}
width: height
radius: height*0.5
color: "#6efc0f"
}
Rectangle {
id: upper_line
width: root.landscape() ? 1:parent.width
height: root.landscape() ? parent.height:1
color: "grey"
@ -242,13 +255,13 @@ Window {
root.state = "STARTING"
if(_cppAppSettings.loadSetting("at_marks_en") === "true"){
next_actionTimer.action = "at_marks"
next_actionTimer.interval = _cppAppSettings.loadSetting("at_marks_delay")
next_actionTimer.interval = _cppAppSettings.loadSetting("at_marks_delay")>0 ? _cppAppSettings.loadSetting("at_marks_delay"):1
next_actionTimer.start()
return
}
if(_cppAppSettings.loadSetting("ready_en") === "true"){
next_actionTimer.action = "ready"
next_actionTimer.interval = _cppAppSettings.loadSetting("ready_delay")
next_actionTimer.interval = _cppAppSettings.loadSetting("ready_delay")>0 ? _cppAppSettings.loadSetting("ready_delay"):1
next_actionTimer.start()
return
}
@ -320,13 +333,13 @@ Window {
}
onClicked: {
root.stoppedTime = 0
time.text = "false start"
root.state = "STOPPED"
next_actionTimer.stop()
at_marksSound.stop()
readySound.stop()
startSound.stop()
root.stoppedTime = 0
time.text = "false start"
root.state = "STOPPED"
}
Behavior on scale {
@ -353,9 +366,12 @@ Window {
Popups
------*/
SettingsDialog{
id:settingsDialog
id: settingsDialog
}
ProfilesDialog {
id: profilesDialog
}
/*-------------------
lower line and menu
@ -455,6 +471,7 @@ Window {
}
onClicked: {
profilesDialog.open()
}
background: Rectangle {
@ -475,83 +492,6 @@ Window {
}
}
/*
// 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
----------------------*/

View file

@ -4,5 +4,6 @@
<file>FadeAnimation.qml</file>
<file>SettingsDialog.qml</file>
<file>ProgressCircle.qml</file>
<file>ProfilesDialog.qml</file>
</qresource>
</RCC>

View file

@ -4,8 +4,13 @@ AppSettings::AppSettings(QObject* parent)
:QObject(parent)
{
QString path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
qDebug(path.toLatin1());
this->settingsManager = new QSettings(path+"/settings.ini", QSettings::IniFormat);
this->setDefaultSetting("ready_en", "false");
this->setDefaultSetting("ready_delay", 0);
this->setDefaultSetting("at_marks_en", "false");
this->setDefaultSetting("at_marks_delay", 0);
}
QString AppSettings::loadSetting(const QString &key)
@ -23,6 +28,15 @@ void AppSettings::writeSetting(const QString &key, const QVariant &variant)
this->settingsManager->endGroup();
}
void AppSettings::setDefaultSetting(const QString &key, const QVariant &defaultVariant)
{
QString value = this->loadSetting(key);
if(value == "false"){
this->writeSetting(key, defaultVariant);
}
}
AppSettings::~AppSettings()
{
delete settingsManager;

View file

@ -12,7 +12,7 @@ BuzzerConn::BuzzerConn(QObject *parent) : QObject(parent)
bool BuzzerConn::connect()
{
qDebug() << "connecting to buzzer...";
QList<double> times = gettimes();
QList<double> times = gettimes(1000);
qDebug() << times[0];
if(times[0] == 200.0){
this->connected = true;
@ -34,7 +34,7 @@ bool BuzzerConn::connect()
bool BuzzerConn::calcoffset()
{
QList<double> times = gettimes();
QList<double> times = gettimes(1000);
if(times.length() != 3){
return(false);
}
@ -59,10 +59,10 @@ bool BuzzerConn::calcoffset()
}
}
QList<double> BuzzerConn::gettimes()
QList<double> BuzzerConn::gettimes(int timeout)
{
QList<double> times;
ReturnData_t ret = senddata(QUrl("http://192.168.4.1"));
ReturnData_t ret = senddata(QUrl("http://192.168.4.1"), timeout);
times.append(double(ret.status_code));
if(ret.status_code == 200){
@ -85,7 +85,7 @@ bool BuzzerConn::buzzer_triggered()
if(!this->connected){
return(false);
}
QList<double> times = this->gettimes();
QList<double> times = this->gettimes(1000);
if(times[0] == 200.0){
if(times[2] > this->latest_button_pressed){
this->latest_button_pressed = times[2];
@ -97,7 +97,7 @@ bool BuzzerConn::buzzer_triggered()
}
}
else{
this->connected = false;
//this->connected = false;
return(false);
}
}
@ -107,7 +107,7 @@ bool BuzzerConn::start()
if(!this->connected){
return(false);
}
QList<double> times = this->gettimes();
QList<double> times = this->gettimes(1000);
if(times[0] == 200.0 && this->connected){
this->latest_button_pressed = times[2];
return(true);
@ -142,11 +142,11 @@ double BuzzerConn::get(QString key)
QString BuzzerConn::test()
{
ReturnData_t ret = this->senddata(QUrl("http://www.google.de"));
ReturnData_t ret = this->senddata(QUrl("http://www.google.de"), 500);
return(ret.text);
}
ReturnData_t BuzzerConn::senddata(QUrl serviceUrl)
ReturnData_t BuzzerConn::senddata(QUrl serviceUrl, int timeout)
{
ReturnData_t ret; //this is a custom type to store the returned data
@ -168,7 +168,7 @@ ReturnData_t BuzzerConn::senddata(QUrl serviceUrl)
loop.connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
loop.connect(this->networkManager, SIGNAL(finished(QNetworkReply*)), SLOT(quit()));
timer.start(500);
timer.start(timeout);
reply = this->networkManager->post(request, pdata.toString(QUrl::FullyEncoded).toUtf8());
loop.exec();
timer.stop();

View file

@ -23,7 +23,8 @@ static void createTable()
"CREATE TABLE IF NOT EXISTS `times` ("
" `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,"
" `profileid` INTEGER NOT NULL,"
" `time` INTEGER NOT NULL"
" `time` INTEGER NOT NULL, "
" `timestamp` INTEGER NOT NULL"
" );")) {
qFatal("Failed to query database: %s", qPrintable(query.lastError().text()));
}

View file

@ -1,6 +1,26 @@
#include "headers/sqlstoragemodel.h"
SqlStorageModel::SqlStorageModel(QObject *parent) : QObject(parent)
SqlStorageModel::SqlStorageModel(QObject *parent) : QSqlTableModel(parent)
{
qDebug("ProfileModel constructor");
setTable("times");
select();
}
QVariant SqlStorageModel::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> SqlStorageModel::roleNames() const
{
QHash<int, QByteArray> names;
names[Qt::UserRole + 0] = "id";
names[Qt::UserRole + 1] = "name";
return names;
}

View file

@ -3,6 +3,7 @@ QT += quick sql
android {
QT += androidextras
}
VERSION =0.03
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
@ -44,7 +45,8 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin
DISTFILES += \
android-sources/AndroidManifest.xml \
android-sources/src/StayAwake.java
android-sources/src/StayAwake.java \
CHANGELOG
android {
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android-sources