1
0
Fork 0

[UI+Backend] Major refactor. Added niconico theme and made components more split up. Used Connections for signals.

This commit is contained in:
NamedKitten 2018-11-28 18:41:54 +00:00
parent bf0bee446a
commit 114662c17d
50 changed files with 735 additions and 498 deletions

View file

@ -14,7 +14,11 @@ find_package(Qt5Gui REQUIRED)
find_package(Qt5 CONFIG REQUIRED COMPONENTS Qml Quick Gui Widgets Core X11Extras)
find_package(Qt5QuickCompiler)
if(DEVELOP)
qt5_add_resources(QT_RESOURCES qml.qrc)
else()
qtquick_compiler_add_resources(qml_QRC src/qml/qml.qrc)
endif()
find_package(PkgConfig)
pkg_check_modules(MPV REQUIRED mpv)

View file

@ -581,4 +581,3 @@ MpvPlayerBackend::createRenderer() const
window()->setPersistentSceneGraph(true);
return new MpvRenderer(const_cast<MpvPlayerBackend*>(this));
}

View file

@ -106,23 +106,22 @@ main(int argc, char* argv[])
QSettings settings;
QString backendSetting = settings.value("Backend/backend", "").toString();
if (backendSetting.length() == 0) {
#ifndef DISABLE_MpvPlayerBackend
settings.setValue("Backend/backend", "mpv");
#else
settings.setValue("Backend/backend", "direct-mpv");
#endif
#ifndef DISABLE_MpvPlayerBackend
settings.setValue("Backend/backend", "mpv");
#else
settings.setValue("Backend/backend", "direct-mpv");
#endif
}
qDebug() << backendSetting;
qDebug() << backendSetting;
for (int i = 1; i < argc; ++i) {
if (!qstrcmp(argv[i], "--update")) {
Utils::updateAppImage();
}
else if (!qstrcmp(argv[i], "--backend=mpv") || backendSetting == "mpv") {
} else if (!qstrcmp(argv[i], "--backend=mpv") || backendSetting == "mpv") {
backend = Enums::Backends::MpvBackend;
}
else if (!qstrcmp(argv[i], "--backend=direct-mpv") || backendSetting == "direct-mpv") {
} else if (!qstrcmp(argv[i], "--backend=direct-mpv") ||
backendSetting == "direct-mpv") {
backend = Enums::Backends::DirectMpvBackend;
}
}
@ -141,19 +140,20 @@ main(int argc, char* argv[])
qRegisterMetaType<Enums::Backends>("Enums.Backends");
qRegisterMetaType<Enums::Commands>("Enums.Commands");
qmlRegisterType<UtilsClass>("player", 1, 0, "Utils");
switch (backend) {
case Enums::Backends::MpvBackend: {
#ifndef DISABLE_MpvPlayerBackend
qmlRegisterType<MpvPlayerBackend>("player", 1, 0, "PlayerBackend");
#else
qDebug() << "Normal MPV backend not available, resetting backend option to blank.";
settings.setValue("Backend/backend", "direct-mpv");
app.exit();
#endif
break;
#ifndef DISABLE_MpvPlayerBackend
qmlRegisterType<MpvPlayerBackend>("player", 1, 0, "PlayerBackend");
#else
qDebug() << "Normal MPV backend not available, resetting backend option "
"to blank.";
settings.setValue("Backend/backend", "direct-mpv");
app.exit();
#endif
break;
}
case Enums::Backends::DirectMpvBackend: {
qmlRegisterType<DirectMpvPlayerBackend>("player", 1, 0, "PlayerBackend");
@ -171,7 +171,7 @@ main(int argc, char* argv[])
rt->setMainQmlFilename("main.qml");
rt->reload();
#else
engine.load(QUrl(QStringLiteral("qrc:///player/main.qml")));
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
#endif
return app.exec();

View file

@ -8,6 +8,7 @@ import Qt.labs.platform 1.0 as LabsPlatform
import player 1.0
Item {
id: controlsBarItem
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
@ -17,6 +18,23 @@ Item {
property var controls: controlsBar
property var duration: progressBar.to
Component.onCompleted: {
setControlsTheme(appearance.themeName)
}
function setControlsTheme(themeName) {
for (var i = 0; i < controlsBar.children.length; ++i) {
if (controlsBar.children[i].objectName == "buttonLayout") {
controlsBar.children[i].destroy()
}
}
var component = Qt.createComponent(themeName + "ButtonLayout.qml")
component.createObject(controlsBar, {
anchors.fill: controlsBar
})
}
Item {
id: subtitlesBar
visible: !appearance.useMpvSubs
@ -67,10 +85,12 @@ Item {
width: subsContainer.childrenRect.width
height: subsContainer.childrenRect.height
}
Component.onCompleted: {
player.subtitlesChanged.connect(function (subtitles) {
text = subtitles
})
Connections {
target: player
enabled: true
onSubtitlesChanged: function (subtitles) {
nativeSubs.text = subtitles
}
}
}
}
@ -79,9 +99,8 @@ Item {
Rectangle {
id: controlsBackground
height: controlsBar.visible ? controlsBar.height
+ (fun.nyanCat ? progressBackground.height
* 0.3 : progressBackground.height * 2) : 0
height: controlsBar.visible ? controlsBar.height + progressBar.topPadding
+ (fun.nyanCat ? 0 : 1) : 0
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
@ -100,353 +119,13 @@ Item {
anchors.bottom: parent.bottom
anchors.bottomMargin: 2
visible: true
Slider {
VideoProgress {
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
Component.onCompleted: {
player.positionChanged.connect(function (position) {
if (!pressed) {
progressBar.value = position
}
})
player.durationChanged.connect(function (duration) {
progressBar.to = duration
})
player.cachedDurationChanged.connect(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)
return isMouse & !fun.nyanCat ? x * 2 : x
}
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
Component.onCompleted: {
player.chaptersChanged.connect(chaptersChanged)
}
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"]
})
}
}
}
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
}
}
}
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
AnimatedImage {
z: 80
visible: fun.nyanCat
paused: progressBar.pressed
height: 30
id: nyanimation
anchors.centerIn: parent
source: "qrc:/player/icons/nyancat.gif"
fillMode: Image.PreserveAspectFit
}
}
}
RowLayout {
id: layout
anchors.fill: parent
spacing: 2
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
}
})
}
}
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"
}
})
}
}
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 {
}
}
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"
}
})
}
}
Slider {
id: volumeBar
to: 100
value: 100
palette.dark: "#f00"
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"
}
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"
}
}
}
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
})
}
}
Item {
Layout.fillWidth: true
}
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 {
}
}
Button {
id: fullscreenButton
//icon.name: "fullscreen"
icon.source: "icons/fullscreen.svg"
icon.color: appearance.buttonColor
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
display: AbstractButton.IconOnly
onClicked: {
toggleFullscreen()
}
background: Item {
}
}
}
}
}

