mirror of
https://github.com/cagnulein/qdomyos-zwift.git
synced 2026-02-18 23:41:50 +01:00
Compare commits
21 Commits
Mobi-Rower
...
build-922
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82a6afe6b6 | ||
|
|
a7b8e63235 | ||
|
|
d7c3a84adb | ||
|
|
64b9ec9d72 | ||
|
|
379cf8d7de | ||
|
|
2f2989f90d | ||
|
|
6fac9770be | ||
|
|
8d07d7c3f7 | ||
|
|
f85f743499 | ||
|
|
74c37f5624 | ||
|
|
527396eafc | ||
|
|
0f149448b3 | ||
|
|
ed1599ca8e | ||
|
|
89808ae65b | ||
|
|
2da194f073 | ||
|
|
d712621b7b | ||
|
|
1c06260036 | ||
|
|
2d1364497e | ||
|
|
cc7757bfcd | ||
|
|
49c7a96c81 | ||
|
|
05d598ffcf |
@@ -4068,7 +4068,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 919;
|
||||
CURRENT_PROJECT_VERSION = 922;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_BITCODE = NO;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = "ADB_HOST=1";
|
||||
@@ -4259,7 +4259,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = "../src/ios/qdomyos-zwift.entitlements";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
CURRENT_PROJECT_VERSION = 919;
|
||||
CURRENT_PROJECT_VERSION = 922;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -4486,7 +4486,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 919;
|
||||
CURRENT_PROJECT_VERSION = 922;
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_BITCODE = YES;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
@@ -4582,7 +4582,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 919;
|
||||
CURRENT_PROJECT_VERSION = 922;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_TEAM = 6335M7T29D;
|
||||
ENABLE_BITCODE = YES;
|
||||
@@ -4674,7 +4674,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 919;
|
||||
CURRENT_PROJECT_VERSION = 922;
|
||||
DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\"";
|
||||
ENABLE_BITCODE = YES;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
@@ -4788,7 +4788,7 @@
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "watchkit Extension/WatchKit Extension.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 919;
|
||||
CURRENT_PROJECT_VERSION = 922;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEVELOPMENT_ASSET_PATHS = "\"watchkit Extension/Preview Content\"";
|
||||
ENABLE_BITCODE = YES;
|
||||
|
||||
@@ -106,6 +106,14 @@ void bike::setGears(double gears) {
|
||||
qDebug() << "new gear value ignored because of gears_zwift_ratio setting!";
|
||||
return;
|
||||
}
|
||||
if(gears > maxGears()) {
|
||||
qDebug() << "new gear value ignored because of maxGears" << maxGears();
|
||||
return;
|
||||
}
|
||||
if(gears < minGears()) {
|
||||
qDebug() << "new gear value ignored because of minGears" << minGears();
|
||||
return;
|
||||
}
|
||||
m_gears = gears;
|
||||
if(homeform::singleton()) {
|
||||
homeform::singleton()->updateGearsValue();
|
||||
|
||||
@@ -23,6 +23,8 @@ class bike : public bluetoothdevice {
|
||||
double currentCrankRevolutions() override;
|
||||
uint16_t lastCrankEventTime() override;
|
||||
bool connected() override;
|
||||
virtual double maxGears() { return 9999.0; }
|
||||
virtual double minGears() { return -9999.0; }
|
||||
virtual uint16_t watts();
|
||||
virtual resistance_t pelotonToBikeResistance(int pelotonResistance);
|
||||
virtual resistance_t resistanceFromPowerRequest(uint16_t power);
|
||||
|
||||
@@ -1511,7 +1511,6 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
|
||||
(b.name().toUpper().startsWith(ftmsAccessoryName.toUpper()) &&
|
||||
settings.value(QZSettings::ss2k_peloton, QZSettings::default_ss2k_peloton)
|
||||
.toBool()) || // ss2k on a peloton bike
|
||||
((b.name().toUpper().startsWith("KICKR CORE")) && deviceHasService(b, QBluetoothUuid((quint16)0x1826))) ||
|
||||
(b.name().toUpper().startsWith("MERACH-MR667-")) ||
|
||||
(b.name().toUpper().startsWith("DS60-")) ||
|
||||
(b.name().toUpper().startsWith("BIKE-")) ||
|
||||
@@ -1562,6 +1561,7 @@ void bluetooth::deviceDiscovered(const QBluetoothDeviceInfo &device) {
|
||||
this->signalBluetoothDeviceConnected(ftmsBike);
|
||||
} else if ((b.name().toUpper().startsWith("KICKR SNAP") || b.name().toUpper().startsWith("KICKR BIKE") ||
|
||||
b.name().toUpper().startsWith("KICKR ROLLR") ||
|
||||
b.name().toUpper().startsWith("KICKR CORE") ||
|
||||
(b.name().toUpper().startsWith("HAMMER ") && saris_trainer) ||
|
||||
(b.name().toUpper().startsWith("WAHOO KICKR"))) &&
|
||||
!wahooKickrSnapBike && !ftmsBike && filter) {
|
||||
|
||||
@@ -31,6 +31,8 @@ wahookickrsnapbike::wahookickrsnapbike(bool noWriteResistance, bool noHeartServi
|
||||
initDone = false;
|
||||
connect(refresh, &QTimer::timeout, this, &wahookickrsnapbike::update);
|
||||
refresh->start(200ms);
|
||||
GearTable g;
|
||||
g.printTable();
|
||||
}
|
||||
|
||||
bool wahookickrsnapbike::writeCharacteristic(uint8_t *data, uint8_t data_len, QString info, bool disable_log,
|
||||
@@ -192,10 +194,16 @@ void wahookickrsnapbike::update() {
|
||||
}
|
||||
QThread::msleep(700);
|
||||
|
||||
QByteArray d = setWheelCircumference(gearsToWheelDiameter(gears()));
|
||||
uint8_t e[20];
|
||||
setGears(1);
|
||||
memcpy(e, d.constData(), d.length());
|
||||
writeCharacteristic(e, d.length(), "setWheelCircumference", false, true);
|
||||
|
||||
// required to the SS2K only one time
|
||||
Resistance = 0;
|
||||
emit resistanceRead(Resistance.value());
|
||||
initRequest = false;
|
||||
initRequest = false;
|
||||
} else if (bluetoothDevice.isValid() &&
|
||||
m_control->state() == QLowEnergyController::DiscoveredState //&&
|
||||
// gattCommunicationChannelService &&
|
||||
@@ -259,7 +267,10 @@ void wahookickrsnapbike::update() {
|
||||
memcpy(b, a.constData(), a.length());
|
||||
writeCharacteristic(b, a.length(), "setResistance", false, true);
|
||||
} else if (virtualBike && virtualBike->ftmsDeviceConnected() && lastGearValue != gears()) {
|
||||
inclinationChanged(lastGrade, lastGrade);
|
||||
QByteArray a = setWheelCircumference(gearsToWheelDiameter(gears()));
|
||||
uint8_t b[20];
|
||||
memcpy(b, a.constData(), a.length());
|
||||
writeCharacteristic(b, a.length(), "setWheelCircumference", false, true);
|
||||
}
|
||||
lastGearValue = gears();
|
||||
requestResistance = -1;
|
||||
@@ -280,6 +291,17 @@ void wahookickrsnapbike::update() {
|
||||
}
|
||||
}
|
||||
|
||||
double wahookickrsnapbike::gearsToWheelDiameter(double gear) {
|
||||
QSettings settings;
|
||||
GearTable table;
|
||||
if(gear < 1) gear = 1;
|
||||
else if(gear > table.maxGears) gear = table.maxGears;
|
||||
double original_ratio = ((double)settings.value(QZSettings::gear_crankset_size, QZSettings::default_gear_crankset_size).toDouble()) / ((double)settings.value(QZSettings::gear_cog_size, QZSettings::default_gear_cog_size).toDouble());
|
||||
GearTable::GearInfo g = table.getGear((int)gear);
|
||||
double current_ratio = ((double)g.crankset / (double)g.rearCog);
|
||||
return (((double)settings.value(QZSettings::gear_circumference, QZSettings::default_gear_circumference).toDouble()) / original_ratio) * ((double)current_ratio);
|
||||
}
|
||||
|
||||
void wahookickrsnapbike::serviceDiscovered(const QBluetoothUuid &gatt) {
|
||||
emit debug(QStringLiteral("serviceDiscovered ") + gatt.toString());
|
||||
}
|
||||
@@ -823,7 +845,6 @@ void wahookickrsnapbike::inclinationChanged(double grade, double percentage) {
|
||||
emit debug(QStringLiteral("writing inclination ") + QString::number(grade));
|
||||
QSettings settings;
|
||||
double g = grade;
|
||||
g += gears();
|
||||
QByteArray a = setSimGrade(g);
|
||||
uint8_t b[20];
|
||||
memcpy(b, a.constData(), a.length());
|
||||
@@ -833,3 +854,12 @@ void wahookickrsnapbike::inclinationChanged(double grade, double percentage) {
|
||||
bool wahookickrsnapbike::inclinationAvailableByHardware() {
|
||||
return KICKR_BIKE;
|
||||
}
|
||||
|
||||
double wahookickrsnapbike::maxGears() {
|
||||
GearTable g;
|
||||
return g.maxGears;
|
||||
}
|
||||
|
||||
double wahookickrsnapbike::minGears() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ class wahookickrsnapbike : public bike {
|
||||
bool connected() override;
|
||||
resistance_t maxResistance() override { return 100; }
|
||||
bool inclinationAvailableByHardware() override;
|
||||
double maxGears() override;
|
||||
double minGears() override;
|
||||
|
||||
enum OperationCode : uint8_t {
|
||||
_unlock = 32,
|
||||
@@ -56,7 +58,7 @@ class wahookickrsnapbike : public bike {
|
||||
_setWheelCircumference = 72,
|
||||
};
|
||||
|
||||
private:
|
||||
private:
|
||||
QByteArray unlockCommand();
|
||||
QByteArray setResistanceMode(double resistance);
|
||||
QByteArray setStandardMode(uint8_t level);
|
||||
@@ -107,7 +109,88 @@ class wahookickrsnapbike : public bike {
|
||||
|
||||
volatile int notificationSubscribed = 0;
|
||||
|
||||
resistance_t lastForcedResistance = -1;
|
||||
resistance_t lastForcedResistance = -1;
|
||||
|
||||
double gearsToWheelDiameter(double gear);
|
||||
|
||||
class GearTable {
|
||||
public:
|
||||
|
||||
int maxGears = 12;
|
||||
|
||||
struct GearInfo {
|
||||
int gear;
|
||||
int crankset;
|
||||
int rearCog;
|
||||
};
|
||||
|
||||
void loadGearSettings() {
|
||||
QSettings settings;
|
||||
|
||||
QString gearConfig = settings.value("gear_configuration").toString();
|
||||
if (gearConfig.isEmpty()) {
|
||||
|
||||
gearConfig = "1|38|44|true\n2|38|38|true\n3|38|32|true\n4|38|28|true\n"
|
||||
"5|38|24|true\n6|38|21|true\n7|38|19|true\n8|38|17|true\n"
|
||||
"9|38|15|true\n10|38|13|true\n11|38|11|true\n12|38|10|true";
|
||||
}
|
||||
|
||||
gears.clear();
|
||||
maxGears = 0;
|
||||
|
||||
// Parsa la configurazione
|
||||
QStringList rows = gearConfig.split('\n');
|
||||
for (const QString& row : rows) {
|
||||
QStringList parts = row.split('|');
|
||||
if (parts.size() >= 4 && (parts[3] == "true")) {
|
||||
GearInfo config;
|
||||
config.gear = parts[0].toInt();
|
||||
config.crankset = parts[1].toInt();
|
||||
config.rearCog = parts[2].toInt();
|
||||
|
||||
gears.push_back(config);
|
||||
maxGears = qMax(maxGears, config.gear);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addGear(int gear, int crankset, int rearCog) {
|
||||
gears.push_back({gear, crankset, rearCog});
|
||||
}
|
||||
|
||||
void removeGear(int gear) {
|
||||
gears.erase(std::remove_if(gears.begin(), gears.end(),
|
||||
[gear](const GearInfo& info) { return info.gear == gear; }),
|
||||
gears.end());
|
||||
}
|
||||
|
||||
void printTable() const {
|
||||
qDebug() << "| Gear | Crankset | Rear Cog |\n";
|
||||
qDebug() << "|------|----------|----------|\n";
|
||||
for (const auto& gear : gears) {
|
||||
qDebug() << "| " << gear.gear << " | " << gear.crankset
|
||||
<< " | " << gear.rearCog << " |\n";
|
||||
}
|
||||
}
|
||||
|
||||
GearInfo getGear(int gearNumber) const {
|
||||
auto it = std::find_if(gears.begin(), gears.end(),
|
||||
[gearNumber](const GearInfo& info) { return info.gear == gearNumber; });
|
||||
|
||||
if (it != gears.end()) {
|
||||
return *it;
|
||||
}
|
||||
return GearInfo();
|
||||
}
|
||||
|
||||
GearTable() {
|
||||
loadGearSettings();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<GearInfo> gears;
|
||||
};
|
||||
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
lockscreen *h = 0;
|
||||
|
||||
817
src/gears.qml
Normal file
817
src/gears.qml
Normal file
@@ -0,0 +1,817 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Controls.Material 2.0
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
ScrollView {
|
||||
contentWidth: -1
|
||||
focus: true
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.fill: parent
|
||||
id: gearSettingsWindow
|
||||
visible: true
|
||||
clip: true
|
||||
|
||||
// Properties
|
||||
Settings {
|
||||
id: settings
|
||||
property string gear_configuration: "1|38|44|true\n2|38|38|true\n3|38|32|true\n4|38|28|true\n5|38|24|true\n6|38|21|true\n7|38|19|true\n8|38|17|true\n9|38|15|true\n10|38|13|true\n11|38|11|true\n12|38|10|true"
|
||||
property int gear_crankset_size: 42
|
||||
property int gear_cog_size: 14
|
||||
property string gear_wheel_size: "700 x 18C"
|
||||
property real gear_circumference: 2070
|
||||
}
|
||||
|
||||
property int selectedCranksetSize: settings.gear_crankset_size
|
||||
property int selectedCogSize: settings.gear_cog_size
|
||||
property string selectedWheelSize: settings.gear_wheel_size
|
||||
property real selectedCircumference: settings.gear_circumference
|
||||
property bool inited: false
|
||||
|
||||
property int initialWheelSizeIndex: {
|
||||
// Trova l'indice corretto basato sul valore salvato
|
||||
for (let i = 0; i < wheelSizes.count; i++) {
|
||||
if (wheelSizes.get(i).text === settings.gear_wheel_size) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0; // default se non trovato
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (settings.gear_configuration) {
|
||||
gearRows = stringToGearRows(settings.gear_configuration)
|
||||
}
|
||||
console.log("Component.onCompleted " + settings.gear_crankset_size + " " + settings.gear_cog_size + " " + settings.gear_wheel_size + " " + settings.gear_circumference)
|
||||
wheelSizeCombo.currentIndex = initialWheelSizeIndex
|
||||
selectedCranksetSize = settings.gear_crankset_size
|
||||
selectedCogSize = settings.gear_cog_size
|
||||
inited = true
|
||||
}
|
||||
|
||||
function updateSettings() {
|
||||
if(!inited)
|
||||
return;
|
||||
settings.gear_crankset_size = selectedCranksetSize
|
||||
settings.gear_cog_size = selectedCogSize
|
||||
settings.gear_wheel_size = selectedWheelSize
|
||||
settings.gear_circumference = selectedCircumference
|
||||
}
|
||||
|
||||
function stringToGearRows(gearString) {
|
||||
if (!gearString) return []
|
||||
|
||||
return gearString.split("\n").map(function(row) {
|
||||
const parts = row.split("|")
|
||||
return {
|
||||
gear: parseInt(parts[0]),
|
||||
crankset: parseInt(parts[1]),
|
||||
cog: parseInt(parts[2]),
|
||||
active: parts[3] === "true"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function gearRowsToString(gearRows) {
|
||||
return gearRows.map(function(row) {
|
||||
return row.gear + "|" + row.crankset + "|" + row.cog + "|" + row.active
|
||||
}).join("\n")
|
||||
}
|
||||
|
||||
// Monitora i cambiamenti nelle gear e salva automaticamente
|
||||
onGearConfigurationChanged: {
|
||||
settings.gear_configuration = gearRowsToString(gearRows)
|
||||
}
|
||||
|
||||
onSettingsChanged: {
|
||||
console.log("onSettingsChanged")
|
||||
updateSettings()
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: gearSettingsWindow
|
||||
function onGearConfigurationChanged() {
|
||||
gearTable.updateGearListModel()
|
||||
}
|
||||
}
|
||||
|
||||
function loadGearProfile(profileName) {
|
||||
if (profileName in gearProfiles) {
|
||||
const profile = gearProfiles[profileName]
|
||||
|
||||
// Create new array with copied objects
|
||||
var newGears = []
|
||||
for (var i = 0; i < profile.gears.length; i++) {
|
||||
newGears.push({
|
||||
gear: profile.gears[i].gear,
|
||||
crankset: profile.gears[i].crankset,
|
||||
cog: profile.gears[i].cog,
|
||||
active: profile.gears[i].active
|
||||
})
|
||||
}
|
||||
|
||||
gearRows = newGears
|
||||
|
||||
// Force update
|
||||
var temp = gearRows
|
||||
gearRows = []
|
||||
gearRows = temp
|
||||
gearConfigurationChanged(gearRows)
|
||||
}
|
||||
}
|
||||
|
||||
property var gearProfiles: {
|
||||
"Time Trial": {
|
||||
name: "Time Trial (52/36, 10 - 28)",
|
||||
gears: [
|
||||
{ gear: 1, crankset: 36, cog: 28, active: true },
|
||||
{ gear: 2, crankset: 36, cog: 24, active: true },
|
||||
{ gear: 3, crankset: 36, cog: 21, active: true },
|
||||
{ gear: 4, crankset: 36, cog: 19, active: true },
|
||||
{ gear: 5, crankset: 36, cog: 18, active: true },
|
||||
{ gear: 6, crankset: 36, cog: 17, active: true },
|
||||
{ gear: 7, crankset: 36, cog: 16, active: true },
|
||||
{ gear: 8, crankset: 36, cog: 15, active: true },
|
||||
{ gear: 9, crankset: 36, cog: 14, active: true },
|
||||
{ gear: 10, crankset: 52, cog: 19, active: true },
|
||||
{ gear: 11, crankset: 52, cog: 18, active: true },
|
||||
{ gear: 12, crankset: 52, cog: 17, active: true },
|
||||
{ gear: 13, crankset: 52, cog: 16, active: true },
|
||||
{ gear: 14, crankset: 52, cog: 15, active: true },
|
||||
{ gear: 15, crankset: 52, cog: 14, active: true },
|
||||
{ gear: 16, crankset: 52, cog: 13, active: true },
|
||||
{ gear: 17, crankset: 52, cog: 12, active: true },
|
||||
{ gear: 18, crankset: 52, cog: 11, active: true },
|
||||
{ gear: 19, crankset: 52, cog: 10, active: true }
|
||||
]
|
||||
},
|
||||
"Rolling Hills": {
|
||||
name: "Rolling Hills (46/33, 10 - 33)",
|
||||
gears: [
|
||||
{ gear: 1, crankset: 33, cog: 33, active: true },
|
||||
{ gear: 2, crankset: 33, cog: 28, active: true },
|
||||
{ gear: 3, crankset: 33, cog: 24, active: true },
|
||||
{ gear: 4, crankset: 33, cog: 21, active: true },
|
||||
{ gear: 5, crankset: 33, cog: 19, active: true },
|
||||
{ gear: 6, crankset: 33, cog: 17, active: true },
|
||||
{ gear: 7, crankset: 33, cog: 15, active: true },
|
||||
{ gear: 8, crankset: 46, cog: 19, active: true },
|
||||
{ gear: 9, crankset: 46, cog: 17, active: true },
|
||||
{ gear: 10, crankset: 46, cog: 15, active: true },
|
||||
{ gear: 11, crankset: 46, cog: 14, active: true },
|
||||
{ gear: 12, crankset: 46, cog: 13, active: true },
|
||||
{ gear: 13, crankset: 46, cog: 12, active: true },
|
||||
{ gear: 14, crankset: 46, cog: 11, active: true },
|
||||
{ gear: 15, crankset: 46, cog: 10, active: true }
|
||||
]
|
||||
},
|
||||
"Alpine": {
|
||||
name: "Alpine (43/30, 10 - 36)",
|
||||
gears: [
|
||||
{ gear: 1, crankset: 30, cog: 36, active: true },
|
||||
{ gear: 2, crankset: 30, cog: 32, active: true },
|
||||
{ gear: 3, crankset: 30, cog: 28, active: true },
|
||||
{ gear: 4, crankset: 30, cog: 24, active: true },
|
||||
{ gear: 5, crankset: 30, cog: 21, active: true },
|
||||
{ gear: 6, crankset: 30, cog: 19, active: true },
|
||||
{ gear: 7, crankset: 30, cog: 17, active: true },
|
||||
{ gear: 8, crankset: 30, cog: 15, active: true },
|
||||
{ gear: 9, crankset: 43, cog: 19, active: true },
|
||||
{ gear: 10, crankset: 43, cog: 17, active: true },
|
||||
{ gear: 11, crankset: 43, cog: 15, active: true },
|
||||
{ gear: 12, crankset: 43, cog: 13, active: true },
|
||||
{ gear: 13, crankset: 43, cog: 12, active: true },
|
||||
{ gear: 14, crankset: 43, cog: 11, active: true },
|
||||
{ gear: 15, crankset: 43, cog: 10, active: true }
|
||||
]
|
||||
},
|
||||
"Reality Bender": {
|
||||
name: "Reality Bender (24 even spaced)",
|
||||
gears: [
|
||||
{ gear: 1, crankset: 30, cog: 40, active: true },
|
||||
{ gear: 2, crankset: 30, cog: 36, active: true },
|
||||
{ gear: 3, crankset: 30, cog: 33, active: true },
|
||||
{ gear: 4, crankset: 30, cog: 30, active: true },
|
||||
{ gear: 5, crankset: 30, cog: 27, active: true },
|
||||
{ gear: 6, crankset: 34, cog: 28, active: true },
|
||||
{ gear: 7, crankset: 34, cog: 26, active: true },
|
||||
{ gear: 8, crankset: 34, cog: 24, active: true },
|
||||
{ gear: 9, crankset: 34, cog: 22, active: true },
|
||||
{ gear: 10, crankset: 44, cog: 26, active: true },
|
||||
{ gear: 11, crankset: 44, cog: 24, active: true },
|
||||
{ gear: 12, crankset: 44, cog: 22, active: true },
|
||||
{ gear: 13, crankset: 44, cog: 20, active: true },
|
||||
{ gear: 14, crankset: 44, cog: 18, active: true },
|
||||
{ gear: 15, crankset: 56, cog: 21, active: true },
|
||||
{ gear: 16, crankset: 56, cog: 19, active: true },
|
||||
{ gear: 17, crankset: 58, cog: 18, active: true },
|
||||
{ gear: 18, crankset: 60, cog: 17, active: true },
|
||||
{ gear: 19, crankset: 62, cog: 16, active: true },
|
||||
{ gear: 20, crankset: 63, cog: 15, active: true },
|
||||
{ gear: 21, crankset: 64, cog: 14, active: true },
|
||||
{ gear: 22, crankset: 66, cog: 13, active: true },
|
||||
{ gear: 23, crankset: 67, cog: 12, active: true }
|
||||
]
|
||||
},
|
||||
"Explorer": {
|
||||
name: "Explorer (40, 10 - 46)",
|
||||
gears: [
|
||||
{ gear: 1, crankset: 40, cog: 46, active: true },
|
||||
{ gear: 2, crankset: 40, cog: 38, active: true },
|
||||
{ gear: 3, crankset: 40, cog: 32, active: true },
|
||||
{ gear: 4, crankset: 40, cog: 28, active: true },
|
||||
{ gear: 5, crankset: 40, cog: 24, active: true },
|
||||
{ gear: 6, crankset: 40, cog: 21, active: true },
|
||||
{ gear: 7, crankset: 40, cog: 19, active: true },
|
||||
{ gear: 8, crankset: 40, cog: 17, active: true },
|
||||
{ gear: 9, crankset: 40, cog: 15, active: true },
|
||||
{ gear: 10, crankset: 40, cog: 13, active: true },
|
||||
{ gear: 11, crankset: 40, cog: 12, active: true },
|
||||
{ gear: 12, crankset: 40, cog: 11, active: true },
|
||||
{ gear: 13, crankset: 40, cog: 10, active: true }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// Initial gear data
|
||||
property var gearRows: [
|
||||
{ gear: 1, crankset: 38, cog: 44, active: true },
|
||||
{ gear: 2, crankset: 38, cog: 38, active: true },
|
||||
{ gear: 3, crankset: 38, cog: 32, active: true },
|
||||
{ gear: 4, crankset: 38, cog: 28, active: true },
|
||||
{ gear: 5, crankset: 38, cog: 24, active: true },
|
||||
{ gear: 6, crankset: 38, cog: 21, active: true },
|
||||
{ gear: 7, crankset: 38, cog: 19, active: true },
|
||||
{ gear: 8, crankset: 38, cog: 17, active: true },
|
||||
{ gear: 9, crankset: 38, cog: 15, active: true },
|
||||
{ gear: 10, crankset: 38, cog: 13, active: true },
|
||||
{ gear: 11, crankset: 38, cog: 11, active: true },
|
||||
{ gear: 12, crankset: 38, cog: 10, active: true }
|
||||
]
|
||||
|
||||
function addNewGear() {
|
||||
// Find the first inactive gear or add at the end
|
||||
let newGearIndex = gearRows.findIndex(row => !row.active);
|
||||
if (newGearIndex === -1) {
|
||||
newGearIndex = gearRows.length;
|
||||
}
|
||||
|
||||
// Create new gear with default values
|
||||
const newGear = {
|
||||
gear: newGearIndex + 1,
|
||||
crankset: selectedCranksetSize,
|
||||
cog: selectedCogSize,
|
||||
active: true
|
||||
};
|
||||
|
||||
if (newGearIndex < gearRows.length) {
|
||||
gearRows[newGearIndex] = newGear;
|
||||
} else {
|
||||
gearRows.push(newGear);
|
||||
}
|
||||
|
||||
// Force update
|
||||
var temp = gearRows;
|
||||
gearRows = [];
|
||||
gearRows = temp;
|
||||
gearConfigurationChanged(gearRows);
|
||||
}
|
||||
|
||||
function clearGearsFromIndex(startIndex) {
|
||||
for (let i = startIndex; i < gearRows.length; i++) {
|
||||
gearRows[i].active = false
|
||||
}
|
||||
// Force update
|
||||
var temp = gearRows
|
||||
gearRows = []
|
||||
gearRows = temp
|
||||
gearConfigurationChanged(gearRows)
|
||||
}
|
||||
|
||||
function initializeGearRows() {
|
||||
gearRows = [
|
||||
{ gear: 1, crankset: 38, cog: 44, active: true },
|
||||
{ gear: 2, crankset: 38, cog: 38, active: true },
|
||||
{ gear: 3, crankset: 38, cog: 32, active: true },
|
||||
{ gear: 4, crankset: 38, cog: 28, active: true },
|
||||
{ gear: 5, crankset: 38, cog: 24, active: true },
|
||||
{ gear: 6, crankset: 38, cog: 21, active: true },
|
||||
{ gear: 7, crankset: 38, cog: 19, active: true },
|
||||
{ gear: 8, crankset: 38, cog: 17, active: true },
|
||||
{ gear: 9, crankset: 38, cog: 15, active: true },
|
||||
{ gear: 10, crankset: 38, cog: 13, active: true },
|
||||
{ gear: 11, crankset: 38, cog: 11, active: true },
|
||||
{ gear: 12, crankset: 38, cog: 10, active: true }
|
||||
]
|
||||
// Force update
|
||||
var temp = gearRows
|
||||
gearRows = []
|
||||
gearRows = temp
|
||||
}
|
||||
|
||||
// Signals to notify when values change
|
||||
signal settingsChanged()
|
||||
signal gearConfigurationChanged(var gearRows)
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 20
|
||||
spacing: 20
|
||||
id: chainringColumn
|
||||
|
||||
// Crankset Size
|
||||
GroupBox {
|
||||
title: "Chainring Size"
|
||||
Layout.fillWidth: true
|
||||
|
||||
ColumnLayout {
|
||||
Label {
|
||||
text: "Tooth count of your chainring on the bike you are currently riding on your trainer - enter 42 for Zwift Ride"
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: chainringColumn.width - 20
|
||||
}
|
||||
|
||||
SpinBox {
|
||||
from: 1
|
||||
to: 60
|
||||
value: selectedCranksetSize
|
||||
onValueChanged: {
|
||||
selectedCranksetSize = value
|
||||
console.log("Crankset Size changed");
|
||||
settingsChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cog Size
|
||||
GroupBox {
|
||||
title: "Cog Size"
|
||||
Layout.fillWidth: true
|
||||
|
||||
ColumnLayout {
|
||||
Label {
|
||||
text: "Tooth count of your rear cog on your trainer - enter 14 if you have the Zwift Cog"
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
Layout.maximumWidth: chainringColumn.width - 20
|
||||
}
|
||||
SpinBox {
|
||||
from: 1
|
||||
to: 50
|
||||
value: selectedCogSize
|
||||
onValueChanged: {
|
||||
selectedCogSize = value
|
||||
console.log("Cog Size changed");
|
||||
settingsChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wheel Size
|
||||
GroupBox {
|
||||
title: "Virtual Wheel Size"
|
||||
Layout.fillWidth: true
|
||||
|
||||
ComboBox {
|
||||
id: wheelSizeCombo
|
||||
width: parent.width
|
||||
currentIndex: initialWheelSizeIndex
|
||||
textRole: "text"
|
||||
model: ListModel {
|
||||
id: wheelSizes
|
||||
ListElement { text: "700 x 18C"; circumference: 2070 }
|
||||
ListElement { text: "700 x 19C"; circumference: 2080 }
|
||||
ListElement { text: "700 x 20C"; circumference: 2086 }
|
||||
ListElement { text: "700 x 23C"; circumference: 2096 }
|
||||
ListElement { text: "700 x 25C"; circumference: 2109 }
|
||||
ListElement { text: "700 x 28C"; circumference: 2127 }
|
||||
ListElement { text: "700 x 30C"; circumference: 2140 }
|
||||
ListElement { text: "700 x 32C"; circumference: 2152 }
|
||||
ListElement { text: "700 x 35C"; circumference: 2171 }
|
||||
ListElement { text: "700 x 38C"; circumference: 2190 }
|
||||
ListElement { text: "700 x 40C"; circumference: 2203 }
|
||||
ListElement { text: "700 x 44C"; circumference: 2230 }
|
||||
ListElement { text: "700 x 45C"; circumference: 2234 }
|
||||
ListElement { text: "700 x 47C"; circumference: 2247 }
|
||||
ListElement { text: "700 x 50C"; circumference: 2265 }
|
||||
ListElement { text: "650 x 20C"; circumference: 1938 }
|
||||
ListElement { text: "650 x 23C"; circumference: 1944 }
|
||||
ListElement { text: "650 x 35A"; circumference: 2090 }
|
||||
ListElement { text: "650 x 38B"; circumference: 2105 }
|
||||
ListElement { text: "650 x 38A"; circumference: 2125 }
|
||||
ListElement { text: "12\" x 1.75\""; circumference: 935 }
|
||||
ListElement { text: "12\" x 1.95\""; circumference: 940 }
|
||||
ListElement { text: "14\" x 1.50\""; circumference: 1020 }
|
||||
ListElement { text: "14\" x 1.75\""; circumference: 1055 }
|
||||
ListElement { text: "16\" x 1.50\""; circumference: 1185 }
|
||||
ListElement { text: "16\" x 1.75\""; circumference: 1195 }
|
||||
ListElement { text: "16\" x 2.00\""; circumference: 1245 }
|
||||
ListElement { text: "16\" x 1-1/8\""; circumference: 1290 }
|
||||
ListElement { text: "16\" x 1-3/8\""; circumference: 1300 }
|
||||
ListElement { text: "18\" x 1.50\""; circumference: 1340 }
|
||||
ListElement { text: "18\" x 1.75\""; circumference: 1350 }
|
||||
ListElement { text: "20\" x 1.25\""; circumference: 1450 }
|
||||
ListElement { text: "20\" x 1.35\""; circumference: 1460 }
|
||||
ListElement { text: "20\" x 1.50\""; circumference: 1490 }
|
||||
ListElement { text: "20\" x 1.75\""; circumference: 1515 }
|
||||
ListElement { text: "20\" x 1.95\""; circumference: 1565 }
|
||||
ListElement { text: "20\" x 1-1/8\""; circumference: 1545 }
|
||||
ListElement { text: "20\" x 1-3/8\""; circumference: 1615 }
|
||||
ListElement { text: "22\" x 1-3/8\""; circumference: 1770 }
|
||||
ListElement { text: "22\" x 1-1/2\""; circumference: 1785 }
|
||||
ListElement { text: "24\" x 3/4\" Tubular"; circumference: 1785 }
|
||||
ListElement { text: "24\" x 1\""; circumference: 1753 }
|
||||
ListElement { text: "24\" x 1-1/8\""; circumference: 1795 }
|
||||
ListElement { text: "24\" x 1-1/4\""; circumference: 1905 }
|
||||
ListElement { text: "24\" x 1.75\""; circumference: 1890 }
|
||||
ListElement { text: "24\" x 2.00\""; circumference: 1925 }
|
||||
ListElement { text: "24\" x 2.125\""; circumference: 1965 }
|
||||
ListElement { text: "26\" x 7/8\" Tubular"; circumference: 1920 }
|
||||
ListElement { text: "26\" x 1.25\""; circumference: 1950 }
|
||||
ListElement { text: "26\" x 1.40\""; circumference: 2005 }
|
||||
ListElement { text: "26\" x 1.50\""; circumference: 2010 }
|
||||
ListElement { text: "26\" x 1.75\""; circumference: 2023 }
|
||||
ListElement { text: "26\" x 1.95\""; circumference: 2050 }
|
||||
ListElement { text: "26\" x 2.00\""; circumference: 2055 }
|
||||
ListElement { text: "26\" x 2.10\""; circumference: 2068 }
|
||||
ListElement { text: "26\" x 2.125\""; circumference: 2070 }
|
||||
ListElement { text: "26\" x 2.35\""; circumference: 2083 }
|
||||
ListElement { text: "26\" x 3.00\""; circumference: 2170 }
|
||||
ListElement { text: "26\" x 1-1.0\""; circumference: 1913 }
|
||||
ListElement { text: "26\" x 1\""; circumference: 1952 }
|
||||
ListElement { text: "26\" x 1-1/8\""; circumference: 1970 }
|
||||
ListElement { text: "26\" x 1-3/8\""; circumference: 2068 }
|
||||
ListElement { text: "26\" x 1-1/2\""; circumference: 2100 }
|
||||
ListElement { text: "27\" x 1\""; circumference: 2145 }
|
||||
ListElement { text: "27\" x 1-1/8\""; circumference: 2155 }
|
||||
ListElement { text: "27\" x 1-1/4\""; circumference: 2161 }
|
||||
ListElement { text: "27\" x 1-3/8\""; circumference: 2169 }
|
||||
ListElement { text: "27.5\" / 650B x 1.50\""; circumference: 2079 }
|
||||
ListElement { text: "27.5\" / 650B x 1.95\""; circumference: 2090 }
|
||||
ListElement { text: "27.5\" / 650B x 2.10\""; circumference: 2148 }
|
||||
ListElement { text: "27.5\" / 650B x 2.25\""; circumference: 2182 }
|
||||
ListElement { text: "27.5\" / 650B x 2.3\""; circumference: 2199 }
|
||||
ListElement { text: "27.5\" / 650B x 2.35\""; circumference: 2207 }
|
||||
ListElement { text: "27.5\" / 650B x 2.4\""; circumference: 2213 }
|
||||
ListElement { text: "27.5\" / 650B x 2.5\""; circumference: 2231 }
|
||||
ListElement { text: "27.5\" / 650B x 2.6\""; circumference: 2247 }
|
||||
ListElement { text: "27.5\" / 650B x 2.8\""; circumference: 2279 }
|
||||
ListElement { text: "29\" x 2.1\""; circumference: 2286 }
|
||||
ListElement { text: "29\" x 2.2\""; circumference: 2302 }
|
||||
ListElement { text: "29\" x 2.25\""; circumference: 2310 }
|
||||
ListElement { text: "29\" x 2.3\""; circumference: 2326 }
|
||||
ListElement { text: "29\" x 2.35\""; circumference: 2326 }
|
||||
ListElement { text: "29\" x 2.4\""; circumference: 2333 }
|
||||
ListElement { text: "29\" x 2.5\""; circumference: 2350 }
|
||||
ListElement { text: "29\" x 2.6\""; circumference: 2366 }
|
||||
}
|
||||
onCurrentIndexChanged: {
|
||||
if (currentIndex >= 0) {
|
||||
selectedWheelSize = model.get(currentIndex).text
|
||||
selectedCircumference = model.get(currentIndex).circumference
|
||||
console.log("wheelSizeCombo changed");
|
||||
settingsChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
title: "Preset Gear Profiles"
|
||||
Layout.fillWidth: true
|
||||
|
||||
ComboBox {
|
||||
id: profileCombo
|
||||
width: parent.width
|
||||
textRole: "text"
|
||||
displayText: currentIndex < 0 ? "Select a profile..." : model.get(currentIndex).text
|
||||
model: ListModel {
|
||||
id: profileModel
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
for (var key in gearProfiles) {
|
||||
profileModel.append({
|
||||
text: gearProfiles[key].name,
|
||||
value: key
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onCurrentIndexChanged: {
|
||||
if (currentIndex >= 0) {
|
||||
loadGearProfile(profileModel.get(currentIndex).value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Gear Table GroupBox
|
||||
GroupBox {
|
||||
title: "Virtual Gear Table"
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredHeight: parent.height
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 10
|
||||
|
||||
// Updated Buttons Row
|
||||
RowLayout {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
spacing: 10
|
||||
|
||||
Button {
|
||||
text: "Add Gear"
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
onClicked: addNewGear()
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Clear Selected Gear and Following"
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
onClicked: {
|
||||
if (gearTable.currentRow >= 0) {
|
||||
clearGearsFromIndex(gearTable.currentRow)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Reset All Gears"
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
onClicked: initializeGearRows()
|
||||
}
|
||||
}
|
||||
|
||||
// Table Header (same as before)
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 40
|
||||
color: "#f0f0f0"
|
||||
border.width: 1
|
||||
border.color: "#cccccc"
|
||||
|
||||
Row {
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
width: parent.width / 3
|
||||
height: parent.height
|
||||
border.width: 1
|
||||
border.color: "#cccccc"
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Gear"
|
||||
font.bold: true
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width / 3
|
||||
height: parent.height
|
||||
border.width: 1
|
||||
border.color: "#cccccc"
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Chainring"
|
||||
font.bold: true
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: parent.width / 3
|
||||
height: parent.height
|
||||
border.width: 1
|
||||
border.color: "#cccccc"
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Rear Cog"
|
||||
font.bold: true
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Table Content
|
||||
ListView {
|
||||
id: gearTable
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
property int currentRow: -1
|
||||
model: ListModel {
|
||||
id: gearListModel
|
||||
}
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
policy: ScrollBar.AlwaysOff
|
||||
}
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
updateGearListModel()
|
||||
}
|
||||
|
||||
function updateGearListModel() {
|
||||
gearListModel.clear()
|
||||
for (var i = 0; i < gearRows.length; i++) {
|
||||
if (gearRows[i].active) {
|
||||
gearListModel.append(gearRows[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delegate: Rectangle {
|
||||
width: gearTable.width
|
||||
height: 40
|
||||
color: gearTable.currentRow === index ? "#e0e0e0" : "white"
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: gearTable.currentRow = index
|
||||
}
|
||||
|
||||
Row {
|
||||
anchors.fill: parent
|
||||
|
||||
// Gear Number (non-editable)
|
||||
Rectangle {
|
||||
width: parent.width / 3
|
||||
height: parent.height
|
||||
border.width: 1
|
||||
border.color: "#cccccc"
|
||||
color: "transparent"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: gear
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
|
||||
// Crankset (editable)
|
||||
Rectangle {
|
||||
width: parent.width / 3
|
||||
height: parent.height
|
||||
border.width: 1
|
||||
border.color: "#cccccc"
|
||||
color: "transparent"
|
||||
|
||||
SpinBox {
|
||||
id: cranksetSpinBox
|
||||
anchors.centerIn: parent
|
||||
width: parent.width * 0.8
|
||||
height: 30
|
||||
from: 1
|
||||
to: 60
|
||||
value: crankset
|
||||
onValueModified: {
|
||||
gearRows[index].crankset = value
|
||||
gearConfigurationChanged(gearRows)
|
||||
}
|
||||
|
||||
// Style the SpinBox
|
||||
contentItem: TextInput {
|
||||
z: 2
|
||||
text: cranksetSpinBox.textFromValue(cranksetSpinBox.value, cranksetSpinBox.locale)
|
||||
font: cranksetSpinBox.font
|
||||
color: "black"
|
||||
selectionColor: "#21be2b"
|
||||
selectedTextColor: "#ffffff"
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
up.indicator: Rectangle {
|
||||
x: parent.width - width
|
||||
height: parent.height
|
||||
width: height
|
||||
color: parent.up.pressed ? "#e4e4e4" : "#f6f6f6"
|
||||
border.color: "#cccccc"
|
||||
|
||||
Text {
|
||||
text: "+"
|
||||
color: "black"
|
||||
anchors.centerIn: parent
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
down.indicator: Rectangle {
|
||||
x: 0
|
||||
height: parent.height
|
||||
width: height
|
||||
color: parent.down.pressed ? "#e4e4e4" : "#f6f6f6"
|
||||
border.color: "#cccccc"
|
||||
|
||||
Text {
|
||||
text: "-"
|
||||
color: "black"
|
||||
anchors.centerIn: parent
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: "white"
|
||||
border.color: "#cccccc"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rear Cog (editable)
|
||||
Rectangle {
|
||||
width: parent.width / 3
|
||||
height: parent.height
|
||||
border.width: 1
|
||||
border.color: "#cccccc"
|
||||
color: "transparent"
|
||||
|
||||
SpinBox {
|
||||
id: cogSpinBox
|
||||
anchors.centerIn: parent
|
||||
width: parent.width * 0.8
|
||||
height: 30
|
||||
from: 1
|
||||
to: 50
|
||||
value: cog
|
||||
onValueModified: {
|
||||
gearRows[index].cog = value
|
||||
gearConfigurationChanged(gearRows)
|
||||
}
|
||||
|
||||
// Style the SpinBox (same as cranksetSpinBox)
|
||||
contentItem: TextInput {
|
||||
z: 2
|
||||
text: cogSpinBox.textFromValue(cogSpinBox.value, cogSpinBox.locale)
|
||||
font: cogSpinBox.font
|
||||
color: "black"
|
||||
selectionColor: "#21be2b"
|
||||
selectedTextColor: "#ffffff"
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
}
|
||||
|
||||
up.indicator: Rectangle {
|
||||
x: parent.width - width
|
||||
height: parent.height
|
||||
width: height
|
||||
color: parent.up.pressed ? "#e4e4e4" : "#f6f6f6"
|
||||
border.color: "#cccccc"
|
||||
|
||||
Text {
|
||||
text: "+"
|
||||
color: "black"
|
||||
anchors.centerIn: parent
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
down.indicator: Rectangle {
|
||||
x: 0
|
||||
height: parent.height
|
||||
width: height
|
||||
color: parent.down.pressed ? "#e4e4e4" : "#f6f6f6"
|
||||
border.color: "#cccccc"
|
||||
|
||||
Text {
|
||||
text: "-"
|
||||
color: "black"
|
||||
anchors.centerIn: parent
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: "white"
|
||||
border.color: "#cccccc"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -109,5 +109,6 @@
|
||||
<file>ChartFooterInnerNoJS.qml</file>
|
||||
<file>inner_templates/chartjs/dochartliveheart.js</file>
|
||||
<file>Wizard.qml</file>
|
||||
<file>gears.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -769,8 +769,15 @@ const QString QZSettings::default_peloton_date_format = QStringLiteral("MM/dd/yy
|
||||
const QString QZSettings::force_resistance_instead_inclination = QStringLiteral("force_resistance_instead_inclination");
|
||||
const QString QZSettings::proform_treadmill_575i = QStringLiteral("proform_treadmill_575i");
|
||||
const QString QZSettings::zwift_play_emulator = QStringLiteral("zwift_play_emulator");
|
||||
const QString QZSettings::gear_configuration = QStringLiteral("gear_configuration");
|
||||
const QString QZSettings::default_gear_configuration = QStringLiteral("1|38|44|true\n2|38|38|true\n3|38|32|true\n4|38|28|true\n5|38|24|true\n6|38|21|true\n7|38|19|true\n8|38|17|true\n9|38|15|true\n10|38|13|true\n11|38|11|true\n12|38|10|true");
|
||||
const QString QZSettings::gear_crankset_size = QStringLiteral("gear_crankset_size");
|
||||
const QString QZSettings::gear_cog_size = QStringLiteral("gear_cog_size");
|
||||
const QString QZSettings::gear_wheel_size = QStringLiteral("gear_wheel_size");
|
||||
const QString QZSettings::default_gear_wheel_size = QStringLiteral("700 x 18C");
|
||||
const QString QZSettings::gear_circumference = QStringLiteral("gear_circumference");
|
||||
|
||||
const uint32_t allSettingsCount = 651;
|
||||
const uint32_t allSettingsCount = 656;
|
||||
|
||||
QVariant allSettings[allSettingsCount][2] = {
|
||||
{QZSettings::cryptoKeySettingsProfiles, QZSettings::default_cryptoKeySettingsProfiles},
|
||||
@@ -1428,6 +1435,11 @@ QVariant allSettings[allSettingsCount][2] = {
|
||||
{QZSettings::force_resistance_instead_inclination, QZSettings::default_force_resistance_instead_inclination},
|
||||
{QZSettings::proform_treadmill_575i, QZSettings::default_proform_treadmill_575i},
|
||||
{QZSettings::zwift_play_emulator, QZSettings::default_zwift_play_emulator},
|
||||
{QZSettings::gear_configuration, QZSettings::default_gear_configuration},
|
||||
{QZSettings::gear_crankset_size, QZSettings::default_gear_crankset_size},
|
||||
{QZSettings::gear_cog_size, QZSettings::default_gear_cog_size},
|
||||
{QZSettings::gear_wheel_size, QZSettings::default_gear_wheel_size},
|
||||
{QZSettings::gear_circumference, QZSettings::default_gear_circumference},
|
||||
};
|
||||
|
||||
void QZSettings::qDebugAllSettings(bool showDefaults) {
|
||||
|
||||
@@ -2153,6 +2153,21 @@ class QZSettings {
|
||||
static const QString zwift_play_emulator;
|
||||
static constexpr bool default_zwift_play_emulator = false;
|
||||
|
||||
static const QString gear_configuration;
|
||||
static const QString default_gear_configuration;
|
||||
|
||||
static const QString gear_crankset_size;
|
||||
static constexpr int default_gear_crankset_size = 42;
|
||||
|
||||
static const QString gear_cog_size;
|
||||
static constexpr int default_gear_cog_size = 14;
|
||||
|
||||
static const QString gear_wheel_size;
|
||||
static const QString default_gear_wheel_size;
|
||||
|
||||
static const QString gear_circumference;
|
||||
static constexpr double default_gear_circumference = 2070.0;
|
||||
|
||||
/**
|
||||
* @brief Write the QSettings values using the constants from this namespace.
|
||||
* @param showDefaults Optionally indicates if the default should be shown with the key.
|
||||
|
||||
@@ -11,7 +11,7 @@ ScrollView {
|
||||
anchors.fill: parent
|
||||
//anchors.bottom: footerSettings.top
|
||||
//anchors.bottomMargin: footerSettings.height + 10
|
||||
id: settingsTTLPane
|
||||
id: settingsInclinationPane
|
||||
|
||||
Settings {
|
||||
id: settings
|
||||
|
||||
@@ -987,6 +987,13 @@ import QtQuick.Dialogs 1.0
|
||||
|
||||
// from version 2.18.1
|
||||
property bool zwift_play_emulator: false
|
||||
|
||||
// from version 2.18.2
|
||||
property string gear_configuration: "1|38|44|true\n2|38|38|true\n3|38|32|true\n4|38|28|true\n5|38|24|true\n6|38|21|true\n7|38|19|true\n8|38|17|true\n9|38|15|true\n10|38|13|true\n11|38|11|true\n12|38|10|true"
|
||||
property int gear_crankset_size: 42
|
||||
property int gear_cog_size: 14
|
||||
property string gear_wheel_size: "700 x 18C"
|
||||
property real gear_circumference: 2070
|
||||
}
|
||||
|
||||
function paddingZeros(text, limit) {
|
||||
@@ -2493,6 +2500,14 @@ import QtQuick.Dialogs 1.0
|
||||
color: Material.color(Material.Lime)
|
||||
}
|
||||
|
||||
NewPageElement {
|
||||
title: qsTr("Wahoo Options")
|
||||
indicatRectColor: Material.color(Material.Grey)
|
||||
textColor: Material.color(Material.Yellow)
|
||||
color: Material.backgroundColor
|
||||
accordionContent: "gears.qml"
|
||||
}
|
||||
|
||||
AccordionElement {
|
||||
id: schwinnBikeAccordion
|
||||
title: qsTr("Schwinn Bike Options")
|
||||
@@ -9800,7 +9815,7 @@ import QtQuick.Dialogs 1.0
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
Layout.fillWidth: true
|
||||
color: Material.color(Material.Lime)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user