mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-04-13 12:42:20 +00:00
Semi automatic creation of ranges for power zones (#4543)
* Changed the UI of CPPage to inline-editing of all values in all tables * Added a sports-specific selector for the model (cp2, cp3, ext, manual) * Allowed to create new ranges either manually or based on the estimated values of the model * Added option to reset each ranges values to those of the selected model * Added message to create a new range if todays estimate differs from those of the currently active one * Refined semi automatic power zones * Added a dialog to inspect and accept only some values while adoption * Added info messages * when the model does not provide FTP or PMAX * that AeTP is only a very rough estimate * Added a tolerance in comparison before proposing new values * Using the following order for defaults when adding a new manual range * selected row * last row * predefined defaults * Zones-Tab: To prevent crashes, a message is shown instead of the real interface if a metric refresh is ongoing * Changed Pace- and HR-Tabs to use inline editing * Moved the unittests into the same structure as the sourcecode * Added a simple (incomplete) unittest for kphToPace * Improved setting the column width * En-/Disabling the action buttons (add, delete, ...) based on the contents state * Changed the layout to prevent jumping widgets when showing / hiding buttons * Fixed compiler warnings from Visual-C++ * Adopt dialog: Refined layout * Fixed the unit of "From BPM" on HR-Page * Set the default mode to manual Fixes #1381
This commit is contained in:
committed by
GitHub
parent
d6e570ce3c
commit
a5829c5c13
@@ -471,7 +471,7 @@ AthleteDirectoryStructure::upgradedDirectoriesHaveData() {
|
||||
}
|
||||
|
||||
QList<PDEstimate>
|
||||
Athlete::getPDEstimates()
|
||||
Athlete::getPDEstimates() const
|
||||
{
|
||||
// returns whatever estimator has, if not running
|
||||
QList<PDEstimate> returning;
|
||||
@@ -592,13 +592,37 @@ Athlete::getPMCFor(Leaf *expr, DataFilterRuntime *df, int stsdays, int ltsdays)
|
||||
}
|
||||
|
||||
PDEstimate
|
||||
Athlete::getPDEstimateFor(QDate date, QString model, bool wpk, QString sport)
|
||||
Athlete::getPDEstimateFor(QDate date, QString model, bool wpk, QString sport) const
|
||||
{
|
||||
// whats the estimate for this date
|
||||
foreach(PDEstimate est, getPDEstimates()) {
|
||||
if (est.model == model && est.wpk == wpk && est.sport == sport && est.from <= date && est.to >= date)
|
||||
if (est.model == model && est.wpk == wpk && est.sport == sport && est.from <= date && est.to >= date) {
|
||||
return est;
|
||||
}
|
||||
}
|
||||
return PDEstimate();
|
||||
}
|
||||
|
||||
|
||||
PDEstimate
|
||||
Athlete::getPDEstimateClosestFor
|
||||
(QDate date, QString model, bool wpk, QString sport) const
|
||||
{
|
||||
qint64 dist = INT64_MAX;
|
||||
PDEstimate ret;
|
||||
foreach (PDEstimate est, getPDEstimates()) {
|
||||
if (est.model != model || est.wpk != wpk || est.sport != sport) {
|
||||
continue;
|
||||
}
|
||||
if (est.from <= date && date <= est.to) {
|
||||
return est;
|
||||
} else if (date < est.from && dist > date.daysTo(est.from)) {
|
||||
dist = date.daysTo(est.from);
|
||||
ret = est;
|
||||
} else if (est.to < date && dist > est.to.daysTo(date)) {
|
||||
dist = est.to.daysTo(date);
|
||||
ret = est;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -100,8 +100,9 @@ class Athlete : public QObject
|
||||
CloudServiceAutoDownload *cloudAutoDownload;
|
||||
|
||||
// Estimates
|
||||
PDEstimate getPDEstimateFor(QDate, QString model, bool wpk, QString sport);
|
||||
QList<PDEstimate> getPDEstimates();
|
||||
PDEstimate getPDEstimateFor(QDate, QString model, bool wpk, QString sport) const;
|
||||
PDEstimate getPDEstimateClosestFor(QDate date, QString model, bool wpk, QString sport) const;
|
||||
QList<PDEstimate> getPDEstimates() const;
|
||||
|
||||
// PMC Data
|
||||
PMCData *getPMCFor(QString metricName, int stsDays = -1, int ltsDays = -1); // no Specification used!
|
||||
|
||||
@@ -289,6 +289,7 @@
|
||||
#define GC_CRANKLENGTH "<athlete-preferences>crankLength"
|
||||
#define GC_WHEELSIZE "<athlete-preferences>wheelsize"
|
||||
#define GC_USE_CP_FOR_FTP "<athlete-preferences>cp/useforftp" // use CP for FTP
|
||||
#define GC_USE_CP_MODEL "<athlete-preferences>cp/useModel"
|
||||
#define GC_NETWORKFILESTORE_FOLDER "<athlete-preferences>networkfilestore/folder" // folder to sync with
|
||||
#define GC_AUTOBACKUP_FOLDER "<athlete-preferences>autobackup/folder"
|
||||
#define GC_AUTOBACKUP_PERIOD "<athlete-preferences>autobackup/period" // how often is the Athlete Folder backuped up / 0 == never
|
||||
|
||||
@@ -19,18 +19,18 @@
|
||||
#include "Units.h"
|
||||
#include <cmath>
|
||||
|
||||
QString kphToPace(double kph, bool metric, bool isSwim)
|
||||
QTime kphToPaceTime(double kph, bool metric, bool isSwim)
|
||||
{
|
||||
// return a min/mile or min/kph string
|
||||
if (!metric && !isSwim) kph /= KM_PER_MILE;
|
||||
|
||||
// stop silly stuff
|
||||
if (kph < 0.1) {
|
||||
return "00:00";
|
||||
return QTime(0, 0, 0);
|
||||
}
|
||||
|
||||
if (kph > 99) {
|
||||
return "xx:xx";
|
||||
return QTime();
|
||||
}
|
||||
|
||||
// Swim pace is min/100m or min/100y
|
||||
@@ -47,9 +47,16 @@ QString kphToPace(double kph, bool metric, bool isSwim)
|
||||
minutes++;
|
||||
}
|
||||
|
||||
return QString("%1:%2")
|
||||
.arg(minutes, 2, 10, QLatin1Char('0'))
|
||||
.arg(seconds, 2, 10, QLatin1Char('0'));
|
||||
return QTime(0, minutes, seconds);
|
||||
}
|
||||
|
||||
QString kphToPace(double kph, bool metric, bool isSwim)
|
||||
{
|
||||
QTime time = kphToPaceTime(kph, metric, isSwim);
|
||||
if (! time.isValid()) {
|
||||
return "xx:xx";
|
||||
}
|
||||
return time.toString("mm:ss");
|
||||
}
|
||||
|
||||
QString mphToPace(double mph, bool metric, bool isSwim)
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
#ifndef _GC_Units_h
|
||||
#define _GC_Units_h 1
|
||||
#include "GoldenCheetah.h"
|
||||
|
||||
#define KM_PER_MILE 1.609344f
|
||||
#define MILES_PER_KM 0.62137119f
|
||||
@@ -41,8 +40,10 @@
|
||||
#define MS_IN_WKO_HOURS 360000 // yes this number of ms is required to match for WKO
|
||||
|
||||
#include <QString>
|
||||
#include <QTime>
|
||||
|
||||
extern QTime kphToPaceTime(double kph, bool metric, bool isSwim=false);
|
||||
extern QString kphToPace(double kph, bool metric, bool isSwim=false);
|
||||
extern QString mphToPace(double mph, bool metric, bool isSwim=false);
|
||||
|
||||
#endif // _GC_Units_h
|
||||
|
||||
|
||||
@@ -163,12 +163,20 @@ AthleteConfig::AthleteConfig(QDir home, Context *context) :
|
||||
|
||||
QWidget *zc = new QWidget(this);
|
||||
QVBoxLayout *zl = new QVBoxLayout(zc);
|
||||
QTabWidget *zonesTab = new QTabWidget(this);
|
||||
zl->addWidget(zonesTab);
|
||||
zonesTab->setContentsMargins(10*dpiXFactor,10*dpiXFactor,10*dpiXFactor,10*dpiXFactor);
|
||||
zonesTab->addTab(zonePage, tr("Power"));
|
||||
zonesTab->addTab(hrZonePage, tr("Heartrate"));
|
||||
zonesTab->addTab(paceZonePage, tr("Pace"));
|
||||
QTabWidget *zonesTab = nullptr;
|
||||
if (context->athlete->rideCache->isRunning()) {
|
||||
QLabel *warn = new QLabel(QString("<center><h1>%1</h1>%2</center>")
|
||||
.arg(tr("Refresh in Progress"))
|
||||
.arg(tr("A metric refresh is currently running, please try again once that has completed.")));
|
||||
zl->addWidget(warn, 0, Qt::AlignCenter);
|
||||
} else {
|
||||
zonesTab = new QTabWidget(this);
|
||||
zl->addWidget(zonesTab);
|
||||
zonesTab->setContentsMargins(10*dpiXFactor,10*dpiXFactor,10*dpiXFactor,10*dpiXFactor);
|
||||
zonesTab->addTab(zonePage, tr("Power"));
|
||||
zonesTab->addTab(hrZonePage, tr("Heartrate"));
|
||||
zonesTab->addTab(paceZonePage, tr("Pace"));
|
||||
}
|
||||
|
||||
// if the plot background and window background
|
||||
// are the same color, lets use the accent color since
|
||||
@@ -196,7 +204,9 @@ AthleteConfig::AthleteConfig(QDir home, Context *context) :
|
||||
.arg(2*dpiXFactor) // 4 padding
|
||||
.arg(75*dpiXFactor) // 5 tab minimum width
|
||||
.arg(std.color(QPalette::Text).name()); // 6 tab text color
|
||||
zonesTab->setStyleSheet(styling);
|
||||
if (zonesTab != nullptr) {
|
||||
zonesTab->setStyleSheet(styling);
|
||||
}
|
||||
measuresTab->setStyleSheet(styling);
|
||||
#endif
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -51,6 +51,7 @@
|
||||
#include "RideAutoImportConfig.h"
|
||||
#include "RemoteControl.h"
|
||||
#include "Measures.h"
|
||||
#include "StyledItemDelegates.h"
|
||||
|
||||
class MeasuresPage : public QWidget
|
||||
{
|
||||
@@ -222,69 +223,122 @@ class CredentialsPage : public QScrollArea
|
||||
class SchemePage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
G_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
SchemePage(Zones *zones);
|
||||
|
||||
ZoneScheme getScheme();
|
||||
qint32 saveClicked();
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void addClicked();
|
||||
void deleteClicked();
|
||||
void renameClicked();
|
||||
void updateButtons();
|
||||
|
||||
private:
|
||||
Zones *zones;
|
||||
QTreeWidget *scheme;
|
||||
QPushButton *addButton, *renameButton, *deleteButton;
|
||||
QPushButton *addButton, *deleteButton;
|
||||
SpinBoxEditDelegate zoneFromDelegate;
|
||||
};
|
||||
|
||||
|
||||
// Compatibility helper for Qt5
|
||||
// exposes methods that turned public in Qt6 from protected in Qt5
|
||||
#if QT_VERSION < 0x060000
|
||||
class TreeWidget6 : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TreeWidget6(QWidget *parent = nullptr): QTreeWidget(parent) {
|
||||
}
|
||||
|
||||
QModelIndex indexFromItem(const QTreeWidgetItem *item, int column = 0) const {
|
||||
return QTreeWidget::indexFromItem(item, column);
|
||||
}
|
||||
|
||||
QTreeWidgetItem* itemFromIndex(const QModelIndex &index) const {
|
||||
return QTreeWidget::itemFromIndex(index);
|
||||
}
|
||||
|
||||
};
|
||||
#else
|
||||
typedef QTreeWidget TreeWidget6;
|
||||
#endif
|
||||
|
||||
|
||||
class CPPage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
G_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
CPPage(Context *context, Zones *zones, SchemePage *schemePage);
|
||||
QComboBox *useCPForFTPCombo;
|
||||
|
||||
qint32 saveClicked();
|
||||
|
||||
struct {
|
||||
int cpforftp;
|
||||
} b4;
|
||||
QComboBox *useModel;
|
||||
QComboBox *useCPForFTPCombo;
|
||||
|
||||
struct {
|
||||
int modelIdx;
|
||||
int cpforftp;
|
||||
} b4;
|
||||
|
||||
public slots:
|
||||
void addClicked();
|
||||
void editClicked();
|
||||
void deleteClicked();
|
||||
void defaultClicked();
|
||||
void rangeEdited();
|
||||
void rangeSelectionChanged();
|
||||
void addZoneClicked();
|
||||
void deleteZoneClicked();
|
||||
void zonesChanged();
|
||||
void initializeRanges();
|
||||
|
||||
private slots:
|
||||
#if QT_VERSION < 0x060000
|
||||
void rangeChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>());
|
||||
#else
|
||||
void rangeChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles = QList<int>());
|
||||
#endif
|
||||
|
||||
void adopt();
|
||||
void updateButtons();
|
||||
|
||||
private:
|
||||
bool active;
|
||||
|
||||
QDateEdit *dateEdit;
|
||||
QDoubleSpinBox *cpEdit;
|
||||
QDoubleSpinBox *aetEdit;
|
||||
QDoubleSpinBox *ftpEdit;
|
||||
QDoubleSpinBox *wEdit;
|
||||
QDoubleSpinBox *pmaxEdit;
|
||||
DateEditDelegate dateDelegate;
|
||||
SpinBoxEditDelegate cpDelegate;
|
||||
SpinBoxEditDelegate aetDelegate;
|
||||
SpinBoxEditDelegate ftpDelegate;
|
||||
SpinBoxEditDelegate wDelegate;
|
||||
SpinBoxEditDelegate pmaxDelegate;
|
||||
NoEditDelegate statusDelegate;
|
||||
|
||||
SpinBoxEditDelegate zoneFromDelegate;
|
||||
|
||||
Context *context;
|
||||
Zones *zones_;
|
||||
SchemePage *schemePage;
|
||||
QTreeWidget *ranges;
|
||||
TreeWidget6 *ranges;
|
||||
QTreeWidget *zones;
|
||||
QPushButton *addButton, *updateButton, *deleteButton;
|
||||
QPushButton *addButton, *deleteButton;
|
||||
QPushButton *adoptButton;
|
||||
QPushButton *addZoneButton, *deleteZoneButton, *defaultButton;
|
||||
QPushButton *newZoneRequired;
|
||||
|
||||
bool getValuesFor(const QDate &date, bool allowDefaults, int &cp, int &aetp, int &ftp, int &wprime, int &pmax, int &estOffset, bool &defaults, QDate *startDate = nullptr) const;
|
||||
void setEstimateStatus(QTreeWidgetItem *item);
|
||||
void setRangeData(QModelIndex modelIndex, int column, QVariant data);
|
||||
bool needsNewRange() const;
|
||||
void mkAdoptionRow(QGridLayout *grid, int row, int labelId, const QString &unit, int cur, int est, QCheckBox *&accept, const QString &infoText = QString()) const;
|
||||
void connectAdoptionDialogApplyButton(QVector<QCheckBox*> checkboxes, QPushButton *applyButton) const;
|
||||
bool modelHasFtp() const;
|
||||
bool modelHasPmax() const;
|
||||
QWidget *mkInfoLabel(int labelId, const QString &infoText = QString()) const;
|
||||
QString getText(int id, int value = 0) const;
|
||||
bool addDialogManual(QDate &date, int &cp, int &aetp, int &wprime, int &ftp, int &pmax) const;
|
||||
};
|
||||
|
||||
class ZonePage : public QWidget
|
||||
@@ -324,93 +378,89 @@ class ZonePage : public QWidget
|
||||
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Heartrate Zones
|
||||
//
|
||||
class HrSchemePage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
G_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
HrSchemePage(HrZones *hrZones);
|
||||
|
||||
HrZoneScheme getScheme();
|
||||
qint32 saveClicked();
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void addClicked();
|
||||
void deleteClicked();
|
||||
void renameClicked();
|
||||
void updateButtons();
|
||||
|
||||
private:
|
||||
HrZones *hrZones;
|
||||
QTreeWidget *scheme;
|
||||
QPushButton *addButton, *renameButton, *deleteButton;
|
||||
QPushButton *addButton, *deleteButton;
|
||||
|
||||
SpinBoxEditDelegate ltDelegate;
|
||||
DoubleSpinBoxEditDelegate trimpkDelegate;
|
||||
};
|
||||
|
||||
|
||||
class LTPage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
G_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
LTPage(Context *context, HrZones *hrZones, HrSchemePage *schemePage);
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void addClicked();
|
||||
void editClicked();
|
||||
void deleteClicked();
|
||||
void defaultClicked();
|
||||
void rangeEdited();
|
||||
void rangeChanged(const QModelIndex &modelIndex);
|
||||
void rangeSelectionChanged();
|
||||
void addZoneClicked();
|
||||
void deleteZoneClicked();
|
||||
void zonesChanged();
|
||||
void updateButtons();
|
||||
|
||||
private:
|
||||
bool active;
|
||||
|
||||
QDateEdit *dateEdit;
|
||||
QDoubleSpinBox *ltEdit;
|
||||
QDoubleSpinBox *aetEdit;
|
||||
QDoubleSpinBox *restHrEdit;
|
||||
QDoubleSpinBox *maxHrEdit;
|
||||
DateEditDelegate dateDelegate;
|
||||
SpinBoxEditDelegate ltDelegate;
|
||||
SpinBoxEditDelegate aetDelegate;
|
||||
SpinBoxEditDelegate restHrDelegate;
|
||||
SpinBoxEditDelegate maxHrDelegate;
|
||||
|
||||
SpinBoxEditDelegate zoneLoDelegate;
|
||||
DoubleSpinBoxEditDelegate zoneTrimpDelegate;
|
||||
|
||||
Context *context;
|
||||
HrZones *hrZones;
|
||||
HrSchemePage *schemePage;
|
||||
QTreeWidget *ranges;
|
||||
QTreeWidget *zones;
|
||||
QPushButton *addButton, *updateButton, *deleteButton;
|
||||
QPushButton *addButton, *deleteButton;
|
||||
QPushButton *addZoneButton, *deleteZoneButton, *defaultButton;
|
||||
};
|
||||
|
||||
class HrZonePage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
G_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
|
||||
HrZonePage(Context *);
|
||||
~HrZonePage();
|
||||
qint32 saveClicked();
|
||||
|
||||
public slots:
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
Context *context;
|
||||
|
||||
QTabWidget *tabs;
|
||||
|
||||
private:
|
||||
|
||||
QLabel *sportLabel;
|
||||
QComboBox *sportCombo;
|
||||
|
||||
@@ -420,7 +470,6 @@ class HrZonePage : public QWidget
|
||||
QHash<QString, LTPage*> ltPage;
|
||||
|
||||
private slots:
|
||||
|
||||
void changeSport();
|
||||
|
||||
};
|
||||
@@ -431,58 +480,63 @@ class HrZonePage : public QWidget
|
||||
class PaceSchemePage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
G_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
PaceSchemePage(PaceZones* paceZones);
|
||||
|
||||
PaceZoneScheme getScheme();
|
||||
qint32 saveClicked();
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void addClicked();
|
||||
void deleteClicked();
|
||||
void renameClicked();
|
||||
void updateButtons();
|
||||
|
||||
private:
|
||||
PaceZones* paceZones;
|
||||
QTreeWidget *scheme;
|
||||
QPushButton *addButton, *renameButton, *deleteButton;
|
||||
QPushButton *addButton, *deleteButton;
|
||||
SpinBoxEditDelegate fromDelegate;
|
||||
};
|
||||
|
||||
class CVPage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
G_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
CVPage(PaceZones* paceZones, PaceSchemePage *schemePage);
|
||||
|
||||
bool metricPace;
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void addClicked();
|
||||
void editClicked();
|
||||
void deleteClicked();
|
||||
void defaultClicked();
|
||||
void rangeEdited();
|
||||
#if QT_VERSION < 0x060000
|
||||
void rangeChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>());
|
||||
#else
|
||||
void rangeChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList<int> &roles = QList<int>());
|
||||
#endif
|
||||
void rangeSelectionChanged();
|
||||
void addZoneClicked();
|
||||
void deleteZoneClicked();
|
||||
void zonesChanged();
|
||||
void updateButtons();
|
||||
|
||||
private:
|
||||
bool active;
|
||||
|
||||
QDateEdit *dateEdit;
|
||||
QTimeEdit *cvEdit;
|
||||
QTimeEdit *aetEdit;
|
||||
DateEditDelegate dateDelegate;
|
||||
TimeEditDelegate cvDelegate;
|
||||
TimeEditDelegate aetDelegate;
|
||||
|
||||
TimeEditDelegate zoneFromDelegate;
|
||||
|
||||
PaceZones* paceZones;
|
||||
PaceSchemePage *schemePage;
|
||||
QTreeWidget *ranges;
|
||||
QTreeWidget *zones;
|
||||
QPushButton *addButton, *updateButton, *deleteButton;
|
||||
QPushButton *addButton, *deleteButton;
|
||||
QPushButton *addZoneButton, *deleteZoneButton, *defaultButton;
|
||||
QLabel *per;
|
||||
};
|
||||
@@ -601,4 +655,6 @@ class AutoImportPage : public QWidget
|
||||
|
||||
};
|
||||
|
||||
extern void basicTreeWidgetStyle(QTreeWidget *tree);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "StyledItemDelegates.h"
|
||||
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QDateEdit>
|
||||
|
||||
|
||||
// NoEditDelegate /////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -49,3 +52,503 @@ UniqueLabelEditDelegate::setModelData
|
||||
model->setData(index, newData, Qt::EditRole);
|
||||
model->setData(modifiedIndex, true, Qt::EditRole);
|
||||
}
|
||||
|
||||
|
||||
// SpinBoxEditDelegate ////////////////////////////////////////////////////////////
|
||||
|
||||
SpinBoxEditDelegate::SpinBoxEditDelegate
|
||||
(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpinBoxEditDelegate::setMininum
|
||||
(int minimum)
|
||||
{
|
||||
this->minimum = minimum;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpinBoxEditDelegate::setMaximum
|
||||
(int maximum)
|
||||
{
|
||||
this->maximum = maximum;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpinBoxEditDelegate::setRange
|
||||
(int minimum, int maximum)
|
||||
{
|
||||
this->minimum = minimum;
|
||||
this->maximum = maximum;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpinBoxEditDelegate::setSingleStep
|
||||
(int val)
|
||||
{
|
||||
singleStep = val;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpinBoxEditDelegate::setSuffix
|
||||
(const QString &suffix)
|
||||
{
|
||||
this->suffix = suffix;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpinBoxEditDelegate::setShowSuffixOnEdit
|
||||
(bool show)
|
||||
{
|
||||
showSuffixOnEdit = show;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpinBoxEditDelegate::setShowSuffixOnDisplay
|
||||
(bool show)
|
||||
{
|
||||
showSuffixOnDisplay = show;
|
||||
}
|
||||
|
||||
|
||||
QWidget*
|
||||
SpinBoxEditDelegate::createEditor
|
||||
(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(index)
|
||||
|
||||
QSpinBox *spinbox = new QSpinBox(parent);
|
||||
spinbox->setRange(minimum, maximum);
|
||||
spinbox->setSingleStep(singleStep);
|
||||
if (suffix.length() > 0) {
|
||||
spinbox->setSuffix(" " + suffix);
|
||||
} else {
|
||||
spinbox->setSuffix("");
|
||||
}
|
||||
|
||||
return spinbox;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpinBoxEditDelegate::setEditorData
|
||||
(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
int value = index.model()->data(index, Qt::EditRole).toInt();
|
||||
QSpinBox *spinbox = static_cast<QSpinBox*>(editor);
|
||||
spinbox->setValue(value);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SpinBoxEditDelegate::setModelData
|
||||
(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||
{
|
||||
QSpinBox *spinbox = static_cast<QSpinBox*>(editor);
|
||||
spinbox->interpretText();
|
||||
int newValue = spinbox->value();
|
||||
if (model->data(index, Qt::EditRole).toInt() != newValue) {
|
||||
model->setData(index, newValue, Qt::EditRole);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
SpinBoxEditDelegate::displayText
|
||||
(const QVariant &value, const QLocale &locale) const
|
||||
{
|
||||
Q_UNUSED(locale)
|
||||
|
||||
QString ret = QString::number(value.toInt());
|
||||
if (showSuffixOnDisplay && ! suffix.isEmpty()) {
|
||||
ret += " " + suffix;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
QSize
|
||||
SpinBoxEditDelegate::sizeHint
|
||||
(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(index)
|
||||
|
||||
QSpinBox widget;
|
||||
if ((showSuffixOnEdit || showSuffixOnDisplay) && ! suffix.isEmpty()) {
|
||||
widget.setSuffix(" " + suffix);
|
||||
}
|
||||
widget.setMaximum(maximum);
|
||||
widget.setValue(maximum);
|
||||
return widget.sizeHint();
|
||||
}
|
||||
|
||||
|
||||
// DoubleSpinBoxEditDelegate //////////////////////////////////////////////////////
|
||||
|
||||
DoubleSpinBoxEditDelegate::DoubleSpinBoxEditDelegate
|
||||
(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DoubleSpinBoxEditDelegate::setMininum
|
||||
(double minimum)
|
||||
{
|
||||
this->minimum = minimum;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DoubleSpinBoxEditDelegate::setMaximum
|
||||
(double maximum)
|
||||
{
|
||||
this->maximum = maximum;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DoubleSpinBoxEditDelegate::setRange
|
||||
(double minimum, double maximum)
|
||||
{
|
||||
this->minimum = minimum;
|
||||
this->maximum = maximum;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DoubleSpinBoxEditDelegate::setSingleStep
|
||||
(double val)
|
||||
{
|
||||
singleStep = val;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DoubleSpinBoxEditDelegate::setDecimals
|
||||
(int prec)
|
||||
{
|
||||
this->prec = prec;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DoubleSpinBoxEditDelegate::setSuffix
|
||||
(const QString &suffix)
|
||||
{
|
||||
this->suffix = suffix;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DoubleSpinBoxEditDelegate::setShowSuffixOnEdit
|
||||
(bool show)
|
||||
{
|
||||
showSuffixOnEdit = show;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DoubleSpinBoxEditDelegate::setShowSuffixOnDisplay
|
||||
(bool show)
|
||||
{
|
||||
showSuffixOnDisplay = show;
|
||||
}
|
||||
|
||||
|
||||
QWidget*
|
||||
DoubleSpinBoxEditDelegate::createEditor
|
||||
(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(index)
|
||||
|
||||
QDoubleSpinBox *spinbox = new QDoubleSpinBox(parent);
|
||||
spinbox->setRange(minimum, maximum);
|
||||
spinbox->setSingleStep(singleStep);
|
||||
spinbox->setDecimals(prec);
|
||||
if (suffix.length() > 0) {
|
||||
spinbox->setSuffix(" " + suffix);
|
||||
} else {
|
||||
spinbox->setSuffix("");
|
||||
}
|
||||
|
||||
return spinbox;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DoubleSpinBoxEditDelegate::setEditorData
|
||||
(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
double value = index.model()->data(index, Qt::EditRole).toDouble();
|
||||
QDoubleSpinBox *spinbox = static_cast<QDoubleSpinBox*>(editor);
|
||||
spinbox->setValue(value);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DoubleSpinBoxEditDelegate::setModelData
|
||||
(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||
{
|
||||
QDoubleSpinBox *spinbox = static_cast<QDoubleSpinBox*>(editor);
|
||||
spinbox->interpretText();
|
||||
double newValue = spinbox->value();
|
||||
if (model->data(index, Qt::EditRole).toDouble() != newValue) {
|
||||
model->setData(index, newValue, Qt::EditRole);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
DoubleSpinBoxEditDelegate::displayText
|
||||
(const QVariant &value, const QLocale &locale) const
|
||||
{
|
||||
Q_UNUSED(locale)
|
||||
|
||||
QString ret = QString::number(value.toDouble(), 'f', prec);
|
||||
if (showSuffixOnDisplay && ! suffix.isEmpty()) {
|
||||
ret += " " + suffix;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
QSize
|
||||
DoubleSpinBoxEditDelegate::sizeHint
|
||||
(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(index)
|
||||
|
||||
QDoubleSpinBox widget;
|
||||
if ((showSuffixOnEdit || showSuffixOnDisplay) && ! suffix.isEmpty()) {
|
||||
widget.setSuffix(" " + suffix);
|
||||
}
|
||||
widget.setMaximum(maximum);
|
||||
widget.setValue(maximum);
|
||||
widget.setDecimals(prec);
|
||||
return widget.sizeHint();
|
||||
}
|
||||
|
||||
|
||||
// DateEditDelegate ///////////////////////////////////////////////////////////////
|
||||
|
||||
DateEditDelegate::DateEditDelegate
|
||||
(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DateEditDelegate::setCalendarPopup
|
||||
(bool enable)
|
||||
{
|
||||
calendarPopup = enable;
|
||||
}
|
||||
|
||||
|
||||
QWidget*
|
||||
DateEditDelegate::createEditor
|
||||
(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(index)
|
||||
|
||||
QDateEdit *dateEdit = new QDateEdit(parent);
|
||||
dateEdit->setCalendarPopup(calendarPopup);
|
||||
|
||||
return dateEdit;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DateEditDelegate::setEditorData
|
||||
(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
QDate value = index.model()->data(index, Qt::EditRole).toDate();
|
||||
QDateEdit *dateEdit = static_cast<QDateEdit*>(editor);
|
||||
dateEdit->setDate(value);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DateEditDelegate::setModelData
|
||||
(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||
{
|
||||
QDateEdit *dateEdit = static_cast<QDateEdit*>(editor);
|
||||
QDate newValue = dateEdit->date();
|
||||
if (model->data(index, Qt::EditRole).toDate() != newValue) {
|
||||
model->setData(index, newValue, Qt::EditRole);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
DateEditDelegate::displayText
|
||||
(const QVariant &value, const QLocale &locale) const
|
||||
{
|
||||
return value.toDate().toString(locale.dateFormat(QLocale::ShortFormat));
|
||||
}
|
||||
|
||||
|
||||
QSize
|
||||
DateEditDelegate::sizeHint
|
||||
(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(index)
|
||||
|
||||
QDateEdit widget;
|
||||
return widget.sizeHint();
|
||||
}
|
||||
|
||||
|
||||
// TimeEditDelegate ///////////////////////////////////////////////////////////////
|
||||
|
||||
TimeEditDelegate::TimeEditDelegate
|
||||
(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TimeEditDelegate::setFormat
|
||||
(const QString &format)
|
||||
{
|
||||
this->format = format;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TimeEditDelegate::setSuffix
|
||||
(const QString &suffix)
|
||||
{
|
||||
this->suffix = suffix;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TimeEditDelegate::setShowSuffixOnEdit
|
||||
(bool show)
|
||||
{
|
||||
showSuffixOnEdit = show;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TimeEditDelegate::setShowSuffixOnDisplay
|
||||
(bool show)
|
||||
{
|
||||
showSuffixOnDisplay = show;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TimeEditDelegate::setTimeRange
|
||||
(const QTime &min, const QTime &max)
|
||||
{
|
||||
this->min = min;
|
||||
this->max = max;
|
||||
}
|
||||
|
||||
|
||||
QWidget*
|
||||
TimeEditDelegate::createEditor
|
||||
(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(index)
|
||||
|
||||
QTimeEdit *timeEdit = new QTimeEdit(parent);
|
||||
QString f = format;
|
||||
if (f.isEmpty()) {
|
||||
f = "mm:ss";
|
||||
}
|
||||
if (showSuffixOnEdit && ! suffix.isEmpty()) {
|
||||
f += " '" + suffix + "'";
|
||||
}
|
||||
timeEdit->setDisplayFormat(f);
|
||||
if (min.isValid()) {
|
||||
timeEdit->setMinimumTime(min);
|
||||
}
|
||||
if (max.isValid()) {
|
||||
timeEdit->setMaximumTime(max);
|
||||
}
|
||||
|
||||
return timeEdit;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TimeEditDelegate::setEditorData
|
||||
(QWidget *editor, const QModelIndex &index) const
|
||||
{
|
||||
QTimeEdit *timeEdit = static_cast<QTimeEdit*>(editor);
|
||||
timeEdit->setTime(index.data(Qt::DisplayRole).toTime());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TimeEditDelegate::setModelData
|
||||
(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
|
||||
{
|
||||
QTimeEdit *timeEdit = static_cast<QTimeEdit*>(editor);
|
||||
QTime newValue = timeEdit->time();
|
||||
if (model->data(index, Qt::EditRole).toTime() != newValue) {
|
||||
model->setData(index, newValue, Qt::EditRole);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
TimeEditDelegate::displayText
|
||||
(const QVariant &value, const QLocale &locale) const
|
||||
{
|
||||
Q_UNUSED(locale)
|
||||
|
||||
QString f = format;
|
||||
if (f.isEmpty()) {
|
||||
f = "mm:ss";
|
||||
}
|
||||
if (showSuffixOnDisplay && ! suffix.isEmpty()) {
|
||||
f += " '" + suffix + "'";
|
||||
}
|
||||
|
||||
return value.toTime().toString(f);
|
||||
}
|
||||
|
||||
|
||||
QSize
|
||||
TimeEditDelegate::sizeHint
|
||||
(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(index)
|
||||
|
||||
QTimeEdit widget;
|
||||
widget.setTime(QTime(0, 0, 0));
|
||||
QString f = format;
|
||||
if (f.isEmpty()) {
|
||||
f = "mm:ss";
|
||||
}
|
||||
if ((showSuffixOnEdit || showSuffixOnDisplay) && ! suffix.isEmpty()) {
|
||||
f += " '" + suffix + "'";
|
||||
}
|
||||
widget.setDisplayFormat(f);
|
||||
return widget.sizeHint();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define STYLEDITEMSDELEGATES_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QTime>
|
||||
|
||||
|
||||
class NoEditDelegate: public QStyledItemDelegate
|
||||
@@ -25,4 +26,113 @@ private:
|
||||
int uniqueColumn;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SpinBoxEditDelegate: public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
SpinBoxEditDelegate(QObject *parent = nullptr);
|
||||
|
||||
void setMininum(int minimum);
|
||||
void setMaximum(int maximum);
|
||||
void setRange(int minimum, int maximum);
|
||||
void setSingleStep(int val);
|
||||
void setSuffix(const QString &suffix);
|
||||
void setShowSuffixOnEdit(bool show);
|
||||
void setShowSuffixOnDisplay(bool show);
|
||||
|
||||
virtual QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||
virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||
virtual QString displayText(const QVariant &value, const QLocale &locale) const override;
|
||||
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
int minimum = 0;
|
||||
int maximum = 100;
|
||||
int singleStep = 1;
|
||||
QString suffix;
|
||||
bool showSuffixOnEdit = true;
|
||||
bool showSuffixOnDisplay = true;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DoubleSpinBoxEditDelegate: public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
DoubleSpinBoxEditDelegate(QObject *parent = nullptr);
|
||||
|
||||
void setMininum(double minimum);
|
||||
void setMaximum(double maximum);
|
||||
void setRange(double minimum, double maximum);
|
||||
void setSingleStep(double val);
|
||||
void setDecimals(int prec);
|
||||
void setSuffix(const QString &suffix);
|
||||
void setShowSuffixOnEdit(bool show);
|
||||
void setShowSuffixOnDisplay(bool show);
|
||||
|
||||
virtual QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||
virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||
virtual QString displayText(const QVariant &value, const QLocale &locale) const override;
|
||||
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
double minimum = 0;
|
||||
double maximum = 100;
|
||||
double singleStep = 1;
|
||||
double prec = 0;
|
||||
QString suffix;
|
||||
bool showSuffixOnEdit = true;
|
||||
bool showSuffixOnDisplay = true;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DateEditDelegate: public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
DateEditDelegate(QObject *parent = nullptr);
|
||||
|
||||
void setCalendarPopup(bool enable);
|
||||
|
||||
virtual QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||
virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||
virtual QString displayText(const QVariant &value, const QLocale &locale) const override;
|
||||
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
bool calendarPopup = false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class TimeEditDelegate: public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
TimeEditDelegate(QObject *parent = nullptr);
|
||||
|
||||
void setFormat(const QString &format);
|
||||
void setSuffix(const QString &suffix);
|
||||
void setShowSuffixOnEdit(bool show);
|
||||
void setShowSuffixOnDisplay(bool show);
|
||||
void setTimeRange(const QTime &min, const QTime &max);
|
||||
|
||||
virtual QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
virtual void setEditorData(QWidget *editor, const QModelIndex &index) const override;
|
||||
virtual void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;
|
||||
virtual QString displayText(const QVariant &value, const QLocale &locale) const override;
|
||||
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
QString format;
|
||||
QString suffix;
|
||||
bool showSuffixOnEdit = true;
|
||||
bool showSuffixOnDisplay = true;
|
||||
QTime min;
|
||||
QTime max;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1043,7 +1043,17 @@ PaceZones::kphFromTime(QTimeEdit *cvedit, bool metric) const
|
||||
// get the value from a time edit and convert
|
||||
// it to kph so we can store it in the zones file
|
||||
|
||||
double secs = cvedit->time().secsTo(QTime(0,0,0)) * -1;
|
||||
return kphFromTime(cvedit->time(), metric);
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
PaceZones::kphFromTime
|
||||
(const QTime &time, bool metric) const
|
||||
{
|
||||
// convert a time to kph so we can store it in the zones file
|
||||
|
||||
double secs = QTime(0, 0, 0).secsTo(time);
|
||||
if (secs == 0) return 0; // avoid division by zero
|
||||
if (swim)
|
||||
return (metric ? 1.00f : METERS_PER_YARD ) * (360.00f / secs);
|
||||
@@ -1051,12 +1061,20 @@ PaceZones::kphFromTime(QTimeEdit *cvedit, bool metric) const
|
||||
return (metric ? 1.00f : KM_PER_MILE ) * (3600.00f / secs);
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
PaceZones::kphToPaceString(double kph, bool metric) const
|
||||
{
|
||||
return kphToPace(kph, metric, swim);
|
||||
}
|
||||
|
||||
|
||||
QTime
|
||||
PaceZones::kphToPaceTime(double kph, bool metric) const
|
||||
{
|
||||
return ::kphToPaceTime(kph, metric, swim);
|
||||
}
|
||||
|
||||
QString
|
||||
PaceZones::paceUnits(bool metric) const
|
||||
{
|
||||
|
||||
@@ -216,7 +216,9 @@ class PaceZones : public QObject
|
||||
|
||||
// convert to/from Pace
|
||||
double kphFromTime(QTimeEdit *cvedit, bool metric) const;
|
||||
double kphFromTime(const QTime &time, bool metric) const;
|
||||
QString kphToPaceString(double kph, bool metric) const;
|
||||
QTime kphToPaceTime(double kph, bool metric) const;
|
||||
QString paceUnits(bool metric) const;
|
||||
QString paceSetting() const;
|
||||
static bool isPaceUnit(QString unit);
|
||||
|
||||
@@ -1123,3 +1123,9 @@ Zones::useCPforFTPSetting() const
|
||||
{
|
||||
return GC_USE_CP_FOR_FTP + ((sport_.isEmpty() || sport_ == "Bike") ? "" : sport_.toLower());
|
||||
}
|
||||
|
||||
QString
|
||||
Zones::useCPModelSetting() const
|
||||
{
|
||||
return GC_USE_CP_MODEL + ((sport_.isEmpty() || sport_ == "Bike") ? "" : sport_.toLower());
|
||||
}
|
||||
|
||||
@@ -220,6 +220,8 @@ class Zones : public QObject
|
||||
|
||||
// USE_CP_FOR_FTP setting differenciated by sport
|
||||
QString useCPforFTPSetting() const;
|
||||
|
||||
QString useCPModelSetting() const;
|
||||
};
|
||||
|
||||
QColor zoneColor(int zone, int num_zones);
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
<file>images/toolbar/main/train.png</file>
|
||||
<file>images/toolbar/clear.png</file>
|
||||
<file>images/toolbar/edit.png</file>
|
||||
<file>images/toolbar/info.png</file>
|
||||
<file>images/toolbar/select.png</file>
|
||||
<file>images/toolbar/new doc.png</file>
|
||||
<file>images/toolbar/properties.png</file>
|
||||
|
||||
@@ -4,4 +4,4 @@ SOURCES = testSeason.cpp
|
||||
GC_OBJS = Season \
|
||||
Utils
|
||||
|
||||
include(../unittests.pri)
|
||||
include(../../unittests.pri)
|
||||
@@ -3,4 +3,4 @@ QT += testlib widgets
|
||||
SOURCES = testSeasonOffset.cpp
|
||||
GC_OBJS = Season
|
||||
|
||||
include(../unittests.pri)
|
||||
include(../../unittests.pri)
|
||||
@@ -6,4 +6,4 @@ GC_OBJS = Seasons \
|
||||
Season \
|
||||
Utils
|
||||
|
||||
include(../unittests.pri)
|
||||
include(../../unittests.pri)
|
||||
56
unittests/Core/units/testUnits.cpp
Normal file
56
unittests/Core/units/testUnits.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "Core/Units.h"
|
||||
|
||||
#include <QTest>
|
||||
|
||||
|
||||
class TestUnits: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void kphToPaceTimeRunTrash() {
|
||||
QCOMPARE(kphToPaceTime(0.01, true), QTime(0, 0, 0));
|
||||
QCOMPARE(kphToPaceTime(100, true), QTime());
|
||||
QCOMPARE(kphToPaceTime(0.01, false), QTime(0, 0, 0));
|
||||
QCOMPARE(kphToPaceTime(160, false), QTime());
|
||||
}
|
||||
|
||||
void kphToPaceTimeRunMetric() {
|
||||
QCOMPARE(kphToPaceTime(30, true), QTime(0, 2, 0));
|
||||
QCOMPARE(kphToPaceTime(24, true), QTime(0, 2, 30));
|
||||
QCOMPARE(kphToPaceTime(15, true), QTime(0, 4, 0));
|
||||
QCOMPARE(kphToPaceTime(13.8, true), QTime(0, 4, 21));
|
||||
}
|
||||
|
||||
void kphToPaceTimeRunImperial() {
|
||||
QCOMPARE(kphToPaceTime(30, false), QTime(0, 3, 13));
|
||||
QCOMPARE(kphToPaceTime(24, false), QTime(0, 4, 1));
|
||||
QCOMPARE(kphToPaceTime(15, false), QTime(0, 6, 26));
|
||||
QCOMPARE(kphToPaceTime(13.8, false), QTime(0, 7, 0));
|
||||
}
|
||||
|
||||
void kphToPaceStringRunTrash() {
|
||||
QCOMPARE(kphToPace(0.01, true), "00:00");
|
||||
QCOMPARE(kphToPace(100, true), "xx:xx");
|
||||
QCOMPARE(kphToPace(0.01, false), "00:00");
|
||||
QCOMPARE(kphToPace(160, false), "xx:xx");
|
||||
}
|
||||
|
||||
void kphToPaceStringRunMetric() {
|
||||
QCOMPARE(kphToPace(30, true), "02:00");
|
||||
QCOMPARE(kphToPace(24, true), "02:30");
|
||||
QCOMPARE(kphToPace(15, true), "04:00");
|
||||
QCOMPARE(kphToPace(13.8, true), "04:21");
|
||||
}
|
||||
|
||||
void kphToPaceStringRunImperial() {
|
||||
QCOMPARE(kphToPace(30, false), "03:13");
|
||||
QCOMPARE(kphToPace(24, false), "04:01");
|
||||
QCOMPARE(kphToPace(15, false), "06:26");
|
||||
QCOMPARE(kphToPace(13.8, false), "07:00");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
QTEST_MAIN(TestUnits)
|
||||
#include "testUnits.moc"
|
||||
6
unittests/Core/units/units.pro
Normal file
6
unittests/Core/units/units.pro
Normal file
@@ -0,0 +1,6 @@
|
||||
QT += testlib core
|
||||
|
||||
SOURCES = testUnits.cpp
|
||||
GC_OBJS = Units
|
||||
|
||||
include(../../unittests.pri)
|
||||
@@ -5,7 +5,7 @@ GC_UNITTESTS = active
|
||||
|
||||
include(../src/gcconfig.pri)
|
||||
|
||||
GC_SRC_DIR = ../../src
|
||||
GC_SRC_DIR = ../../../src
|
||||
GC_OBJECTS_DIR = $$GC_SRC_DIR/$(OBJECTS_DIR)
|
||||
INCLUDEPATH += $$GC_SRC_DIR
|
||||
win32 {
|
||||
|
||||
@@ -5,9 +5,10 @@ exists(unittests.pri) {
|
||||
}
|
||||
|
||||
equals(GC_UNITTESTS, active) {
|
||||
SUBDIRS += seasonOffset \
|
||||
season \
|
||||
seasonParser
|
||||
SUBDIRS += Core/seasonOffset \
|
||||
Core/season \
|
||||
Core/seasonParser \
|
||||
Core/units
|
||||
CONFIG += ordered
|
||||
} else {
|
||||
message("Unittests are disabled; to enable copy unittests/unittests.pri.in to unittests/unittests.pri")
|
||||
|
||||
Reference in New Issue
Block a user