View file

@ -1,75 +0,0 @@
import QtQuick 2.11
import QtQuick.Controls 2.4
import Qt.labs.settings 1.0
ComboBox {
id: control
width: parent.width
height: 10
indicator: Canvas {
id: canvas
x: control.width - width - control.rightPadding
y: control.topPadding + (control.availableHeight - height) / 2
width: 12
height: 8
contextType: "2d"
Connections {
target: control
onPressedChanged: canvas.requestPaint()
}
onPaint: {
context.reset()
context.moveTo(0, 0)
context.lineTo(width, 0)
context.lineTo(width / 2, height)
context.closePath()
context.fillStyle = control.pressed ? "#17a81a" : "#21be2b"
context.fill()
}
}
contentItem: Text {
leftPadding: 2
rightPadding: control.indicator.width + control.spacing
text: control.displayText
font.family: appearance.fontName
color: control.pressed ? "#5a50da" : "white"
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
}
background: Rectangle {
implicitWidth: 120
implicitHeight: 40
color: "transparent"
}
popup: Popup {
y: control.height - 1
width: control.width
implicitHeight: contentItem.implicitHeight
padding: 1
contentItem: ListView {
clip: true
implicitHeight: contentHeight
model: control.popup.visible ? control.delegateModel : null
currentIndex: control.highlightedIndex
highlight: Rectangle {
color: "white"
opacity: 1
}
ScrollIndicator.vertical: ScrollIndicator {
}
}
background: Rectangle {
opacity: 0.6
color: "orange"
}
}
}

