2018-11-10 19:55:59 +00:00
|
|
|
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
|
|
|
|
|
|
|
|
Item {
|
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
anchors.left: parent.left
|
|
|
|
anchors.right: parent.right
|
|
|
|
|
|
|
|
property var background: controlsBackground
|
|
|
|
property var progress: progressBar
|
|
|
|
property var controls: controlsBar
|
2018-11-21 10:26:39 +00:00
|
|
|
property var duration: progressBar.to
|
2018-11-10 19:55:59 +00:00
|
|
|
|
2018-11-19 12:24:13 +00:00
|
|
|
Item {
|
2018-11-10 19:55:59 +00:00
|
|
|
id: subtitlesBar
|
|
|
|
visible: !appearance.useMpvSubs
|
|
|
|
height: player.height / 8
|
|
|
|
anchors.bottom: controlsBackground.top
|
|
|
|
anchors.bottomMargin: 5
|
|
|
|
anchors.right: parent.right
|
|
|
|
anchors.left: parent.left
|
|
|
|
|
|
|
|
RowLayout {
|
|
|
|
id: nativeSubtitles
|
|
|
|
visible: true
|
|
|
|
anchors.left: subtitlesBar.left
|
|
|
|
anchors.right: subtitlesBar.right
|
|
|
|
height: childrenRect.height
|
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
anchors.bottomMargin: 10
|
|
|
|
|
2018-11-19 12:24:13 +00:00
|
|
|
Item {
|
2018-11-10 19:55:59 +00:00
|
|
|
id: subsContainer
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
|
|
|
Layout.rightMargin: 0
|
|
|
|
Layout.leftMargin: 0
|
|
|
|
Layout.maximumWidth: nativeSubtitles.width
|
|
|
|
height: childrenRect.height
|
|
|
|
|
|
|
|
Label {
|
|
|
|
id: nativeSubs
|
|
|
|
objectName: "nativeSubs"
|
|
|
|
onWidthChanged: {
|
|
|
|
|
|
|
|
if (width > parent.width - 10)
|
|
|
|
width = parent.width - 10
|
|
|
|
}
|
|
|
|
onTextChanged: if (width <= parent.width - 10)
|
|
|
|
width = undefined
|
|
|
|
color: "white"
|
|
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
|
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
|
|
|
font.pixelSize: Screen.height / 24
|
|
|
|
font.family: appearance.fontName
|
|
|
|
horizontalAlignment: Text.AlignHCenter
|
|
|
|
opacity: 1
|
|
|
|
background: Rectangle {
|
|
|
|
id: subsBackground
|
2018-11-19 04:26:08 +00:00
|
|
|
color: appearance.mainBackground
|
2018-11-10 19:55:59 +00:00
|
|
|
width: subsContainer.childrenRect.width
|
|
|
|
height: subsContainer.childrenRect.height
|
|
|
|
}
|
2018-11-17 15:45:21 +00:00
|
|
|
Component.onCompleted: {
|
2018-11-23 08:19:28 +00:00
|
|
|
player.subtitlesChanged.connect(function (subtitles) {
|
2018-11-17 15:45:21 +00:00
|
|
|
text = subtitles
|
|
|
|
})
|
|
|
|
}
|
2018-11-10 19:55:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Rectangle {
|
|
|
|
id: controlsBackground
|
2018-11-23 08:19:28 +00:00
|
|
|
height: controlsBar.visible ? controlsBar.height
|
|
|
|
+ (fun.nyanCat ? progressBackground.height
|
|
|
|
* 0.3 : progressBackground.height * 2) : 0
|
2018-11-10 19:55:59 +00:00
|
|
|
anchors.bottom: parent.bottom
|
|
|
|
anchors.left: parent.left
|
|
|
|
anchors.right: parent.right
|
|
|
|
Layout.fillWidth: true
|
|
|
|
Layout.fillHeight: true
|
2018-11-19 04:26:08 +00:00
|
|
|
color: appearance.mainBackground
|
2018-11-10 19:55:59 +00:00
|
|
|
}
|
|
|
|
|
2018-11-19 12:24:13 +00:00
|
|
|
Item {
|
2018-11-10 19:55:59 +00:00
|
|
|
id: controlsBar
|
|
|
|
height: controlsBar.visible ? Screen.height / 24 : 0
|
|
|
|
anchors.right: parent.right
|
|
|
|
anchors.rightMargin: parent.width / 128
|
|
|
|
anchors.left: parent.left
|
|
|
|
anchors.leftMargin: parent.width / 128
|
|
|
|
anchors.bottom: parent.bottom
|
2018-11-22 17:20:58 +00:00
|
|
|
anchors.bottomMargin: 2
|
2018-11-10 19:55:59 +00:00
|
|
|
visible: true
|
|
|
|
|
|
|
|
Slider {
|
|
|
|
id: progressBar
|
|
|
|
objectName: "progressBar"
|
|
|
|
to: 1
|
|
|
|
value: 0.0
|
|
|
|
anchors.bottom: parent.top
|
|
|
|
anchors.left: parent.left
|
|
|
|
anchors.right: parent.right
|
|
|
|
anchors.bottomMargin: 0
|
|
|
|
anchors.topMargin: progressBackground.height
|
|
|
|
bottomPadding: 0
|
2018-11-17 15:45:21 +00:00
|
|
|
Component.onCompleted: {
|
2018-11-23 08:19:28 +00:00
|
|
|
player.positionChanged.connect(function (position) {
|
|
|
|
if (!pressed) {
|
|
|
|
progressBar.value = position
|
|
|
|
}
|
2018-11-17 15:45:21 +00:00
|
|
|
})
|
2018-11-23 08:19:28 +00:00
|
|
|
player.durationChanged.connect(function (duration) {
|
2018-11-17 15:45:21 +00:00
|
|
|
progressBar.to = duration
|
|
|
|
})
|
2018-11-23 08:19:28 +00:00
|
|
|
player.cachedDurationChanged.connect(function (duration) {
|
2018-11-24 14:35:34 +00:00
|
|
|
cachedLength.duration = duration
|
2018-11-17 15:45:21 +00:00
|
|
|
})
|
2018-11-10 19:55:59 +00:00
|
|
|
}
|
|
|
|
onMoved: {
|
2018-11-17 19:33:32 +00:00
|
|
|
player.playerCommand(Enums.Commands.SeekAbsolute, value)
|
2018-11-10 19:55:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function getProgressBarHeight(nyan, isMouse) {
|
|
|
|
var x = Math.max(Screen.height / 256, fun.nyanCat ? 12 : 2)
|
|
|
|
return isMouse & !fun.nyanCat ? x * 2 : x
|
|
|
|
}
|
|
|
|
MouseArea {
|
|
|
|
id: mouseAreaProgressBar
|
|
|
|
width: parent.width
|
|
|
|
height: parent.height
|
|
|
|
anchors.fill: parent
|
2018-11-26 16:50:25 +00:00
|
|
|
y: parent.y
|
|
|
|
x: parent.x
|
2018-11-10 19:55:59 +00:00
|
|
|
hoverEnabled: true
|
2018-11-26 16:50:25 +00:00
|
|
|
propagateComposedEvents: false
|
2018-11-10 19:55:59 +00:00
|
|
|
acceptedButtons: Qt.NoButton
|
2018-11-26 16:50:25 +00:00
|
|
|
z: 1
|
|
|
|
onPositionChanged: {
|
|
|
|
var a = (mouseAreaProgressBar.mouseX * (progressBar.to / (progressBackground.width)));
|
|
|
|
hoverProgressLabel.text = utils.createTimestamp(a)
|
|
|
|
}
|
2018-11-10 19:55:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
background: Rectangle {
|
|
|
|
id: progressBackground
|
|
|
|
x: progressBar.leftPadding
|
|
|
|
y: progressBar.topPadding + progressBar.availableHeight / 2 - height / 2
|
|
|
|
width: progressBar.availableWidth
|
2018-11-24 14:35:34 +00:00
|
|
|
height: progressBar.getProgressBarHeight(
|
|
|
|
fun.nyanCat, mouseAreaProgressBar.containsMouse)
|
2018-11-22 17:20:58 +00:00
|
|
|
color: appearance.progressBackgroundColor
|
2018-11-26 16:50:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-22 11:49:51 +00:00
|
|
|
ProgressBar {
|
|
|
|
id: cachedLength
|
2018-11-23 08:19:28 +00:00
|
|
|
background: Item {
|
|
|
|
}
|
2018-11-22 11:49:51 +00:00
|
|
|
contentItem: Item {
|
|
|
|
Rectangle {
|
|
|
|
width: cachedLength.visualPosition * parent.width
|
|
|
|
height: parent.height
|
2018-11-22 17:20:58 +00:00
|
|
|
color: appearance.progressCachedColor
|
2018-11-22 11:49:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
z: 40
|
|
|
|
to: progressBar.to
|
2018-11-24 14:35:34 +00:00
|
|
|
property int duration
|
|
|
|
value: progressBar.value + duration
|
2018-11-22 11:49:51 +00:00
|
|
|
anchors.fill: parent
|
|
|
|
}
|
2018-11-24 14:35:34 +00:00
|
|
|
|
|
|
|
Item {
|
|
|
|
anchors.fill: parent
|
|
|
|
id: chapterMarkers
|
|
|
|
Component.onCompleted: {
|
|
|
|
player.chaptersChanged.connect(chaptersChanged)
|
2018-11-23 08:19:28 +00:00
|
|
|
}
|
2018-11-24 14:35:34 +00:00
|
|
|
function chaptersChanged(chapters) {
|
|
|
|
for (var i = 0, len = chapters.length; i < len; i++) {
|
|
|
|
var chapter = chapters[i]
|
|
|
|
var component = Qt.createComponent(
|
|
|
|
"ChapterMarker.qml")
|
|
|
|
|
|
|
|
var marker = component.createObject(chapterMarkers,
|
|
|
|
{
|
|
|
|
time: chapter["time"]
|
|
|
|
})
|
2018-11-22 11:49:51 +00:00
|
|
|
}
|
2018-11-10 19:55:59 +00:00
|
|
|
}
|
|
|
|
}
|
2018-11-24 14:35:34 +00:00
|
|
|
|
|
|
|
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:/player/icons/rainbow.png"
|
|
|
|
fillMode: Image.TileHorizontally
|
|
|
|
}
|
|
|
|
}
|
2018-11-10 19:55:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
handle: Rectangle {
|
2018-11-22 11:49:51 +00:00
|
|
|
z: 70
|
2018-11-10 19:55:59 +00:00
|
|
|
id: handleRect
|
|
|
|
x: progressBar.leftPadding + progressBar.visualPosition
|
2018-11-23 08:19:28 +00:00
|
|
|
* (progressBar.availableWidth - width)
|
2018-11-10 19:55:59 +00:00
|
|
|
y: progressBar.topPadding + progressBar.availableHeight / 2 - height / 2
|
|
|
|
implicitHeight: radius
|
|
|
|
implicitWidth: radius
|
|
|
|
radius: 12 + (progressBackground.height / 2)
|
2018-11-19 13:01:38 +00:00
|
|
|
color: fun.nyanCat ? "transparent" : appearance.progressSliderColor
|
2018-11-10 19:55:59 +00:00
|
|
|
AnimatedImage {
|
2018-11-22 11:49:51 +00:00
|
|
|
z: 80
|
2018-11-10 19:55:59 +00:00
|
|
|
visible: fun.nyanCat
|
|
|
|
paused: progressBar.pressed
|
|
|
|
height: 30
|
|
|
|
id: nyanimation
|
|
|
|
anchors.centerIn: parent
|
|
|
|
source: "qrc:/player/icons/nyancat.gif"
|
|
|
|
fillMode: Image.PreserveAspectFit
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-23 08:19:28 +00:00
|
|
|
RowLayout {
|
|
|
|
id: layout
|
|
|
|
anchors.fill: parent
|
|
|
|
spacing: 2
|
2018-11-22 17:20:58 +00:00
|
|
|
|
2018-11-23 08:19:28 +00:00
|
|
|
Button {
|
|
|
|
id: playlistPrevButton
|
|
|
|
objectName: "playlistPrevButton"
|
|
|
|
icon.source: "icons/prev.svg"
|
|
|
|
icon.color: appearance.buttonColor
|
|
|
|
display: AbstractButton.IconOnly
|
|
|
|
visible: false
|
|
|
|
width: visible ? playPauseButton.width : 0
|
|
|
|
onClicked: {
|
|
|
|
player.playerCommand(Enums.Commands.PreviousPlaylistItem)
|
|
|
|
}
|
|
|
|
background: Item {
|
|
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
|
|
player.playlistPositionChanged.connect(function (position) {
|
|
|
|
if (position != 0) {
|
|
|
|
visible = true
|
|
|
|
} else {
|
|
|
|
visible = false
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2018-11-17 15:45:21 +00:00
|
|
|
}
|
2018-11-10 19:55:59 +00:00
|
|
|
|
2018-11-23 08:19:28 +00:00
|
|
|
Button {
|
|
|
|
id: playPauseButton
|
|
|
|
icon.source: "icons/pause.svg"
|
|
|
|
icon.color: appearance.buttonColor
|
|
|
|
display: AbstractButton.IconOnly
|
|
|
|
onClicked: {
|
|
|
|
player.playerCommand(Enums.Commands.TogglePlayPause)
|
|
|
|
}
|
|
|
|
background: Item {
|
|
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
|
|
player.playStatusChanged.connect(function (status) {
|
|
|
|
if (status == Enums.PlayStatus.Playing) {
|
|
|
|
icon.source = "qrc:/player/icons/pause.svg"
|
|
|
|
} else if (status == Enums.PlayStatus.Paused) {
|
|
|
|
icon.source = "qrc:/player/icons/play.svg"
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2018-11-17 15:45:21 +00:00
|
|
|
}
|
2018-11-10 19:55:59 +00:00
|
|
|
|
2018-11-23 08:19:28 +00:00
|
|
|
Button {
|
|
|
|
id: playlistNextButton
|
|
|
|
//icon.name: "next"
|
|
|
|
icon.source: "icons/next.svg"
|
|
|
|
icon.color: appearance.buttonColor
|
|
|
|
display: AbstractButton.IconOnly
|
|
|
|
onClicked: {
|
|
|
|
player.playerCommand(Enums.Commands.NextPlaylistItem)
|
|
|
|
}
|
|
|
|
background: Item {
|
|
|
|
}
|
2018-11-10 19:55:59 +00:00
|
|
|
}
|
|
|
|
|
2018-11-23 08:19:28 +00:00
|
|
|
Button {
|
|
|
|
id: volumeButton
|
|
|
|
objectName: "volumeButton"
|
|
|
|
icon.source: "icons/volume-up.svg"
|
|
|
|
icon.color: appearance.buttonColor
|
|
|
|
display: AbstractButton.IconOnly
|
|
|
|
onClicked: {
|
|
|
|
player.playerCommand(Enums.Commands.ToggleMute)
|
|
|
|
}
|
|
|
|
background: Item {
|
|
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
|
|
player.volumeStatusChanged.connect(function (status) {
|
|
|
|
if (status == Enums.VolumeStatus.Muted) {
|
|
|
|
volumeButton.icon.source = "qrc:/player/icons/volume-mute.svg"
|
|
|
|
} else if (status == Enums.VolumeStatus.Low) {
|
|
|
|
volumeButton.icon.source = "qrc:/player/icons/volume-down.svg"
|
|
|
|
} else if (status == Enums.VolumeStatus.Normal) {
|
|
|
|
volumeButton.icon.source = "qrc:/player/icons/volume-up.svg"
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
2018-11-17 15:45:21 +00:00
|
|
|
}
|
2018-11-23 08:19:28 +00:00
|
|
|
Slider {
|
|
|
|
id: volumeBar
|
|
|
|
to: 100
|
|
|
|
value: 100
|
|
|
|
palette.dark: "#f00"
|
2018-11-10 19:55:59 +00:00
|
|
|
|
2018-11-23 08:19:28 +00:00
|
|
|
implicitWidth: Math.max(
|
|
|
|
background ? background.implicitWidth : 0,
|
|
|
|
(handle ? handle.implicitWidth : 0)
|
|
|
|
+ leftPadding + rightPadding)
|
|
|
|
implicitHeight: Math.max(
|
|
|
|
background ? background.implicitHeight : 0,
|
|
|
|
(handle ? handle.implicitHeight : 0)
|
|
|
|
+ topPadding + bottomPadding)
|
|
|
|
onMoved: {
|
|
|
|
player.playerCommand(Enums.Commands.SetVolume,
|
|
|
|
Math.round(volumeBar.value).toString())
|
|
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
|
|
player.volumeChanged.connect(function (volume) {
|
|
|
|
volumeBar.value = volume
|
|
|
|
})
|
|
|
|
}
|
|
|
|
handle: Rectangle {
|
|
|
|
x: volumeBar.leftPadding + volumeBar.visualPosition
|
|
|
|
* (volumeBar.availableWidth - width)
|
|
|
|
y: volumeBar.topPadding + volumeBar.availableHeight / 2 - height / 2
|
|
|
|
implicitWidth: 12
|
|
|
|
implicitHeight: 12
|
|
|
|
radius: 12
|
|
|
|
color: "#f6f6f6"
|
|
|
|
border.color: "#f6f6f6"
|
|
|
|
}
|
2018-11-10 19:55:59 +00:00
|
|
|
|
2018-11-23 08:19:28 +00:00
|
|
|
background: Rectangle {
|
|
|
|
x: volumeBar.leftPadding
|
|
|
|
y: volumeBar.topPadding + volumeBar.availableHeight / 2 - height / 2
|
|
|
|
implicitWidth: 60
|
|
|
|
implicitHeight: 3
|
|
|
|
width: volumeBar.availableWidth
|
|
|
|
height: implicitHeight
|
|
|
|
color: "#33333311"
|
|
|
|
Rectangle {
|
|
|
|
width: volumeBar.visualPosition * parent.width
|
|
|
|
height: parent.height
|
|
|
|
color: "white"
|
|
|
|
}
|
2018-11-10 19:55:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-23 08:19:28 +00:00
|
|
|
Text {
|
|
|
|
id: timeLabel
|
|
|
|
objectName: "timeLabel"
|
|
|
|
text: "0:00 / 0:00"
|
|
|
|
color: "white"
|
|
|
|
padding: 2
|
|
|
|
font.family: appearance.fontName
|
|
|
|
font.pixelSize: 14
|
|
|
|
verticalAlignment: Text.AlignVCenter
|
|
|
|
renderType: Text.NativeRendering
|
|
|
|
Component.onCompleted: {
|
|
|
|
player.durationStringChanged.connect(
|
|
|
|
function (durationString) {
|
|
|
|
text = durationString
|
|
|
|
})
|
|
|
|
}
|
2018-11-17 15:45:21 +00:00
|
|
|
}
|
2018-11-10 19:55:59 +00:00
|
|
|
|
2018-11-23 08:19:28 +00:00
|
|
|
Item {
|
|
|
|
Layout.fillWidth: true
|
|
|
|
}
|
2018-11-22 17:20:58 +00:00
|
|
|
|
2018-11-23 08:19:28 +00:00
|
|
|
Button {
|
|
|
|
id: settingsButton
|
|
|
|
//icon.name: "settings"
|
|
|
|
icon.source: "icons/settings.svg"
|
|
|
|
icon.color: appearance.buttonColor
|
|
|
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
|
|
|
display: AbstractButton.IconOnly
|
|
|
|
onClicked: {
|
|
|
|
console.log("Settings Menu Not Yet Implemented.")
|
|
|
|
}
|
|
|
|
background: Item {
|
|
|
|
}
|
2018-11-10 19:55:59 +00:00
|
|
|
}
|
|
|
|
|
2018-11-23 08:19:28 +00:00
|
|
|
Button {
|
|
|
|
id: fullscreenButton
|
|
|
|
//icon.name: "fullscreen"
|
|
|
|
icon.source: "icons/fullscreen.svg"
|
|
|
|
icon.color: appearance.buttonColor
|
|
|
|
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
2018-11-22 17:20:58 +00:00
|
|
|
|
2018-11-23 08:19:28 +00:00
|
|
|
display: AbstractButton.IconOnly
|
|
|
|
onClicked: {
|
|
|
|
toggleFullscreen()
|
|
|
|
}
|
2018-11-10 19:55:59 +00:00
|
|
|
|
2018-11-23 08:19:28 +00:00
|
|
|
background: Item {
|
|
|
|
}
|
|
|
|
}
|
2018-11-10 19:55:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|