[UI] Reformatting + Niconico forward / back buttons (using YouTube's icons for now)
This commit is contained in:
parent
bdea9ade90
commit
a307a01eef
|
@ -1,5 +1,5 @@
|
||||||
SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
SOURCE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
||||||
pushd $SOURCE_DIR
|
pushd $SOURCE_DIR
|
||||||
qmlfmt -w src/qml/*.qml
|
qmlfmt -w src/qml/*.qml src/qml/*/*.qml
|
||||||
clang-format -style mozilla -i src/*
|
clang-format -style mozilla -i src/*
|
||||||
popd
|
popd
|
||||||
|
|
|
@ -30,9 +30,7 @@ Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
var component = Qt.createComponent(themeName + "ButtonLayout.qml")
|
var component = Qt.createComponent(themeName + "ButtonLayout.qml")
|
||||||
component.createObject(controlsBar, {
|
component.createObject(controlsBar, {})
|
||||||
"anchors.fill": controlsBar
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
|
|
|
@ -15,16 +15,16 @@ Dialog {
|
||||||
Connections {
|
Connections {
|
||||||
target: player
|
target: player
|
||||||
enabled: true
|
enabled: true
|
||||||
onPlaylistChanged: function(playlist) {
|
onPlaylistChanged: function (playlist) {
|
||||||
playlistModel.clear()
|
playlistModel.clear()
|
||||||
for (var thing in playlist) {
|
for (var thing in playlist) {
|
||||||
var item = playlist[thing]
|
var item = playlist[thing]
|
||||||
playlistModel.append({
|
playlistModel.append({
|
||||||
playlistItemTitle: item["title"],
|
playlistItemTitle: item["title"],
|
||||||
playlistItemFilename: item["filename"],
|
playlistItemFilename: item["filename"],
|
||||||
current: item["current"],
|
current: item["current"],
|
||||||
playlistPos: thing
|
playlistPos: thing
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,9 @@ Rectangle {
|
||||||
Connections {
|
Connections {
|
||||||
target: player
|
target: player
|
||||||
enabled: true
|
enabled: true
|
||||||
onChaptersChanged: {chapterMarker.destroy()}
|
onChaptersChanged: {
|
||||||
|
chapterMarker.destroy()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
width: 4
|
width: 4
|
||||||
|
|
|
@ -10,6 +10,7 @@ import player 1.0
|
||||||
Item {
|
Item {
|
||||||
objectName: "buttonLayout"
|
objectName: "buttonLayout"
|
||||||
id: layout
|
id: layout
|
||||||
|
anchors.fill: controlsBar
|
||||||
|
|
||||||
PlayPauseButton {
|
PlayPauseButton {
|
||||||
id: playPauseButton
|
id: playPauseButton
|
||||||
|
@ -36,21 +37,37 @@ Item {
|
||||||
|
|
||||||
PlaylistPrevButton {
|
PlaylistPrevButton {
|
||||||
id: playlistPrevButton
|
id: playlistPrevButton
|
||||||
anchors.right: timeLabel.left
|
anchors.right: backwardButton.left
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
icon.height: 16
|
icon.height: 16
|
||||||
icon.width: 16
|
icon.width: 16
|
||||||
}
|
}
|
||||||
|
BackwardButton {
|
||||||
|
id: backwardButton
|
||||||
|
anchors.right: timeLabel.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
icon.height: 32
|
||||||
|
icon.width: 32
|
||||||
|
}
|
||||||
TimeLabel {
|
TimeLabel {
|
||||||
id: timeLabel
|
id: timeLabel
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
}
|
}
|
||||||
|
ForwardButton {
|
||||||
|
id: forwardButton
|
||||||
|
anchors.left: timeLabel.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
icon.height: 32
|
||||||
|
icon.width: 32
|
||||||
|
}
|
||||||
PlaylistNextButton {
|
PlaylistNextButton {
|
||||||
id: playlistNextButton
|
id: playlistNextButton
|
||||||
anchors.left: timeLabel.right
|
anchors.left: forwardButton.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
icon.height: 16
|
icon.height: 16
|
||||||
|
|
20
src/qml/UIComponents/BackwardButton.qml
Normal file
20
src/qml/UIComponents/BackwardButton.qml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import QtQuick 2.11
|
||||||
|
import QtQuick.Controls 2.4
|
||||||
|
import QtQuick.Dialogs 1.3
|
||||||
|
import QtQuick.Layouts 1.11
|
||||||
|
import QtQuick.Window 2.11
|
||||||
|
import Qt.labs.settings 1.0
|
||||||
|
import Qt.labs.platform 1.0 as LabsPlatform
|
||||||
|
import player 1.0
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: backwardButton
|
||||||
|
icon.source: "icons/" + appearance.themeName + "/backward.svg"
|
||||||
|
icon.color: appearance.buttonColor
|
||||||
|
display: AbstractButton.IconOnly
|
||||||
|
onClicked: {
|
||||||
|
player.playerCommand(Enums.Commands.Seek, "-10")
|
||||||
|
}
|
||||||
|
background: Item {
|
||||||
|
}
|
||||||
|
}
|
20
src/qml/UIComponents/ForwardButton.qml
Normal file
20
src/qml/UIComponents/ForwardButton.qml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import QtQuick 2.11
|
||||||
|
import QtQuick.Controls 2.4
|
||||||
|
import QtQuick.Dialogs 1.3
|
||||||
|
import QtQuick.Layouts 1.11
|
||||||
|
import QtQuick.Window 2.11
|
||||||
|
import Qt.labs.settings 1.0
|
||||||
|
import Qt.labs.platform 1.0 as LabsPlatform
|
||||||
|
import player 1.0
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: forwardButton
|
||||||
|
icon.source: "icons/" + appearance.themeName + "/forward.svg"
|
||||||
|
icon.color: appearance.buttonColor
|
||||||
|
display: AbstractButton.IconOnly
|
||||||
|
onClicked: {
|
||||||
|
player.playerCommand(Enums.Commands.Seek, "10")
|
||||||
|
}
|
||||||
|
background: Item {
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import QtQuick 2.11
|
import QtQuick 2.11
|
||||||
import QtQuick.Controls 2.4
|
import QtQuick.Controls 2.4
|
||||||
import QtQuick.Dialogs 1.3
|
import QtQuick.Dialogs 1.3
|
||||||
import QtQuick.Layouts 1.11
|
import QtQuick.Layouts 1.11
|
||||||
|
@ -7,18 +7,18 @@ import Qt.labs.settings 1.0
|
||||||
import Qt.labs.platform 1.0 as LabsPlatform
|
import Qt.labs.platform 1.0 as LabsPlatform
|
||||||
import player 1.0
|
import player 1.0
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: fullscreenButton
|
id: fullscreenButton
|
||||||
//icon.name: "fullscreen"
|
//icon.name: "fullscreen"
|
||||||
icon.source: "icons/" + appearance.themeName + "/fullscreen.svg"
|
icon.source: "icons/" + appearance.themeName + "/fullscreen.svg"
|
||||||
icon.color: appearance.buttonColor
|
icon.color: appearance.buttonColor
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||||
|
|
||||||
display: AbstractButton.IconOnly
|
display: AbstractButton.IconOnly
|
||||||
onClicked: {
|
onClicked: {
|
||||||
toggleFullscreen()
|
toggleFullscreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
background: Item {
|
background: Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,26 +7,26 @@ import Qt.labs.settings 1.0
|
||||||
import Qt.labs.platform 1.0 as LabsPlatform
|
import Qt.labs.platform 1.0 as LabsPlatform
|
||||||
import player 1.0
|
import player 1.0
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: playPauseButton
|
id: playPauseButton
|
||||||
icon.source: "icons/" + appearance.themeName + "/pause.svg"
|
icon.source: "icons/" + appearance.themeName + "/pause.svg"
|
||||||
icon.color: appearance.buttonColor
|
icon.color: appearance.buttonColor
|
||||||
display: AbstractButton.IconOnly
|
display: AbstractButton.IconOnly
|
||||||
onClicked: {
|
onClicked: {
|
||||||
player.playerCommand(Enums.Commands.TogglePlayPause)
|
player.playerCommand(Enums.Commands.TogglePlayPause)
|
||||||
}
|
}
|
||||||
background: Item {
|
background: Item {
|
||||||
}
|
}
|
||||||
Connections {
|
Connections {
|
||||||
target: player
|
target: player
|
||||||
enabled: true
|
enabled: true
|
||||||
onPlayStatusChanged: function (status) {
|
onPlayStatusChanged: function (status) {
|
||||||
console.log(icon.height)
|
console.log(icon.height)
|
||||||
if (status == Enums.PlayStatus.Playing) {
|
if (status == Enums.PlayStatus.Playing) {
|
||||||
icon.source = "qrc:/icons/" + appearance.themeName + "/pause.svg"
|
icon.source = "qrc:/icons/" + appearance.themeName + "/pause.svg"
|
||||||
} else if (status == Enums.PlayStatus.Paused) {
|
} else if (status == Enums.PlayStatus.Paused) {
|
||||||
icon.source = "qrc:/icons/" + appearance.themeName + "/play.svg"
|
icon.source = "qrc:/icons/" + appearance.themeName + "/play.svg"
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,17 +7,15 @@ import Qt.labs.settings 1.0
|
||||||
import Qt.labs.platform 1.0 as LabsPlatform
|
import Qt.labs.platform 1.0 as LabsPlatform
|
||||||
import player 1.0
|
import player 1.0
|
||||||
|
|
||||||
|
Button {
|
||||||
Button {
|
id: playlistNextButton
|
||||||
id: playlistNextButton
|
//icon.name: "next"
|
||||||
//icon.name: "next"
|
icon.source: "icons/" + appearance.themeName + "/next.svg"
|
||||||
icon.source: "icons/" + appearance.themeName + "/next.svg"
|
icon.color: appearance.buttonColor
|
||||||
icon.color: appearance.buttonColor
|
display: AbstractButton.IconOnly
|
||||||
display: AbstractButton.IconOnly
|
onClicked: {
|
||||||
onClicked: {
|
player.playerCommand(Enums.Commands.NextPlaylistItem)
|
||||||
player.playerCommand(Enums.Commands.NextPlaylistItem)
|
}
|
||||||
}
|
background: Item {
|
||||||
background: Item {
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -7,31 +7,29 @@ import Qt.labs.settings 1.0
|
||||||
import Qt.labs.platform 1.0 as LabsPlatform
|
import Qt.labs.platform 1.0 as LabsPlatform
|
||||||
import player 1.0
|
import player 1.0
|
||||||
|
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: playlistPrevButton
|
id: playlistPrevButton
|
||||||
objectName: "playlistPrevButton"
|
objectName: "playlistPrevButton"
|
||||||
icon.source: "icons/" + appearance.themeName + "/prev.svg"
|
icon.source: "icons/" + appearance.themeName + "/prev.svg"
|
||||||
icon.color: appearance.buttonColor
|
icon.color: appearance.buttonColor
|
||||||
display: AbstractButton.IconOnly
|
display: AbstractButton.IconOnly
|
||||||
visible: appearance.themeName == "Youtube" ? false : true
|
visible: appearance.themeName == "Youtube" ? false : true
|
||||||
onClicked: {
|
onClicked: {
|
||||||
player.playerCommand(Enums.Commands.PreviousPlaylistItem)
|
player.playerCommand(Enums.Commands.PreviousPlaylistItem)
|
||||||
}
|
}
|
||||||
background: Item {
|
background: Item {
|
||||||
}
|
}
|
||||||
Connections {
|
Connections {
|
||||||
target: player
|
target: player
|
||||||
enabled: true
|
enabled: true
|
||||||
onPlaylistPositionChanged: function (position) {
|
onPlaylistPositionChanged: function (position) {
|
||||||
if (appearance.themeName == "YouTube") {
|
if (appearance.themeName == "YouTube") {
|
||||||
if (position != 0) {
|
if (position != 0) {
|
||||||
visible = true
|
visible = true
|
||||||
|
} else {
|
||||||
} else {
|
visible = false
|
||||||
visible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import QtQuick 2.11
|
import QtQuick 2.11
|
||||||
import QtQuick.Controls 2.4
|
import QtQuick.Controls 2.4
|
||||||
import QtQuick.Dialogs 1.3
|
import QtQuick.Dialogs 1.3
|
||||||
import QtQuick.Layouts 1.11
|
import QtQuick.Layouts 1.11
|
||||||
|
@ -7,18 +7,18 @@ import Qt.labs.settings 1.0
|
||||||
import Qt.labs.platform 1.0 as LabsPlatform
|
import Qt.labs.platform 1.0 as LabsPlatform
|
||||||
import player 1.0
|
import player 1.0
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
id: settingsButton
|
id: settingsButton
|
||||||
//icon.name: "settings"
|
//icon.name: "settings"
|
||||||
icon.source: "icons/" + appearance.themeName + "/settings.svg"
|
icon.source: "icons/" + appearance.themeName + "/settings.svg"
|
||||||
icon.color: appearance.buttonColor
|
icon.color: appearance.buttonColor
|
||||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||||
display: AbstractButton.IconOnly
|
display: AbstractButton.IconOnly
|
||||||
onClicked: {
|
onClicked: {
|
||||||
appearance.themeName = appearance.themeName == "YouTube" ? "Niconico" : "YouTube"
|
appearance.themeName = appearance.themeName == "YouTube" ? "Niconico" : "YouTube"
|
||||||
controlsBarItem.setControlsTheme(appearance.themeName)
|
controlsBarItem.setControlsTheme(appearance.themeName)
|
||||||
console.log("Settings Menu Not Yet Implemented.")
|
console.log("Settings Menu Not Yet Implemented.")
|
||||||
}
|
}
|
||||||
background: Item {
|
background: Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,22 +6,22 @@ import QtQuick.Window 2.11
|
||||||
import Qt.labs.settings 1.0
|
import Qt.labs.settings 1.0
|
||||||
import Qt.labs.platform 1.0 as LabsPlatform
|
import Qt.labs.platform 1.0 as LabsPlatform
|
||||||
import player 1.0
|
import player 1.0
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
id: timeLabel
|
id: timeLabel
|
||||||
objectName: "timeLabel"
|
objectName: "timeLabel"
|
||||||
text: "0:00 / 0:00"
|
text: "0:00 / 0:00"
|
||||||
color: "white"
|
color: "white"
|
||||||
padding: 2
|
padding: 2
|
||||||
font.family: appearance.fontName
|
font.family: appearance.fontName
|
||||||
font.pixelSize: 14
|
font.pixelSize: 14
|
||||||
verticalAlignment: Text.AlignVCenter
|
verticalAlignment: Text.AlignVCenter
|
||||||
renderType: Text.NativeRendering
|
renderType: Text.NativeRendering
|
||||||
Connections {
|
Connections {
|
||||||
target: player
|
target: player
|
||||||
enabled: true
|
enabled: true
|
||||||
onDurationStringChanged: function (durationString) {
|
onDurationStringChanged: function (durationString) {
|
||||||
timeLabel.text = durationString
|
timeLabel.text = durationString
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,175 +7,172 @@ import Qt.labs.settings 1.0
|
||||||
import Qt.labs.platform 1.0 as LabsPlatform
|
import Qt.labs.platform 1.0 as LabsPlatform
|
||||||
import player 1.0
|
import player 1.0
|
||||||
|
|
||||||
Slider {
|
Slider {
|
||||||
id: progressBar
|
id: progressBar
|
||||||
objectName: "progressBar"
|
objectName: "progressBar"
|
||||||
to: 1
|
to: 1
|
||||||
value: 0.0
|
value: 0.0
|
||||||
|
Connections {
|
||||||
|
target: player
|
||||||
|
enabled: true
|
||||||
|
onPositionChanged: function (position) {
|
||||||
|
if (!pressed) {
|
||||||
|
progressBar.value = position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onDurationChanged: function (duration) {
|
||||||
|
progressBar.to = duration
|
||||||
|
}
|
||||||
|
onCachedDurationChanged: function (duration) {
|
||||||
|
cachedLength.duration = duration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onMoved: {
|
||||||
|
player.playerCommand(Enums.Commands.SeekAbsolute, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getProgressBarHeight(nyan, isMouse) {
|
||||||
|
var x = Math.max(Screen.height / 256, fun.nyanCat ? 12 : 2)
|
||||||
|
if (appearance.themeName == "Niconico" && !fun.nyanCat) {
|
||||||
|
return x * 2
|
||||||
|
} else if (isMouse & !fun.nyanCat) {
|
||||||
|
return x * 2
|
||||||
|
} else {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function getHandleVisibility(themeName, isMouse) {
|
||||||
|
if (appearance.themeName == "Niconico" && isMouse) {
|
||||||
|
return true
|
||||||
|
} else if (appearance.themeName == "Niconico") {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
id: mouseAreaProgressBar
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
anchors.fill: parent
|
||||||
|
y: parent.y
|
||||||
|
x: parent.x
|
||||||
|
hoverEnabled: true
|
||||||
|
propagateComposedEvents: false
|
||||||
|
acceptedButtons: Qt.NoButton
|
||||||
|
z: 1
|
||||||
|
|
||||||
|
onPositionChanged: {
|
||||||
|
var a = (progressBar.to / progressBar.width) * mouseAreaProgressBar.mouseX
|
||||||
|
hoverProgressLabel.text = utils.createTimestamp(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
id: progressBackground
|
||||||
|
x: progressBar.leftPadding
|
||||||
|
y: progressBar.topPadding + progressBar.availableHeight / 2 - height / 2
|
||||||
|
width: progressBar.availableWidth
|
||||||
|
height: progressBar.getProgressBarHeight(
|
||||||
|
fun.nyanCat, mouseAreaProgressBar.containsMouse)
|
||||||
|
color: appearance.progressBackgroundColor
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
x: (mouseAreaProgressBar.mouseX - width / 2) + progressBar.leftPadding
|
||||||
|
y: progressBackground.y - 20 - height
|
||||||
|
visible: mouseAreaProgressBar.containsMouse
|
||||||
|
color: appearance.mainBackground
|
||||||
|
height: 20
|
||||||
|
width: 50
|
||||||
|
z: 80
|
||||||
|
Text {
|
||||||
|
id: hoverProgressLabel
|
||||||
|
text: "0:00"
|
||||||
|
color: "white"
|
||||||
|
padding: 2
|
||||||
|
font.family: appearance.fontName
|
||||||
|
font.pixelSize: 14
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
renderType: Text.NativeRendering
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressBar {
|
||||||
|
id: cachedLength
|
||||||
|
background: Item {
|
||||||
|
}
|
||||||
|
contentItem: Item {
|
||||||
|
Rectangle {
|
||||||
|
width: cachedLength.visualPosition * parent.width
|
||||||
|
height: parent.height
|
||||||
|
color: appearance.progressCachedColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
z: 40
|
||||||
|
to: progressBar.to
|
||||||
|
property int duration
|
||||||
|
value: progressBar.value + duration
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
id: chapterMarkers
|
||||||
Connections {
|
Connections {
|
||||||
target: player
|
target: player
|
||||||
enabled: true
|
enabled: true
|
||||||
onPositionChanged: function (position) {
|
onChaptersChanged: function (chapters) {
|
||||||
if (!pressed) {
|
for (var i = 0, len = chapters.length; i < len; i++) {
|
||||||
progressBar.value = position
|
var component = Qt.createComponent("ChapterMarker.qml")
|
||||||
|
|
||||||
|
var marker = component.createObject(chapterMarkers, {
|
||||||
|
time: chapters[i]["time"]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onDurationChanged: function (duration) {
|
|
||||||
progressBar.to = duration
|
|
||||||
}
|
|
||||||
onCachedDurationChanged: function (duration) {
|
|
||||||
cachedLength.duration = duration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onMoved: {
|
|
||||||
player.playerCommand(Enums.Commands.SeekAbsolute, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
function getProgressBarHeight(nyan, isMouse) {
|
|
||||||
var x = Math.max(Screen.height / 256, fun.nyanCat ? 12 : 2)
|
|
||||||
if (appearance.themeName == "Niconico" && !fun.nyanCat) {
|
|
||||||
return x * 2
|
|
||||||
} else if (isMouse & !fun.nyanCat) {
|
|
||||||
return x * 2
|
|
||||||
} else {
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function getHandleVisibility(themeName, isMouse) {
|
|
||||||
if (appearance.themeName == "Niconico" && isMouse) {
|
|
||||||
return true
|
|
||||||
} else if (appearance.themeName == "Niconico") {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MouseArea {
|
|
||||||
id: mouseAreaProgressBar
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height
|
|
||||||
anchors.fill: parent
|
|
||||||
y: parent.y
|
|
||||||
x: parent.x
|
|
||||||
hoverEnabled: true
|
|
||||||
propagateComposedEvents: false
|
|
||||||
acceptedButtons: Qt.NoButton
|
|
||||||
z: 1
|
|
||||||
|
|
||||||
onPositionChanged: {
|
|
||||||
var a = (progressBar.to / progressBar.width ) * mouseAreaProgressBar.mouseX
|
|
||||||
hoverProgressLabel.text = utils.createTimestamp(a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
id: progressBackground
|
|
||||||
x: progressBar.leftPadding
|
|
||||||
y: progressBar.topPadding + progressBar.availableHeight / 2 - height / 2
|
|
||||||
width: progressBar.availableWidth
|
|
||||||
height: progressBar.getProgressBarHeight(
|
|
||||||
fun.nyanCat, mouseAreaProgressBar.containsMouse)
|
|
||||||
color: appearance.progressBackgroundColor
|
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
x: (mouseAreaProgressBar.mouseX - width / 2) + progressBar.leftPadding
|
|
||||||
y: progressBackground.y - 20 - height
|
|
||||||
visible: mouseAreaProgressBar.containsMouse
|
|
||||||
color: appearance.mainBackground
|
|
||||||
height: 20
|
|
||||||
width: 50
|
|
||||||
z: 80
|
|
||||||
Text {
|
|
||||||
id: hoverProgressLabel
|
|
||||||
text: "0:00"
|
|
||||||
color: "white"
|
|
||||||
padding: 2
|
|
||||||
font.family: appearance.fontName
|
|
||||||
font.pixelSize: 14
|
|
||||||
verticalAlignment: Text.AlignVCenter
|
|
||||||
renderType: Text.NativeRendering
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ProgressBar {
|
|
||||||
id: cachedLength
|
|
||||||
background: Item {
|
|
||||||
}
|
|
||||||
contentItem: Item {
|
|
||||||
Rectangle {
|
|
||||||
width: cachedLength.visualPosition * parent.width
|
|
||||||
height: parent.height
|
|
||||||
color: appearance.progressCachedColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
z: 40
|
|
||||||
to: progressBar.to
|
|
||||||
property int duration
|
|
||||||
value: progressBar.value + duration
|
|
||||||
anchors.fill: parent
|
|
||||||
}
|
|
||||||
|
|
||||||
Item {
|
|
||||||
anchors.fill: parent
|
|
||||||
id: chapterMarkers
|
|
||||||
Connections {
|
|
||||||
target: player
|
|
||||||
enabled: true
|
|
||||||
onChaptersChanged: function(chapters) {
|
|
||||||
for (var i = 0, len = chapters.length; i < len; i++) {
|
|
||||||
var component = Qt.createComponent(
|
|
||||||
"ChapterMarker.qml")
|
|
||||||
|
|
||||||
var marker = component.createObject(chapterMarkers,
|
|
||||||
{
|
|
||||||
time: chapters[i]["time"]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: progressLength
|
|
||||||
z: 50
|
|
||||||
anchors.left: progressBackground.left
|
|
||||||
width: progressBar.visualPosition * parent.width
|
|
||||||
height: parent.height
|
|
||||||
color: appearance.progressSliderColor
|
|
||||||
Image {
|
|
||||||
visible: fun.nyanCat
|
|
||||||
id: rainbow
|
|
||||||
anchors.fill: parent
|
|
||||||
height: parent.height
|
|
||||||
width: parent.width
|
|
||||||
source: "qrc:/icons/rainbow.png"
|
|
||||||
fillMode: Image.TileHorizontally
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handle: Rectangle {
|
|
||||||
z: 70
|
|
||||||
id: handleRect
|
|
||||||
x: progressBar.leftPadding + progressBar.visualPosition
|
|
||||||
* (progressBar.availableWidth - width)
|
|
||||||
y: progressBar.topPadding + progressBar.availableHeight / 2 - height / 2
|
|
||||||
implicitHeight: radius
|
|
||||||
implicitWidth: radius
|
|
||||||
radius: 12 + (progressBackground.height / 2)
|
|
||||||
color: fun.nyanCat ? "transparent" : appearance.progressSliderColor
|
|
||||||
visible: getHandleVisibility(appearance.themeName, mouseAreaProgressBar.containsMouse)
|
|
||||||
AnimatedImage {
|
|
||||||
z: 80
|
|
||||||
visible: fun.nyanCat
|
|
||||||
paused: progressBar.pressed
|
|
||||||
height: 30
|
|
||||||
id: nyanimation
|
|
||||||
anchors.centerIn: parent
|
|
||||||
source: "qrc:/icons/nyancat.gif"
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: progressLength
|
||||||
|
z: 50
|
||||||
|
anchors.left: progressBackground.left
|
||||||
|
width: progressBar.visualPosition * parent.width
|
||||||
|
height: parent.height
|
||||||
|
color: appearance.progressSliderColor
|
||||||
|
Image {
|
||||||
|
visible: fun.nyanCat
|
||||||
|
id: rainbow
|
||||||
|
anchors.fill: parent
|
||||||
|
height: parent.height
|
||||||
|
width: parent.width
|
||||||
|
source: "qrc:/icons/rainbow.png"
|
||||||
|
fillMode: Image.TileHorizontally
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle: Rectangle {
|
||||||
|
z: 70
|
||||||
|
id: handleRect
|
||||||
|
x: progressBar.leftPadding + progressBar.visualPosition
|
||||||
|
* (progressBar.availableWidth - width)
|
||||||
|
y: progressBar.topPadding + progressBar.availableHeight / 2 - height / 2
|
||||||
|
implicitHeight: radius
|
||||||
|
implicitWidth: radius
|
||||||
|
radius: 12 + (progressBackground.height / 2)
|
||||||
|
color: fun.nyanCat ? "transparent" : appearance.progressSliderColor
|
||||||
|
visible: getHandleVisibility(appearance.themeName,
|
||||||
|
mouseAreaProgressBar.containsMouse)
|
||||||
|
AnimatedImage {
|
||||||
|
z: 80
|
||||||
|
visible: fun.nyanCat
|
||||||
|
paused: progressBar.pressed
|
||||||
|
height: 30
|
||||||
|
id: nyanimation
|
||||||
|
anchors.centerIn: parent
|
||||||
|
source: "qrc:/icons/nyancat.gif"
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,32 +7,31 @@ import Qt.labs.settings 1.0
|
||||||
import Qt.labs.platform 1.0 as LabsPlatform
|
import Qt.labs.platform 1.0 as LabsPlatform
|
||||||
import player 1.0
|
import player 1.0
|
||||||
|
|
||||||
|
Button {
|
||||||
|
id: volumeButton
|
||||||
|
objectName: "volumeButton"
|
||||||
|
icon.source: "icons/" + appearance.themeName + "/volume-up.svg"
|
||||||
|
icon.color: appearance.buttonColor
|
||||||
|
display: AbstractButton.IconOnly
|
||||||
|
onClicked: {
|
||||||
|
player.playerCommand(Enums.Commands.ToggleMute)
|
||||||
|
}
|
||||||
|
background: Item {
|
||||||
|
}
|
||||||
|
Connections {
|
||||||
|
target: player
|
||||||
|
enabled: true
|
||||||
|
onVolumeStatusChanged: function (status) {
|
||||||
|
if (volumeButton == null)
|
||||||
|
console.log("OwO")
|
||||||
|
|
||||||
Button {
|
if (status == Enums.VolumeStatus.Muted) {
|
||||||
id: volumeButton
|
volumeButton.icon.source = "qrc:/icons/" + appearance.themeName + "/volume-mute.svg"
|
||||||
objectName: "volumeButton"
|
} else if (status == Enums.VolumeStatus.Low) {
|
||||||
icon.source: "icons/" + appearance.themeName + "/volume-up.svg"
|
volumeButton.icon.source = "qrc:/icons/" + appearance.themeName + "/volume-down.svg"
|
||||||
icon.color: appearance.buttonColor
|
} else if (status == Enums.VolumeStatus.Normal) {
|
||||||
display: AbstractButton.IconOnly
|
volumeButton.icon.source = "qrc:/icons/" + appearance.themeName + "/volume-up.svg"
|
||||||
onClicked: {
|
|
||||||
player.playerCommand(Enums.Commands.ToggleMute)
|
|
||||||
}
|
|
||||||
background: Item {
|
|
||||||
}
|
|
||||||
Connections {
|
|
||||||
target: player
|
|
||||||
enabled: true
|
|
||||||
onVolumeStatusChanged: function (status){
|
|
||||||
if (volumeButton == null)
|
|
||||||
console.log("OwO");
|
|
||||||
|
|
||||||
if (status == Enums.VolumeStatus.Muted) {
|
|
||||||
volumeButton.icon.source = "qrc:/icons/" + appearance.themeName + "/volume-mute.svg"
|
|
||||||
} else if (status == Enums.VolumeStatus.Low) {
|
|
||||||
volumeButton.icon.source = "qrc:/icons/" + appearance.themeName + "/volume-down.svg"
|
|
||||||
} else if (status == Enums.VolumeStatus.Normal) {
|
|
||||||
volumeButton.icon.source = "qrc:/icons/" + appearance.themeName + "/volume-up.svg"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,57 +7,52 @@ import Qt.labs.settings 1.0
|
||||||
import Qt.labs.platform 1.0 as LabsPlatform
|
import Qt.labs.platform 1.0 as LabsPlatform
|
||||||
import player 1.0
|
import player 1.0
|
||||||
|
|
||||||
|
Slider {
|
||||||
|
id: volumeBar
|
||||||
|
to: 100
|
||||||
|
value: 100
|
||||||
|
palette.dark: "#f00"
|
||||||
|
|
||||||
Slider {
|
implicitWidth: Math.max(background ? background.implicitWidth : 0,
|
||||||
id: volumeBar
|
(handle ? handle.implicitWidth : 0)
|
||||||
to: 100
|
+ leftPadding + rightPadding)
|
||||||
value: 100
|
implicitHeight: Math.max(background ? background.implicitHeight : 0,
|
||||||
palette.dark: "#f00"
|
(handle ? handle.implicitHeight : 0)
|
||||||
|
+ topPadding + bottomPadding)
|
||||||
implicitWidth: Math.max(
|
onMoved: {
|
||||||
background ? background.implicitWidth : 0,
|
player.playerCommand(Enums.Commands.SetVolume,
|
||||||
(handle ? handle.implicitWidth : 0)
|
Math.round(volumeBar.value).toString())
|
||||||
+ leftPadding + rightPadding)
|
}
|
||||||
implicitHeight: Math.max(
|
Connections {
|
||||||
background ? background.implicitHeight : 0,
|
target: player
|
||||||
(handle ? handle.implicitHeight : 0)
|
enabled: true
|
||||||
+ topPadding + bottomPadding)
|
onVolumeChanged: function (volume) {
|
||||||
onMoved: {
|
volumeBar.value = volume
|
||||||
player.playerCommand(Enums.Commands.SetVolume,
|
}
|
||||||
Math.round(volumeBar.value).toString())
|
}
|
||||||
}
|
handle: Rectangle {
|
||||||
Connections {
|
x: volumeBar.leftPadding + volumeBar.visualPosition * (volumeBar.availableWidth - width)
|
||||||
target: player
|
y: volumeBar.topPadding + volumeBar.availableHeight / 2 - height / 2
|
||||||
enabled: true
|
implicitWidth: 12
|
||||||
onVolumeChanged: function (volume){
|
implicitHeight: 12
|
||||||
volumeBar.value = volume
|
radius: 12
|
||||||
}
|
visible: appearance.themeName == "Niconico" ? false : true
|
||||||
}
|
color: "#f6f6f6"
|
||||||
handle: Rectangle {
|
border.color: "#f6f6f6"
|
||||||
x: volumeBar.leftPadding + volumeBar.visualPosition
|
}
|
||||||
* (volumeBar.availableWidth - width)
|
|
||||||
y: volumeBar.topPadding + volumeBar.availableHeight / 2 - height / 2
|
|
||||||
implicitWidth: 12
|
|
||||||
implicitHeight: 12
|
|
||||||
radius: 12
|
|
||||||
visible: appearance.themeName == "Niconico" ? false : true
|
|
||||||
color: "#f6f6f6"
|
|
||||||
border.color: "#f6f6f6"
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
x: volumeBar.leftPadding
|
|
||||||
y: volumeBar.topPadding + volumeBar.availableHeight / 2 - height / 2
|
|
||||||
implicitWidth: appearance.themeName == "Niconico" ? 80 : 60
|
|
||||||
implicitHeight: appearance.themeName == "Niconico" ? 4 : 3
|
|
||||||
width: volumeBar.availableWidth
|
|
||||||
height: implicitHeight
|
|
||||||
color: appearance.progressBackgroundColor
|
|
||||||
Rectangle {
|
|
||||||
width: volumeBar.visualPosition * parent.width
|
|
||||||
height: parent.height
|
|
||||||
color: appearance.volumeSliderBackground
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
x: volumeBar.leftPadding
|
||||||
|
y: volumeBar.topPadding + volumeBar.availableHeight / 2 - height / 2
|
||||||
|
implicitWidth: appearance.themeName == "Niconico" ? 80 : 60
|
||||||
|
implicitHeight: appearance.themeName == "Niconico" ? 4 : 3
|
||||||
|
width: volumeBar.availableWidth
|
||||||
|
height: implicitHeight
|
||||||
|
color: appearance.progressBackgroundColor
|
||||||
|
Rectangle {
|
||||||
|
width: volumeBar.visualPosition * parent.width
|
||||||
|
height: parent.height
|
||||||
|
color: appearance.volumeSliderBackground
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import player 1.0
|
||||||
Item {
|
Item {
|
||||||
objectName: "buttonLayout"
|
objectName: "buttonLayout"
|
||||||
id: layout
|
id: layout
|
||||||
|
anchors.fill: controlsBar
|
||||||
|
|
||||||
PlaylistPrevButton {
|
PlaylistPrevButton {
|
||||||
id: playlistPrevButton
|
id: playlistPrevButton
|
||||||
|
|
1
src/qml/icons/Niconico/backward.svg
Normal file
1
src/qml/icons/Niconico/backward.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48"><path d="M24 10V2L14 12l10 10v-8c6.6 0 12 5.4 12 12s-5.4 12-12 12-12-5.4-12-12H8c0 8.8 7.2 16 16 16s16-7.2 16-16-7.2-16-16-16zm-2.2 22h-1.7v-6.5l-2 .6v-1.4l3.5-1.3h.2V32zm8.5-3.5c0 .6-.1 1.2-.2 1.6s-.3.8-.6 1.1-.6.5-.9.7-.7.2-1.2.2-.8-.1-1.2-.2-.7-.4-.9-.7-.5-.7-.6-1.1-.2-1-.2-1.6V27c0-.6.1-1.2.2-1.6s.3-.8.6-1.1.6-.5.9-.7.7-.2 1.2-.2.8.1 1.2.2.7.4.9.7.5.7.6 1.1.2 1 .2 1.6v1.5zm-1.6-1.7c0-.4 0-.7-.1-1s-.1-.5-.2-.6-.2-.3-.4-.3-.3-.1-.5-.1-.4 0-.5.1-.3.2-.4.3-.2.4-.2.6-.1.6-.1 1v1.9c0 .4 0 .7.1 1s.1.5.2.6.2.3.4.3.3.1.5.1.4 0 .5-.1.3-.2.4-.3.2-.4.2-.6.1-.6.1-1v-1.9z"/></svg>
|
After Width: | Height: | Size: 640 B |
1
src/qml/icons/Niconico/forward.svg
Normal file
1
src/qml/icons/Niconico/forward.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48"><path d="M8 26c0 8.8 7.2 16 16 16s16-7.2 16-16h-4c0 6.6-5.4 12-12 12s-12-5.4-12-12 5.4-12 12-12v8l10-10L24 2v8c-8.8 0-16 7.2-16 16zm13.7 6H20v-6.5l-2 .6v-1.4l3.5-1.3h.2V32zm8.5-3.5c0 .6-.1 1.2-.2 1.6s-.3.8-.6 1.1-.6.5-.9.7-.7.2-1.2.2-.8-.1-1.2-.2-.7-.4-.9-.7-.5-.7-.6-1.1-.2-1-.2-1.6V27c0-.6.1-1.2.2-1.6s.3-.8.6-1.1.6-.5.9-.7.7-.2 1.2-.2.8.1 1.2.2.7.4.9.7.5.7.6 1.1.2 1 .2 1.6v1.5zm-1.7-1.7c0-.4 0-.7-.1-1s-.1-.5-.2-.6-.2-.3-.4-.3-.3-.1-.5-.1-.4 0-.5.1-.3.2-.4.3-.2.4-.2.6-.1.6-.1 1v1.9c0 .4 0 .7.1 1s.1.5.2.6.2.3.4.3.3.1.5.1.4 0 .5-.1.3-.2.4-.3.2-.4.2-.6.1-.6.1-1v-1.9z"/></svg>
|
After Width: | Height: | Size: 642 B |
|
@ -17,7 +17,7 @@ Window {
|
||||||
height: 480
|
height: 480
|
||||||
|
|
||||||
property bool onTop: false
|
property bool onTop: false
|
||||||
|
|
||||||
Translator {
|
Translator {
|
||||||
id: translate
|
id: translate
|
||||||
}
|
}
|
||||||
|
@ -44,8 +44,7 @@ Window {
|
||||||
property string chapterMarkerColor: "#fc0"
|
property string chapterMarkerColor: "#fc0"
|
||||||
property string volumeSliderBackground: "white"
|
property string volumeSliderBackground: "white"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Settings {
|
Settings {
|
||||||
id: i18n
|
id: i18n
|
||||||
category: "I18N"
|
category: "I18N"
|
||||||
|
@ -122,11 +121,11 @@ Window {
|
||||||
mainWindow.visibility = lastScreenVisibility
|
mainWindow.visibility = lastScreenVisibility
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils {
|
Utils {
|
||||||
id: utils
|
id: utils
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerBackend {
|
PlayerBackend {
|
||||||
id: player
|
id: player
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -200,7 +199,7 @@ Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: controlsOverlay
|
id: controlsOverlay
|
||||||
anchors.centerIn: player
|
anchors.centerIn: player
|
||||||
|
@ -222,7 +221,7 @@ Window {
|
||||||
mouseAreaPlayer.cursorShape = Qt.ArrowCursor
|
mouseAreaPlayer.cursorShape = Qt.ArrowCursor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
id: mouseAreaBar
|
id: mouseAreaBar
|
||||||
|
|
||||||
|
@ -327,9 +326,9 @@ Window {
|
||||||
&& ((!appearance.titleOnlyOnFullscreen)
|
&& ((!appearance.titleOnlyOnFullscreen)
|
||||||
|| (mainWindow.visibility == Window.FullScreen))
|
|| (mainWindow.visibility == Window.FullScreen))
|
||||||
Connections {
|
Connections {
|
||||||
target: player
|
target: player
|
||||||
enabled: true
|
enabled: true
|
||||||
onTitleChanged: function (title) {
|
onTitleChanged: function (title) {
|
||||||
titleLabel.text = title
|
titleLabel.text = title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
<file>MainMenu.qml</file>
|
<file>MainMenu.qml</file>
|
||||||
<file>YouTubeButtonLayout.qml</file>
|
<file>YouTubeButtonLayout.qml</file>
|
||||||
<file>NiconicoButtonLayout.qml</file>
|
<file>NiconicoButtonLayout.qml</file>
|
||||||
|
<file alias="ForwardButton.qml">UIComponents/ForwardButton.qml</file>
|
||||||
|
<file alias="BackwardButton.qml">UIComponents/BackwardButton.qml</file>
|
||||||
<file alias="PlaylistPrevButton.qml">UIComponents/PlaylistPrevButton.qml</file>
|
<file alias="PlaylistPrevButton.qml">UIComponents/PlaylistPrevButton.qml</file>
|
||||||
<file alias="PlayPauseButton.qml">UIComponents/PlayPauseButton.qml</file>
|
<file alias="PlayPauseButton.qml">UIComponents/PlayPauseButton.qml</file>
|
||||||
<file alias="VideoProgress.qml">UIComponents/VideoProgress.qml</file>
|
<file alias="VideoProgress.qml">UIComponents/VideoProgress.qml</file>
|
||||||
|
@ -45,6 +47,8 @@
|
||||||
<file>icons/Niconico/prev.svg</file>
|
<file>icons/Niconico/prev.svg</file>
|
||||||
<file>icons/Niconico/next.svg</file>
|
<file>icons/Niconico/next.svg</file>
|
||||||
<file>icons/Niconico/fullscreen.svg</file>
|
<file>icons/Niconico/fullscreen.svg</file>
|
||||||
|
<file>icons/Niconico/forward.svg</file>
|
||||||
|
<file>icons/Niconico/backward.svg</file>
|
||||||
<file>icons/nyancat.gif</file>
|
<file>icons/nyancat.gif</file>
|
||||||
<file>icons/rainbow.png</file>
|
<file>icons/rainbow.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
|
|
Loading…
Reference in a new issue