View file

@ -12,19 +12,20 @@ Dialog {
height: Math.max(480, childrenRect.height * playlistListView.count)
width: 720
modality: Qt.NonModal
Component.onCompleted: {
player.playlistChanged.connect(updatePlaylistMenu)
}
function updatePlaylistMenu(playlist) {
playlistModel.clear()
for (var thing in playlist) {
var item = playlist[thing]
playlistModel.append({
playlistItemTitle: item["title"],
playlistItemFilename: item["filename"],
current: item["current"],
playlistPos: thing
})
Connections {
target: player
enabled: true
onPlaylistChanged: function(playlist) {
playlistModel.clear()
for (var thing in playlist) {
var item = playlist[thing]
playlistModel.append({
playlistItemTitle: item["title"],
playlistItemFilename: item["filename"],
current: item["current"],
playlistPos: thing
})
}
}
}

View file

@ -7,8 +7,10 @@ Rectangle {
id: chapterMarker
property int time: 0
color: appearance.chapterMarkerColor
Component.onCompleted: {
player.chaptersChanged.connect(chapterMarker.destroy)
Connections {
target: player
enabled: true
onChaptersChanged: {chapterMarker.destroy()}
}
width: 4

View file

@ -20,8 +20,12 @@ MenuBar {
}
}
Component.onCompleted: {
player.tracksChanged.connect(updateTracks)
Connections {
target: player
enabled: true
onTracksChanged: function (tracks) {
menuBar.updateTracks(tracks)
}
}
function updateTracks(tracks) {
@ -340,8 +344,12 @@ MenuBar {
id: audioDeviceMenu
objectName: "audioDeviceMenu"
Component.onCompleted: {
player.audioDevicesChanged.connect(updateAudioDevices)
Connections {
target: player
enabled: true
onAudioDevicesChanged: function (ad) {
audioDeviceMenu.updateAudioDevices(ad)
}
}
function updateAudioDevices(audioDevices) {
for (var i = 0, len = audioDeviceMenu.count; i < len; i++) {

View file

@ -0,0 +1,76 @@
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 {
objectName: "buttonLayout"
id: layout
PlayPauseButton {
id: playPauseButton
anchors.top: parent.top
anchors.bottom: parent.bottom
height: 16
width: 26
icon.height: 16
icon.width: 26
}
VolumeButton {
id: volumeButton
anchors.left: playPauseButton.right
anchors.top: parent.top
anchors.bottom: parent.bottom
icon.height: 16
icon.width: 16
}
VolumeSlider {
anchors.left: volumeButton.right
anchors.top: parent.top
anchors.bottom: parent.bottom
}
PlaylistPrevButton {
id: playlistPrevButton
anchors.right: timeLabel.left
anchors.top: parent.top
anchors.bottom: parent.bottom
icon.height: 16
icon.width: 16
}
TimeLabel {
id: timeLabel
anchors.centerIn: parent
anchors.top: parent.top
anchors.bottom: parent.bottom
}
PlaylistNextButton {
id: playlistNextButton
anchors.left: timeLabel.right
anchors.top: parent.top
anchors.bottom: parent.bottom
icon.height: 16
icon.width: 16
}
FullscreenButton {
id: fullscreenButton
anchors.right: settingsButton.left
anchors.top: parent.top
anchors.bottom: parent.bottom
icon.height: 16
icon.width: 16
}
SettingsButton {
id: settingsButton
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
icon.height: 16
icon.width: 16
}
}

View file

@ -0,0 +1,24 @@
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: fullscreenButton
//icon.name: "fullscreen"
icon.source: "icons/" + appearance.themeName + "/fullscreen.svg"
icon.color: appearance.buttonColor
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
display: AbstractButton.IconOnly
onClicked: {
toggleFullscreen()
}
background: Item {
}
}

View file

@ -0,0 +1,32 @@
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: playPauseButton
icon.source: "icons/" + appearance.themeName + "/pause.svg"
icon.color: appearance.buttonColor
display: AbstractButton.IconOnly
onClicked: {
player.playerCommand(Enums.Commands.TogglePlayPause)
}
background: Item {
}
Connections {
target: player
enabled: true
onPlayStatusChanged: function (status) {
console.log(icon.height)
if (status == Enums.PlayStatus.Playing) {
icon.source = "qrc:/icons/" + appearance.themeName + "/pause.svg"
} else if (status == Enums.PlayStatus.Paused) {
icon.source = "qrc:/icons/" + appearance.themeName + "/play.svg"
}
}
}
}

View file

@ -0,0 +1,23 @@
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: playlistNextButton
//icon.name: "next"
icon.source: "icons/" + appearance.themeName + "/next.svg"
icon.color: appearance.buttonColor
display: AbstractButton.IconOnly
onClicked: {
player.playerCommand(Enums.Commands.NextPlaylistItem)
}
background: Item {
}
}

View file

@ -0,0 +1,37 @@
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: playlistPrevButton
objectName: "playlistPrevButton"
icon.source: "icons/" + appearance.themeName + "/prev.svg"
icon.color: appearance.buttonColor
display: AbstractButton.IconOnly
visible: appearance.themeName == "Youtube" ? false : true
onClicked: {
player.playerCommand(Enums.Commands.PreviousPlaylistItem)
}
background: Item {
}
Connections {
target: player
enabled: true
onPlaylistPositionChanged: function (position) {
if (appearance.themeName == "YouTube") {
if (position != 0) {
visible = true
} else {
visible = false
}
}
}
}
}

View file

@ -0,0 +1,24 @@
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: settingsButton
//icon.name: "settings"
icon.source: "icons/" + appearance.themeName + "/settings.svg"
icon.color: appearance.buttonColor
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
display: AbstractButton.IconOnly
onClicked: {
appearance.themeName = appearance.themeName == "YouTube" ? "Niconico" : "YouTube"
controlsBarItem.setControlsTheme(appearance.themeName)
console.log("Settings Menu Not Yet Implemented.")
}
background: Item {
}
}

View file

@ -0,0 +1,27 @@
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
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
Connections {
target: player
enabled: true
onDurationStringChanged: function (durationString) {
timeLabel.text = durationString
}
}
}

View file

@ -0,0 +1,181 @@
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
Slider {
id: progressBar
objectName: "progressBar"
to: 1
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 {
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
}
}
}

View file

@ -0,0 +1,38 @@
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: 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");
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"
}
}
}
}

