Library migration #36
15 changed files with 70 additions and 66 deletions
|
@ -91,7 +91,7 @@ RemoteDataListView {
|
|||
}
|
||||
|
||||
text: swipeDelegate.text
|
||||
color: appTheme.style.textColor
|
||||
color: appTheme.theme.colors.text
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
|
@ -104,7 +104,7 @@ RemoteDataListView {
|
|||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: pressed ? appTheme.style.delegatePressedColor : appTheme.style.delegateBackgroundColor
|
||||
color: pressed ? appTheme.theme.colors.delegatePressed : appTheme.theme.colors.delegateBackground
|
||||
|
||||
Behavior on color {
|
||||
|
||||
|
@ -128,22 +128,22 @@ RemoteDataListView {
|
|||
Repeater {
|
||||
id: athleteSelectBoxRep
|
||||
|
||||
model: speedBackend.timers.length
|
||||
model: speedBackend.race.timers.length
|
||||
|
||||
delegate: CheckBox {
|
||||
id: control
|
||||
|
||||
property bool active: speedBackend.timers[index]["id"] === profileList.listData[swipeDelegate.thisIndex]["active"]
|
||||
property bool active: speedBackend.race.timers[index]["id"] === profileList.listData[swipeDelegate.thisIndex]["active"]
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
height: parent.height * 0.6
|
||||
|
||||
enabled: speedBackend.timers[index]["state"] !== "DISABLED"
|
||||
enabled: speedBackend.race.timers[index]["state"] !== ScStwTimer.DISABLED
|
||||
checked: control.active
|
||||
|
||||
onCheckedChanged: {
|
||||
if(checked && !control.active && speedBackend.selectAthlete(profileList.listData[swipeDelegate.thisIndex]["userName"], speedBackend.timers[index]["id"])){
|
||||
if(checked && !control.active && speedBackend.selectAthlete(profileList.listData[swipeDelegate.thisIndex]["userName"], speedBackend.race.timers[index]["id"])){
|
||||
profileList.loadData()
|
||||
}
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ RemoteDataListView {
|
|||
|
||||
radius: width * 0.2
|
||||
border.color: control.enabled ? control.down ? "#17a81a" : "#21be2b" : "grey"
|
||||
color: control.down ? appTheme.style.delegatePressedColor : appTheme.style.delegateBackgroundColor
|
||||
color: control.down ? appTheme.theme.colors.delegatePressed : appTheme.theme.colors.delegateBackground
|
||||
|
||||
Rectangle {
|
||||
width: parent.width * 0.65
|
||||
|
@ -233,7 +233,7 @@ RemoteDataListView {
|
|||
Label {
|
||||
id: deleteLabel
|
||||
text: qsTr("Delete")
|
||||
color: appTheme.style.textColor
|
||||
color: appTheme.theme.colors.text
|
||||
verticalAlignment: Label.AlignVCenter
|
||||
padding: 12
|
||||
height: parent.height
|
||||
|
|
|
@ -59,7 +59,7 @@ Popup {
|
|||
id: backgroundRect
|
||||
anchors.fill: parent
|
||||
radius: width * 0.1
|
||||
color: appTheme.style.viewColor
|
||||
color: appTheme.theme.colors.view
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ Popup {
|
|||
|
||||
anchors.fill: parent
|
||||
|
||||
property color color: appTheme.style.viewColor
|
||||
property color color: appTheme.theme.colors.view
|
||||
|
||||
onPaint: {
|
||||
var ctx = getContext("2d");
|
||||
|
@ -173,7 +173,7 @@ Popup {
|
|||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
color: appTheme.style.textColor
|
||||
color: appTheme.theme.colors.text
|
||||
|
||||
text: profilesStack.currentItem.title
|
||||
|
||||
|
@ -196,9 +196,9 @@ Popup {
|
|||
|
||||
glowOpacity: Math.pow( root.opacity, 100 )
|
||||
|
||||
backgroundColor: appTheme.style.buttonColor
|
||||
backgroundColor: appTheme.theme.colors.button
|
||||
|
||||
image: appTheme.style.backIcon
|
||||
image: appTheme.theme.images.backIcon
|
||||
|
||||
onClicked: profilesStack.depth > 1 ? profilesStack.pop():root.close()
|
||||
|
||||
|
@ -221,9 +221,9 @@ Popup {
|
|||
|
||||
glowOpacity: opacity < 1 ? Math.pow( opacity, 100 ) : Math.pow( opacity, 100 )
|
||||
|
||||
backgroundColor: appTheme.style.buttonColor
|
||||
backgroundColor: appTheme.theme.colors.button
|
||||
|
||||
image: appTheme.style.confirmIcon
|
||||
image: appTheme.theme.images.confirmIcon
|
||||
imageScale: profilesStack.currentItem.secondButt === "ok" ? 1:0
|
||||
|
||||
Label {
|
||||
|
@ -235,7 +235,7 @@ Popup {
|
|||
}
|
||||
opacity: profilesStack.currentItem.secondButt === "add" ? 1:0
|
||||
|
||||
color: appTheme.style.textColor
|
||||
color: appTheme.theme.colors.text
|
||||
|
||||
text: "+"
|
||||
font.pixelSize: parent.height * 0.8
|
||||
|
|
|
@ -83,7 +83,7 @@ RemoteDataListView {
|
|||
font.pixelSize: height * 0.8
|
||||
fontSizeMode: Text.Fit
|
||||
|
||||
color: appTheme.style.textColor
|
||||
color: appTheme.theme.colors.text
|
||||
|
||||
text: resultDel.getDateText()
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ RemoteDataListView {
|
|||
font.pixelSize: height * 0.8
|
||||
fontSizeMode: Text.Fit
|
||||
|
||||
color: appTheme.style.textColor
|
||||
color: appTheme.theme.colors.text
|
||||
|
||||
text: qsTr("result: ") + (listData[index]["result"] / 1000).toFixed(3) + " s"
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ RemoteDataListView {
|
|||
font.pixelSize: height * 0.8
|
||||
fontSizeMode: Text.Fit
|
||||
|
||||
color: appTheme.style.textColor
|
||||
color: appTheme.theme.colors.text
|
||||
|
||||
text: qsTr("reaction time: ") + listData[index]["reactionTime"].toFixed(0) + " ms"
|
||||
}
|
||||
|
|
|
@ -189,6 +189,8 @@ Column {
|
|||
|
||||
minimumPixelSize: 1
|
||||
|
||||
color: appTheme.theme.colors.text
|
||||
|
||||
text: "ScStwBaseStation"
|
||||
}
|
||||
|
||||
|
@ -207,7 +209,8 @@ Column {
|
|||
|
||||
minimumPixelSize: 1
|
||||
|
||||
color: appTheme.style.lineColor
|
||||
color: appTheme.theme.colors.line
|
||||
|
||||
text: "Firmware: " + speedBackend.scStwClient.getFirmwareVersion() + " API: " + speedBackend.scStwClient.getApiVersion()
|
||||
}
|
||||
|
||||
|
|
|
@ -42,8 +42,8 @@ Popup {
|
|||
|
||||
background: Rectangle {
|
||||
radius: width * 0.5
|
||||
color: appTheme.style.viewColor
|
||||
border.color: appTheme.style.lineColor
|
||||
color: appTheme.theme.colors.view
|
||||
border.color: appTheme.theme.colors.line
|
||||
border.width: 0
|
||||
|
||||
Behavior on color {
|
||||
|
@ -76,7 +76,7 @@ Popup {
|
|||
height: header.height
|
||||
width: header.width
|
||||
|
||||
property color color: appTheme.style.viewColor
|
||||
property color color: appTheme.theme.colors.view
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
|
@ -130,7 +130,7 @@ Popup {
|
|||
|
||||
text: options_stack.currentItem.title
|
||||
font.pixelSize: headlineUnderline.width * 0.1
|
||||
color: enabled ? appTheme.style.textColor:appTheme.style.disabledTextColor
|
||||
color: enabled ? appTheme.theme.colors.text:appTheme.theme.colors.disabledText
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ Popup {
|
|||
id: headlineUnderline
|
||||
height: 1
|
||||
width: parent.width
|
||||
color: appTheme.style.lineColor
|
||||
color: appTheme.theme.colors.line
|
||||
visible: false
|
||||
anchors {
|
||||
top: parent.top
|
||||
|
@ -166,7 +166,7 @@ Popup {
|
|||
|
||||
glowOpacity: Math.pow( root.opacity, 100 )
|
||||
|
||||
image: appTheme.style.backIcon
|
||||
image: appTheme.theme.images.backIcon
|
||||
|
||||
onClicked: {
|
||||
options_stack.depth > 1 ? options_stack.pop():root.close()
|
||||
|
|
|
@ -51,10 +51,10 @@ Column {
|
|||
width: parent.width
|
||||
height: parentObj.delegateHeight
|
||||
|
||||
checked: parseInt(speedBackend.readSetting("theme")) === AppTheme.Dark
|
||||
checked: speedBackend.readSetting("theme") === "Dark"
|
||||
|
||||
onCheckedChanged: {
|
||||
var newTheme = checked ? AppTheme.Dark:AppTheme.Light
|
||||
var newTheme = checked ? "Dark":"Light"
|
||||
speedBackend.writeSetting("theme", newTheme)
|
||||
appTheme.setTheme(newTheme)
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ SmoothItemDelegate {
|
|||
onStatusChanged: {
|
||||
if(oldState !== status.status) {
|
||||
if(status.status === "disconnected" && oldState === "connecting") {
|
||||
statusIndicator.color_override = appTheme.style.errorColor
|
||||
statusIndicator.color_override = appTheme.theme.colors.error
|
||||
shortDelay.start()
|
||||
}
|
||||
oldState = status.status
|
||||
|
@ -58,10 +58,10 @@ SmoothItemDelegate {
|
|||
id: statusIndicator
|
||||
property string color_override: ""
|
||||
anchors.fill: parent
|
||||
color: color_override === "" ? status.status === "connected" ? appTheme.style.successColor:"transparent":color_override
|
||||
color: color_override === "" ? status.status === "connected" ? appTheme.theme.colors.success:"transparent":color_override
|
||||
opacity: status.status === "connecting" ? 0:1
|
||||
radius: height * 0.5
|
||||
border.color: appTheme.style.lineColor
|
||||
border.color: appTheme.theme.colors.line
|
||||
border.width: 1
|
||||
|
||||
Behavior on color {
|
||||
|
@ -86,7 +86,7 @@ SmoothItemDelegate {
|
|||
|
||||
arcBegin: 0
|
||||
arcEnd: 360 * ( status.progress / 100 )
|
||||
colorCircle: appTheme.style.lineColor
|
||||
colorCircle: appTheme.theme.colors.line
|
||||
onColorCircleChanged: prog.repaint()
|
||||
onArcEndChanged: prog.repaint()
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ Button {
|
|||
id: control
|
||||
|
||||
property string image
|
||||
property color backgroundColor: appTheme.style.buttonColor
|
||||
property color backgroundColor: appTheme.theme.colors.button
|
||||
property real imageScale: 1
|
||||
property double glowRadius: 0.001
|
||||
property double glowSpread: 0.2
|
||||
|
|
|
@ -37,7 +37,7 @@ SmoothItemDelegate {
|
|||
|
||||
inputMethodHints: control.inputMethodHints
|
||||
|
||||
palette.text: appTheme.style.textColor
|
||||
palette.text: appTheme.theme.colors.text
|
||||
|
||||
onTextChanged: {
|
||||
control.inputText = text
|
||||
|
|
|
@ -9,7 +9,7 @@ SmoothItemDelegate {
|
|||
|
||||
Image {
|
||||
id: forwardImage
|
||||
source: appTheme.style.backIcon
|
||||
source: appTheme.theme.images.backIcon
|
||||
rotation: 180
|
||||
height: control.height * 0.4
|
||||
width: height
|
||||
|
|
|
@ -4,7 +4,7 @@ import QtQuick.Controls 2.2
|
|||
ItemDelegate {
|
||||
id: control
|
||||
text: ""
|
||||
property color textColor: appTheme.style.textColor
|
||||
property color textColor: appTheme.theme.colors.text
|
||||
property alias backgroundRect: backgroundRect
|
||||
|
||||
font.pixelSize: height * 0.4
|
||||
|
@ -26,7 +26,7 @@ ItemDelegate {
|
|||
}
|
||||
|
||||
text: control.text
|
||||
color: appTheme.style.textColor
|
||||
color: appTheme.theme.colors.text
|
||||
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
|
@ -42,7 +42,7 @@ ItemDelegate {
|
|||
|
||||
background: Rectangle {
|
||||
id: backgroundRect
|
||||
color: control.down ? appTheme.style.delegatePressedColor : appTheme.style.delegateBackgroundColor
|
||||
color: control.down ? appTheme.theme.colors.delegatePressed : appTheme.theme.colors.delegateBackground
|
||||
|
||||
radius: height * 0.3
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ SwitchDelegate {
|
|||
}
|
||||
|
||||
text: control.text
|
||||
color: appTheme.style.textColor
|
||||
color: appTheme.theme.colors.text
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
|
||||
|
@ -60,7 +60,7 @@ SwitchDelegate {
|
|||
width: parent.height
|
||||
height: parent.height
|
||||
radius: height * 0.5
|
||||
color: parent.down ? appTheme.style.buttonPressedColor:appTheme.style.backgroundColor
|
||||
color: parent.down ? appTheme.theme.colors.buttonPressed:appTheme.theme.colors.background
|
||||
border.color: parent.checked ? (parent.down ? "#17a81a" : "#21be2b") : "#999999"
|
||||
Behavior on x{
|
||||
NumberAnimation {
|
||||
|
@ -74,7 +74,7 @@ SwitchDelegate {
|
|||
|
||||
background: Rectangle {
|
||||
opacity: enabled ? 1 : 0.3
|
||||
color: control.down ? appTheme.style.delegatePressedColor : appTheme.style.delegateBackgroundColor
|
||||
color: control.down ? appTheme.theme.colors.delegatePressed : appTheme.theme.colors.delegateBackground
|
||||
|
||||
radius: height * 0.3
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ Window {
|
|||
Rectangle {
|
||||
id: backgroundRect
|
||||
anchors.fill: parent
|
||||
color: appTheme.style.backgroundColor
|
||||
color: appTheme.theme.colors.background
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
|
@ -96,7 +96,7 @@ Window {
|
|||
}
|
||||
}
|
||||
|
||||
AppTheme {
|
||||
ScStwAppThemeManager {
|
||||
id: appTheme
|
||||
|
||||
Component.onCompleted: {
|
||||
|
@ -131,7 +131,7 @@ Window {
|
|||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: appTheme.style.menuColor
|
||||
color: appTheme.theme.colors.menu
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
|
@ -155,7 +155,7 @@ Window {
|
|||
text: implicitText === "NEXT_START_ACTION" ?
|
||||
["", "at your \nmarks", "ready", "starting..."][speedBackend.race.nextStartActionDetails[ScStwRace.NextStartAction]+1]:implicitText
|
||||
|
||||
color: appTheme.style.textColor
|
||||
color: appTheme.theme.colors.text
|
||||
|
||||
fontSizeMode: Text.Fit
|
||||
|
||||
|
@ -204,9 +204,9 @@ Window {
|
|||
height: parent.height
|
||||
|
||||
elide: "ElideRight"
|
||||
color: [ScStwTimer.WON].includes(speedBackend.race.timers[index]["state"]) ? appTheme.style.successColor :
|
||||
[ScStwTimer.LOST, ScStwTimer.FAILED].includes(speedBackend.race.timers[index]["state"]) ? appTheme.style.errorColor:
|
||||
appTheme.style.textColor
|
||||
color: [ScStwTimer.WON].includes(speedBackend.race.timers[index]["state"]) ? appTheme.theme.colors.success :
|
||||
[ScStwTimer.LOST, ScStwTimer.FAILED].includes(speedBackend.race.timers[index]["state"]) ? appTheme.theme.colors.error:
|
||||
appTheme.theme.colors.text
|
||||
|
||||
enabled: speedBackend.race.timers[index]["state"] !== ScStwTimer.DISABLED
|
||||
|
||||
|
@ -251,7 +251,7 @@ Window {
|
|||
|
||||
opacity: (app.state === "RUNNING" || app.state === "STOPPED") && rtime !== 0 ? 1:0
|
||||
|
||||
color: appTheme.style.textColor
|
||||
color: appTheme.theme.colors.text
|
||||
|
||||
font.pixelSize: timerTextLa.font.pixelSize * 0.5
|
||||
}
|
||||
|
@ -302,7 +302,7 @@ Window {
|
|||
|
||||
status: clientStateToString(speedBackend.scStwClient.state)
|
||||
|
||||
source: appTheme.style.baseStationIcon
|
||||
source: appTheme.theme.images.baseStationIcon
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: 10
|
||||
|
@ -338,10 +338,10 @@ Window {
|
|||
var source
|
||||
switch(speedBackend.scStwClient.extensions[index]["type"]){
|
||||
case "STARTPAD":
|
||||
source = appTheme.style.startpadIcon
|
||||
source = appTheme.theme.images.startpadIcon
|
||||
break
|
||||
case "TOPPAD":
|
||||
source = appTheme.style.buzzerIcon
|
||||
source = appTheme.theme.images.buzzerIcon
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +375,7 @@ Window {
|
|||
id: upper_line
|
||||
width: app.landscape() ? 1:parent.width
|
||||
height: app.landscape() ? parent.height:1
|
||||
color: appTheme.style.lineColor
|
||||
color: appTheme.theme.colors.line
|
||||
anchors.left: app.landscape() ? topContainerItm.right:parent.left
|
||||
anchors.top: app.landscape() ? parent.top:topContainerItm.bottom
|
||||
anchors.bottom: app.landscape() ? parent.bottom:undefined
|
||||
|
@ -390,7 +390,7 @@ Window {
|
|||
|
||||
text: "start"
|
||||
property int size: app.landscape() ? parent.width * 0.5:parent.height * 0.5
|
||||
property color backgroundColor: appTheme.style.buttonColor
|
||||
property color backgroundColor: appTheme.theme.colors.button
|
||||
property bool progressControlActivated: speedBackend.scStwClient.state === ScStwClient.CONNECTED && app.state === "RUNNING"
|
||||
delay: progressControlActivated ? 2000:0
|
||||
|
||||
|
@ -410,7 +410,7 @@ Window {
|
|||
anchors.centerIn: parent
|
||||
font.pixelSize: parent.height * 0.16
|
||||
font.family: "Helvetica"
|
||||
color: enabled ? appTheme.style.textColor:appTheme.style.disabledTextColor
|
||||
color: enabled ? appTheme.theme.colors.text:appTheme.theme.colors.disabledText
|
||||
}
|
||||
|
||||
Behavior on text {
|
||||
|
@ -561,10 +561,10 @@ Window {
|
|||
anchors.centerIn: parent
|
||||
font.pixelSize: parent.height * 0.16
|
||||
font.family: "Helvetica"
|
||||
color: appTheme.style.textColor
|
||||
color: appTheme.theme.colors.text
|
||||
}
|
||||
|
||||
backgroundColor: appTheme.style.buttonColor
|
||||
backgroundColor: appTheme.theme.colors.button
|
||||
}
|
||||
|
||||
/*------
|
||||
|
@ -598,7 +598,7 @@ Window {
|
|||
id: lowerLine
|
||||
width: app.landscape() ? 1:parent.width
|
||||
height: app.landscape() ? parent.height:1
|
||||
color: appTheme.style.lineColor
|
||||
color: appTheme.theme.colors.line
|
||||
anchors.right: app.landscape() ? menu_container.left:parent.right
|
||||
anchors.bottom: app.landscape() ? parent.bottom:menu_container.top
|
||||
anchors.top: app.landscape() ? parent.top:undefined
|
||||
|
@ -630,7 +630,7 @@ Window {
|
|||
Rectangle {
|
||||
id: lowerMenuBackground
|
||||
anchors.fill: parent
|
||||
color: appTheme.style.menuColor
|
||||
color: appTheme.theme.colors.menu
|
||||
|
||||
Behavior on color {
|
||||
ColorAnimation {
|
||||
|
@ -683,9 +683,9 @@ Window {
|
|||
settingsDialog.open()
|
||||
}
|
||||
|
||||
image: appTheme.style.settIcon
|
||||
image: appTheme.theme.images.settIcon
|
||||
|
||||
backgroundColor: parent.pressed ? appTheme.style.buttonPressedColor:appTheme.style.buttonColor
|
||||
backgroundColor: parent.pressed ? appTheme.theme.colors.buttonPressed:appTheme.theme.colors.button
|
||||
|
||||
}
|
||||
|
||||
|
@ -706,9 +706,9 @@ Window {
|
|||
profilesDialog.open()
|
||||
}
|
||||
|
||||
image: appTheme.style.profilesIcon
|
||||
image: appTheme.theme.images.profilesIcon
|
||||
|
||||
backgroundColor: parent.pressed ? appTheme.style.buttonPressedColor:appTheme.style.buttonColor
|
||||
backgroundColor: parent.pressed ? appTheme.theme.colors.buttonPressed:appTheme.theme.colors.button
|
||||
|
||||
states: [
|
||||
State {
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include <ScStw.hpp>
|
||||
#include <scstwtimer.h>
|
||||
#include <scstwapptheme.h>
|
||||
#include <scstwappthememanager.h>
|
||||
#include <QTranslator>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -91,8 +92,8 @@ int main(int argc, char *argv[])
|
|||
qmlRegisterType<ScStwAppBackend>("com.itsblue.speedclimbingstopwatch", 2, 0, "SpeedBackend");
|
||||
qmlRegisterType<ScStwRace>("com.itsblue.speedclimbingstopwatch", 2, 0, "ScStwRace");
|
||||
qmlRegisterType<ScStwTimer>("com.itsblue.speedclimbingstopwatch", 2, 0, "ScStwTimer");
|
||||
qmlRegisterType<ScStwAppTheme>("com.itsblue.speedclimbingstopwatch", 2, 0, "AppTheme");
|
||||
//qmlRegisterUncreatableType<ScStw>("com.itsblue.speedclimbingstopwatch", 2, 0, "ScStw", "This is a static class and therefore not instantiable");
|
||||
qmlRegisterUncreatableType<ScStwAppTheme>("com.itsblue.speedclimbingstopwatch", 2, 0, "ScStwAppTheme", "readonly");
|
||||
qmlRegisterType<ScStwAppThemeManager>("com.itsblue.speedclimbingstopwatch", 2, 0, "ScStwAppThemeManager");
|
||||
qmlRegisterType<ScStw>("com.itsblue.speedclimbingstopwatch", 2, 0, "ScStw");
|
||||
qmlRegisterType<ScStwClient>("com.itsblue.speedclimbingstopwatch", 2, 0, "ScStwClient");
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 585d524a20e2e090b719cf36c2b8775d2b075704
|
||||
Subproject commit c027fa242afc77746af5028af2919ffd3905658b
|
Reference in a new issue