View file

@ -0,0 +1,63 @@
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
Slider {
id: volumeBar
to: 100
value: 100
palette.dark: "#f00"
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())
}
Connections {
target: player
enabled: true
onVolumeChanged: 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
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
}
}
}

View file

@ -0,0 +1,64 @@
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 {
objectName: "buttonLayout"
id: layout
PlaylistPrevButton {
id: playlistPrevButton
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: visible ? playlistNextButton.width : 0
}
PlayPauseButton {
id: playPauseButton
anchors.left: playlistPrevButton.right
anchors.top: parent.top
anchors.bottom: parent.bottom
}
PlaylistNextButton {
id: playlistNextButton
anchors.left: playPauseButton.right
anchors.top: parent.top
anchors.bottom: parent.bottom
}
VolumeButton {
id: volumeButton
anchors.left: playlistNextButton.right
anchors.top: parent.top
anchors.bottom: parent.bottom
}
VolumeSlider {
id: volumeSlider
anchors.left: volumeButton.right
anchors.top: parent.top
anchors.bottom: parent.bottom
}
TimeLabel {
anchors.left: volumeSlider.right
anchors.top: parent.top
anchors.bottom: parent.bottom
}
SettingsButton {
id: settingsButton
anchors.right: fullscreenButton.left
anchors.top: parent.top
anchors.bottom: parent.bottom
}
FullscreenButton {
id: fullscreenButton
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
}
}

View file

@ -0,0 +1 @@
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.4" class="EnableFullScreenButton-icon"><path d="M60 92a4 4 0 0 1 4-4h15.5L59 67.5a4 4 0 0 1 0-5.7l2.8-2.8a4 4 0 0 1 5.7 0L88 79.5V64a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v32a4 4 0 0 1-4 4H64a4 4 0 0 1-4-4v-4zM40 8a4 4 0 0 1-4 4H20.5L41 32.5a4 4 0 0 1 0 5.7L38.2 41a4 4 0 0 1-5.7 0L12 20.5V36a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V4a4 4 0 0 1 4-4h32a4 4 0 0 1 4 4v4z"></path></svg>

After

Width:  |  Height:  |  Size: 512 B

View file

@ -0,0 +1 @@
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.4" class="PlayerSkipNextButton-icon"><path d="M34.6 46.6a4 4 0 0 1 0 6.8L6 71.2A4 4 0 0 1 0 67.8V32.2a4 4 0 0 1 6.1-3.4l28.5 17.8zM74.6 46.6a4 4 0 0 1 0 6.8L46 71.2a4 4 0 0 1-6.1-3.4V32.2a4 4 0 0 1 6.1-3.4l28.5 17.8zM100 4a4 4 0 0 0-4-4h-8a4 4 0 0 0-4 4v92a4 4 0 0 0 4 4h8a4 4 0 0 0 4-4V4z"></path></svg>

After

Width:  |  Height:  |  Size: 452 B

View file

@ -0,0 +1 @@
<svg viewBox="0 0 88 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.4" class="PlayerPauseButton-icon"><path d="M32 4a4 4 0 0 0-4-4H4a4 4 0 0 0-4 4v92a4 4 0 0 0 4 4h24a4 4 0 0 0 4-4V4zM88 4a4 4 0 0 0-4-4H60a4 4 0 0 0-4 4v92a4 4 0 0 0 4 4h24a4 4 0 0 0 4-4V4z"></path></svg>

After

Width:  |  Height:  |  Size: 350 B

View file

@ -0,0 +1 @@
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.4" class="PlayerPlayButton-icon"><path d="M95 42a8.9 8.9 0 0 1 0 16L12.9 99A8.9 8.9 0 0 1 0 91.2V9a8.9 8.9 0 0 1 12.8-8C33.2 11.1 73 31 95.1 42.1z"></path></svg>

After

Width:  |  Height:  |  Size: 309 B

View file

@ -0,0 +1 @@
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.4" class="SeekToHeadButton-icon"><path d="M65.4 46.6a4 4 0 0 0 0 6.8L94 71.2a4 4 0 0 0 6.1-3.4V32.2a4 4 0 0 0-6.1-3.4L65.4 46.6zM25.4 46.6a4 4 0 0 0 0 6.8L54 71.2a4 4 0 0 0 6.1-3.4V32.2a4 4 0 0 0-6.1-3.4L25.4 46.6zM0 4a4 4 0 0 1 4-4h8a4 4 0 0 1 4 4v92a4 4 0 0 1-4 4H4a4 4 0 0 1-4-4V4z"></path></svg>

After

Width:  |  Height:  |  Size: 447 B

View file

@ -0,0 +1 @@
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.4" class="PlayerOptionButton-icon"><path d="M56.5 3.2A4 4 0 0 0 53 0H47a4 4 0 0 0-3.6 3L41 14a4 4 0 0 1-2.6 2.9c-1.3.4-2.5 1-3.7 1.5a4 4 0 0 1-3.9-.2l-9.3-5.8a4 4 0 0 0-4.8.4 52.2 52.2 0 0 0-4 4 4 4 0 0 0-.4 4.8l5.8 9.3a4 4 0 0 1 .2 4c-.6 1.1-1 2.3-1.5 3.6a4 4 0 0 1-2.9 2.6L3.2 43.5A4 4 0 0 0 0 47V53a4 4 0 0 0 3 3.6L14 59a4 4 0 0 1 2.9 2.6c.4 1.3 1 2.5 1.5 3.7a4 4 0 0 1-.2 3.9l-5.8 9.3a4 4 0 0 0 .4 4.8c1.2 1.4 2.6 2.8 4 4a4 4 0 0 0 4.8.4l9.3-5.8a4 4 0 0 1 4-.2c1.1.6 2.3 1 3.6 1.5a4 4 0 0 1 2.6 3l2.5 10.6A4 4 0 0 0 47 100H53a4 4 0 0 0 3.6-3L59 86a4 4 0 0 1 2.6-2.9c1.3-.4 2.5-1 3.7-1.5a4 4 0 0 1 3.9.2l9.3 5.8a4 4 0 0 0 4.8-.4c1.4-1.2 2.8-2.6 4-4a4 4 0 0 0 .4-4.8L82 69.2a4 4 0 0 1-.2-4c.6-1.1 1-2.3 1.5-3.6a4 4 0 0 1 3-2.6l10.6-2.5A4 4 0 0 0 100 53V47a4 4 0 0 0-3-3.6L86 41a4 4 0 0 1-2.9-2.6c-.4-1.3-1-2.5-1.5-3.7a4 4 0 0 1 .2-3.9l5.8-9.3a4 4 0 0 0-.4-4.8 52.2 52.2 0 0 0-4-4 4 4 0 0 0-4.8-.4L69.2 18a4 4 0 0 1-4 .2c-1.1-.6-2.3-1-3.6-1.5a4 4 0 0 1-2.6-2.9L56.5 3.2zm-6.5 27a19.9 19.9 0 0 1 0 39.7 19.9 19.9 0 1 1 0-39.7z"></path></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View file

@ -0,0 +1 @@
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.4" class="MuteVideoButton-icon"><path d="M24.1 24L45.2 1.3a3.7 3.7 0 0 1 4.4-1C51 1.2 52 2.8 52 4.6v91c0 1.8-1 3.4-2.4 4.1-1.5.7-3.2.4-4.4-.9L24.2 76H8a8 8 0 0 1-8-8V32a8 8 0 0 1 8-8h16.1zm51.4-9.3l.5-.7 1.5-1.5a4 4 0 0 1 5.4-.2 49.9 49.9 0 0 1 0 75.3 4 4 0 0 1-5.4-.2A75 75 0 0 1 76 86a4 4 0 0 1 .2-5.8 40 40 0 0 0 9-11.1V69l.1-.2a39.3 39.3 0 0 0 4.4-14v-.3L90 50c0-10.6-4.1-20.2-10.8-27.3l-.1-.2a44 44 0 0 0-1-1H78l-.1-.2a35 35 0 0 0-2-1.8 4 4 0 0 1-.6-.8v-.3a4 4 0 0 1 .1-3.6v-.1zM62.2 27.8l1-1a4 4 0 0 1 5.4-.4l2.5 2.2a30 30 0 0 1-2.7 45v.1a4 4 0 0 1-2.2.7c-1.1 0-2.1-.4-3-1.1l-.9-1-.5-.5a4 4 0 0 1-.6-.8l-.1-.2a4 4 0 0 1 1-5A20 20 0 0 0 70 50a20 20 0 0 0-7.8-15.8A4 4 0 0 1 62 28l.2-.2z"></path></svg>

After

Width:  |  Height:  |  Size: 854 B

View file

@ -0,0 +1 @@
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.4" class="UnMuteVideoButton-icon"><path d="M24.1 24L45.2 1.3a3.7 3.7 0 0 1 4.4-1C51 1.2 52 2.8 52 4.6v91c0 1.8-1 3.4-2.4 4.1-1.5.7-3.2.4-4.4-.9L24.2 76H8a8 8 0 0 1-8-8V32a8 8 0 0 1 8-8h16.1zM80 42.7l11.5-11.4a4.4 4.4 0 0 1 6.1 0l1.1 1a4.4 4.4 0 0 1 0 6.2L87.3 50l11.4 11.5a4.4 4.4 0 0 1 0 6.1l-1 1.1a4.4 4.4 0 0 1-6.2 0L80 57.3 68.5 68.7a4.4 4.4 0 0 1-6.1 0l-1.1-1a4.4 4.4 0 0 1 0-6.2L72.7 50 61.3 38.5a4.4 4.4 0 0 1 0-6.1l1-1.1a4.4 4.4 0 0 1 6.2 0L80 42.7z"></path></svg>

After

Width:  |  Height:  |  Size: 620 B

View file

@ -0,0 +1 @@
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.4" class="MuteVideoButton-icon"><path d="M24.1 24L45.2 1.3a3.7 3.7 0 0 1 4.4-1C51 1.2 52 2.8 52 4.6v91c0 1.8-1 3.4-2.4 4.1-1.5.7-3.2.4-4.4-.9L24.2 76H8a8 8 0 0 1-8-8V32a8 8 0 0 1 8-8h16.1zm51.4-9.3l.5-.7 1.5-1.5a4 4 0 0 1 5.4-.2 49.9 49.9 0 0 1 0 75.3 4 4 0 0 1-5.4-.2A75 75 0 0 1 76 86a4 4 0 0 1 .2-5.8 40 40 0 0 0 9-11.1V69l.1-.2a39.3 39.3 0 0 0 4.4-14v-.3L90 50c0-10.6-4.1-20.2-10.8-27.3l-.1-.2a44 44 0 0 0-1-1H78l-.1-.2a35 35 0 0 0-2-1.8 4 4 0 0 1-.6-.8v-.3a4 4 0 0 1 .1-3.6v-.1zM62.2 27.8l1-1a4 4 0 0 1 5.4-.4l2.5 2.2a30 30 0 0 1-2.7 45v.1a4 4 0 0 1-2.2.7c-1.1 0-2.1-.4-3-1.1l-.9-1-.5-.5a4 4 0 0 1-.6-.8l-.1-.2a4 4 0 0 1 1-5A20 20 0 0 0 70 50a20 20 0 0 0-7.8-15.8A4 4 0 0 1 62 28l.2-.2z"></path></svg>

After

Width:  |  Height:  |  Size: 854 B

View file

@ -1,3 +0,0 @@
# Icons
- Icons where all from https://material.io/tools/icons/?style=baseline
- Exceptions: nyancat.gif

View file

Before

Width:  |  Height:  |  Size: 640 B

After

Width:  |  Height:  |  Size: 640 B

View file

Before

Width:  |  Height:  |  Size: 642 B

After

Width:  |  Height:  |  Size: 642 B

View file

Before

Width:  |  Height:  |  Size: 172 B

After

Width:  |  Height:  |  Size: 172 B

View file

Before

Width:  |  Height:  |  Size: 121 B

After

Width:  |  Height:  |  Size: 121 B

View file

Before

Width:  |  Height:  |  Size: 117 B

After

Width:  |  Height:  |  Size: 117 B

View file

Before

Width:  |  Height:  |  Size: 97 B

After

Width:  |  Height:  |  Size: 97 B

View file

Before

Width:  |  Height:  |  Size: 174 B

After

Width:  |  Height:  |  Size: 174 B

View file

Before

Width:  |  Height:  |  Size: 111 B

After

Width:  |  Height:  |  Size: 111 B

View file

Before

Width:  |  Height:  |  Size: 754 B

After

Width:  |  Height:  |  Size: 754 B

View file

Before

Width:  |  Height:  |  Size: 235 B

After

Width:  |  Height:  |  Size: 235 B

View file

Before

Width:  |  Height:  |  Size: 171 B

After

Width:  |  Height:  |  Size: 171 B

View file

Before

Width:  |  Height:  |  Size: 451 B

After

Width:  |  Height:  |  Size: 451 B

View file

Before

Width:  |  Height:  |  Size: 281 B

After

Width:  |  Height:  |  Size: 281 B

View file

@ -17,7 +17,7 @@ Window {
height: 480
property bool onTop: false
Translator {
id: translate
}
@ -34,6 +34,7 @@ Window {
property bool titleOnlyOnFullscreen: true
property bool clickToPause: true
property bool useMpvSubs: false
property string themeName: "YouTube"
property string fontName: "Roboto"
property string mainBackground: "#9C000000"
property string progressBackgroundColor: "#3CFFFFFF"
@ -41,7 +42,9 @@ Window {
property string buttonColor: "white"
property string progressSliderColor: "red"
property string chapterMarkerColor: "#fc0"
property string volumeSliderBackground: "white"
}
Settings {
id: i18n
category: "I18N"
@ -118,11 +121,11 @@ Window {
mainWindow.visibility = lastScreenVisibility
}
}
Utils {
id: utils
}
PlayerBackend {
id: player
anchors.fill: parent
@ -196,7 +199,7 @@ Window {
}
}
}
Item {
id: controlsOverlay
anchors.centerIn: player
@ -218,7 +221,7 @@ Window {
mouseAreaPlayer.cursorShape = Qt.ArrowCursor
}
}
MouseArea {
id: mouseAreaBar
@ -322,10 +325,12 @@ Window {
visible: controlsOverlay.controlsShowing
&& ((!appearance.titleOnlyOnFullscreen)
|| (mainWindow.visibility == Window.FullScreen))
Component.onCompleted: {
player.titleChanged.connect(function (title) {
text = title
})
Connections {
target: player
enabled: true
onTitleChanged: function (title) {
titleLabel.text = title
}
}
}
}

View file

@ -1,32 +1,51 @@
<RCC>
<qresource prefix="/player">
<qresource prefix="/">
<file>main.qml</file>
<file>ChapterMarker.qml</file>
<file>PlaylistDialog.qml</file>
<file>CustomComboBox.qml</file>
<file>CustomMenuItem.qml</file>
<file>CustomMenu.qml</file>
<file>ControlsBar.qml</file>
<file>MainMenu.qml</file>
<file>TrackItem.qml</file>
<file>AudioDeviceItem.qml</file>
<file>Translator.qml</file>
<file>translations.js</file>
<file>icons/play.svg</file>
<file>icons/pause.svg</file>
<file>icons/forward.svg</file>
<file>icons/backward.svg</file>
<file>icons/settings.svg</file>
<file>icons/fullscreen.svg</file>
<file>icons/volume-up.svg</file>
<file>icons/volume-mute.svg</file>
<file>icons/volume-down.svg</file>
<file>icons/next.svg</file>
<file>icons/prev.svg</file>
<file>icons/subtitles.svg</file>
<file>YouTubeButtonLayout.qml</file>
<file>NiconicoButtonLayout.qml</file>
<file alias="PlaylistPrevButton.qml">UIComponents/PlaylistPrevButton.qml</file>
<file alias="PlayPauseButton.qml">UIComponents/PlayPauseButton.qml</file>
<file alias="VideoProgress.qml">UIComponents/VideoProgress.qml</file>
<file alias="VolumeButton.qml">UIComponents/VolumeButton.qml</file>
<file alias="VolumeSlider.qml">UIComponents/VolumeSlider.qml</file>
<file alias="TimeLabel.qml">UIComponents/TimeLabel.qml</file>
<file alias="SettingsButton.qml">UIComponents/SettingsButton.qml</file>
<file alias="FullscreenButton.qml">UIComponents/FullscreenButton.qml</file>
<file alias="PlaylistNextButton.qml">UIComponents/PlaylistNextButton.qml</file>
<file alias="codes.js">Utils/codes.js</file>
<file alias="Translator.qml">Utils/Translator.qml</file>
<file alias="translations.js">Utils/translations.js</file>
<file alias="ChapterMarkerItem.qml">Items/ChapterMarkerItem.qml</file>
<file alias="TrackItem.qml">Items/TrackItem.qml</file>
<file alias="AudioDeviceItem.qml">Items/AudioDeviceItem.qml</file>
<file alias="CustomMenuItem.qml">Items/CustomMenuItem.qml</file>
<file alias="PlaylistDialog.qml">Dialogs/PlaylistDialog.qml</file>
<file>icons/YouTube/play.svg</file>
<file>icons/YouTube/pause.svg</file>
<file>icons/YouTube/forward.svg</file>
<file>icons/YouTube/backward.svg</file>
<file>icons/YouTube/settings.svg</file>
<file>icons/YouTube/fullscreen.svg</file>
<file>icons/YouTube/volume-up.svg</file>
<file>icons/YouTube/volume-mute.svg</file>
<file>icons/YouTube/volume-down.svg</file>
<file>icons/YouTube/next.svg</file>
<file>icons/YouTube/prev.svg</file>
<file>icons/YouTube/subtitles.svg</file>
<file>icons/YouTube/playlist.svg</file>
<file>icons/Niconico/play.svg</file>
<file>icons/Niconico/pause.svg</file>
<file>icons/Niconico/settings.svg</file>
<file>icons/Niconico/volume-up.svg</file>
<file>icons/Niconico/volume-down.svg</file>
<file>icons/Niconico/volume-mute.svg</file>
<file>icons/Niconico/prev.svg</file>
<file>icons/Niconico/next.svg</file>
<file>icons/Niconico/fullscreen.svg</file>
<file>icons/nyancat.gif</file>
<file>icons/rainbow.png</file>
<file>icons/playlist.svg</file>
<file>codes.js</file>
</qresource>
</RCC>