Refactored the code
@ -1,75 +1,55 @@
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
project(cutefish-videoplayer LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
|
||||
find_package(ECM 1.0.0 REQUIRED NO_MODULE)
|
||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
|
||||
include(KDEInstallDirs)
|
||||
include(ECMInstallIcons)
|
||||
include(FeatureSummary)
|
||||
|
||||
find_package(Qt5Core)
|
||||
set_package_properties(Qt5Core PROPERTIES TYPE REQUIRED)
|
||||
|
||||
find_package(Qt5DBus)
|
||||
set_package_properties(Qt5DBus PROPERTIES TYPE REQUIRED)
|
||||
|
||||
find_package(Qt5Qml)
|
||||
set_package_properties(Qt5Qml PROPERTIES TYPE REQUIRED)
|
||||
|
||||
find_package(Qt5Quick)
|
||||
set_package_properties(Qt5Quick PROPERTIES TYPE REQUIRED)
|
||||
|
||||
find_package(Qt5QuickControls2)
|
||||
set_package_properties(Qt5QuickControls2 PROPERTIES TYPE REQUIRED)
|
||||
|
||||
find_package(Qt5 COMPONENTS Core Quick DBus Widgets REQUIRED)
|
||||
find_package(Libmpv)
|
||||
set_package_properties(Libmpv PROPERTIES TYPE REQUIRED
|
||||
URL "https://mpv.io")
|
||||
|
||||
find_package(KF5Config)
|
||||
set_package_properties(KF5Config PROPERTIES TYPE REQUIRED
|
||||
URL "https://api.kde.org/frameworks/kconfig/html/index.html")
|
||||
|
||||
find_package(KF5CoreAddons)
|
||||
set_package_properties(KF5CoreAddons PROPERTIES TYPE REQUIRED
|
||||
URL "https://api.kde.org/frameworks/kcoreaddons/html/index.html")
|
||||
|
||||
find_package(KF5DocTools)
|
||||
set_package_properties(KF5DocTools PROPERTIES
|
||||
DESCRIPTION "https://api.kde.org/frameworks/kdoctools/html/index.html")
|
||||
|
||||
find_package(KF5FileMetaData)
|
||||
set_package_properties(KF5FileMetaData PROPERTIES TYPE REQUIRED
|
||||
URL "https://api.kde.org/frameworks/kfilemetadata/html/index.html")
|
||||
|
||||
find_package(KF5KIO)
|
||||
set_package_properties(KF5KIO PROPERTIES TYPE REQUIRED
|
||||
URL "https://api.kde.org/frameworks/kio/html/index.html")
|
||||
|
||||
#find_package(KF5Kirigami2)
|
||||
#set_package_properties(KF5Kirigami2 PROPERTIES TYPE REQUIRED
|
||||
# URL "https://api.kde.org/frameworks/kirigami/html/index.html")
|
||||
|
||||
find_package(KF5XmlGui)
|
||||
set_package_properties(KF5XmlGui PROPERTIES TYPE REQUIRED
|
||||
URL "https://api.kde.org/frameworks/kxmlgui/html/index.html")
|
||||
|
||||
#option(InstallColorSchemes "Installs breeze color schemes." OFF)
|
||||
|
||||
feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
|
||||
|
||||
add_subdirectory(src)
|
||||
qt5_add_dbus_interface(screensaver_inhibit_SRCS ./org.freedesktop.ScreenSaver.xml screensaverdbusinterface)
|
||||
|
||||
set(PROJECT_SOURCES
|
||||
src/main.cpp
|
||||
src/application.cpp
|
||||
src/playlistmodel.cpp
|
||||
src/playlistitem.cpp
|
||||
src/track.cpp
|
||||
src/tracksmodel.cpp
|
||||
src/mpvobject.cpp
|
||||
src/qthelper.h
|
||||
src/lockmanager.cpp
|
||||
src/mpris2/mediaplayer2.cpp
|
||||
src/mpris2/mediaplayer2player.cpp
|
||||
qml.qrc
|
||||
${screensaver_inhibit_SRCS}
|
||||
)
|
||||
|
||||
add_executable(cutefish-videoplayer
|
||||
${PROJECT_SOURCES}
|
||||
)
|
||||
|
||||
target_link_libraries(cutefish-videoplayer
|
||||
PRIVATE
|
||||
Qt5::Core
|
||||
Qt5::Quick
|
||||
Qt5::DBus
|
||||
Qt5::Widgets
|
||||
Libmpv::Libmpv
|
||||
)
|
||||
|
||||
install(TARGETS cutefish-videoplayer DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
install(FILES
|
||||
cutefish-videoplayer.desktop
|
||||
DESTINATION /usr/share/applications/
|
||||
COMPONENT Runtime
|
||||
)
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
[Desktop Entry]
|
||||
Name=Cutefish Video Player
|
||||
Exec=cutefish-videoplayer %u
|
||||
Icon=videoplayer
|
||||
Icon=cutefish-videoplayer
|
||||
Type=Application
|
||||
Categories=Qt;KDE;AudioVideo;Player;Video;TV;
|
||||
Categories=Qt;AudioVideo;Player;Video;TV;
|
||||
MimeType=application/ogg;application/x-ogg;application/mxf;application/sdp;application/smil;application/x-smil;application/streamingmedia;application/x-streamingmedia;application/vnd.rn-realmedia;application/vnd.rn-realmedia-vbr;audio/aac;audio/x-aac;audio/vnd.dolby.heaac.1;audio/vnd.dolby.heaac.2;audio/aiff;audio/x-aiff;audio/m4a;audio/x-m4a;application/x-extension-m4a;audio/mp1;audio/x-mp1;audio/mp2;audio/x-mp2;audio/mp3;audio/x-mp3;audio/mpeg;audio/mpeg2;audio/mpeg3;audio/mpegurl;audio/x-mpegurl;audio/mpg;audio/x-mpg;audio/rn-mpeg;audio/musepack;audio/x-musepack;audio/ogg;audio/scpls;audio/x-scpls;audio/vnd.rn-realaudio;audio/wav;audio/x-pn-wav;audio/x-pn-windows-pcm;audio/x-realaudio;audio/x-pn-realaudio;audio/x-ms-wma;audio/x-pls;audio/x-wav;video/mpeg;video/x-mpeg2;video/x-mpeg3;video/mp4v-es;video/x-m4v;video/mp4;application/x-extension-mp4;video/divx;video/vnd.divx;video/msvideo;video/x-msvideo;video/ogg;video/quicktime;video/vnd.rn-realvideo;video/x-ms-afs;video/x-ms-asf;audio/x-ms-asf;application/vnd.ms-asf;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvxvideo;video/x-avi;video/avi;video/x-flic;video/fli;video/x-flc;video/flv;video/x-flv;video/x-theora;video/x-theora+ogg;video/x-matroska;video/mkv;audio/x-matroska;application/x-matroska;video/webm;audio/webm;audio/vorbis;audio/x-vorbis;audio/x-vorbis+ogg;video/x-ogm;video/x-ogm+ogg;application/x-ogm;application/x-ogm-audio;application/x-ogm-video;application/x-shorten;audio/x-shorten;audio/x-ape;audio/x-wavpack;audio/x-tta;audio/AMR;audio/ac3;audio/eac3;audio/amr-wb;video/mp2t;audio/flac;audio/mp4;application/x-mpegurl;video/vnd.mpegurl;application/vnd.apple.mpegurl;audio/x-pn-au;video/3gp;video/3gpp;video/3gpp2;audio/3gpp;audio/3gpp2;video/dv;audio/dv;audio/opus;audio/vnd.dts;audio/vnd.dts.hd;audio/x-adpcm;application/x-cue;audio/m3u;
|
||||
X-KDE-Protocols=ftp,http,https,mms,rtmp,rtsp,sftp,smb,srt
|
||||
Terminal=false
|
||||
Terminal=false
|
||||
|
After Width: | Height: | Size: 7.4 KiB |
@ -0,0 +1,11 @@
|
||||
<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0 -.00047914)" fill="#ffffff">
|
||||
<rect y="6" width="5" height="4" ry="1" fill-rule="evenodd"/>
|
||||
<path d="m6 3-3 3v4l3 3z"/>
|
||||
<g fill-rule="evenodd">
|
||||
<path d="M 13.139,1.428 C 12.594,1 12,1.652 12.455,2.16 A 8,8 0 0 1 15,8 8,8 0 0 1 12.446,13.852 C 12,14.323 12.626,15 13.123,14.58 A 9,9 0 0 0 16,8 9,9 0 0 0 13.139,1.428 Z"/>
|
||||
<path d="m10.775 2.889c-0.587-0.535-1.199 0.225-0.684 0.732a6 6 0 0 1 1.909 4.379 6 6 0 0 1-1.916 4.389c-0.469 0.446 0.173 1.146 0.68 0.728a7 7 0 0 0 2.236-5.117 7 7 0 0 0-2.225-5.111z"/>
|
||||
<path d="M 8.41,4.35 C 7.89,3.856 7.255,4.57 7.727,5.08 A 4,4 0 0 1 9,8 4,4 0 0 1 7.723,10.926 c -0.473,0.43 0.14,1.152 0.68,0.73 A 5,5 0 0 0 10,8 5,5 0 0 0 8.41,4.35 Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 820 B |
@ -0,0 +1,11 @@
|
||||
<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0 -.00047914)" fill="#ffffff">
|
||||
<rect y="6" width="5" height="4" ry="1" fill-rule="evenodd"/>
|
||||
<path d="m6 3-3 3v4l3 3z"/>
|
||||
<g fill-rule="evenodd">
|
||||
<path d="M 13.139,1.428 C 12.594,1 12,1.652 12.455,2.16 A 8,8 0 0 1 15,8 8,8 0 0 1 12.446,13.852 C 12,14.323 12.626,15 13.123,14.58 A 9,9 0 0 0 16,8 9,9 0 0 0 13.139,1.428 Z" opacity=".35"/>
|
||||
<path d="m10.775 2.889c-0.587-0.535-1.199 0.225-0.684 0.732a6 6 0 0 1 1.909 4.379 6 6 0 0 1-1.916 4.389c-0.469 0.446 0.173 1.146 0.68 0.728a7 7 0 0 0 2.236-5.117 7 7 0 0 0-2.225-5.111z" opacity=".35"/>
|
||||
<path d="M 8.41,4.35 C 7.89,3.856 7.255,4.57 7.727,5.08 A 4,4 0 0 1 9,8 4,4 0 0 1 7.723,10.926 c -0.473,0.43 0.14,1.152 0.68,0.73 A 5,5 0 0 0 10,8 5,5 0 0 0 8.41,4.35 Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 848 B |
@ -0,0 +1,11 @@
|
||||
<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0 -.00047914)" fill="#ffffff">
|
||||
<rect y="6" width="5" height="4" ry="1" fill-rule="evenodd"/>
|
||||
<path d="m6 3-3 3v4l3 3z"/>
|
||||
<g fill-rule="evenodd">
|
||||
<path d="M 13.139,1.428 C 12.594,1 12,1.652 12.455,2.16 A 8,8 0 0 1 15,8 8,8 0 0 1 12.446,13.852 C 12,14.323 12.626,15 13.123,14.58 A 9,9 0 0 0 16,8 9,9 0 0 0 13.139,1.428 Z" opacity=".35"/>
|
||||
<path d="m10.775 2.889c-0.587-0.535-1.199 0.225-0.684 0.732a6 6 0 0 1 1.909 4.379 6 6 0 0 1-1.916 4.389c-0.469 0.446 0.173 1.146 0.68 0.728a7 7 0 0 0 2.236-5.117 7 7 0 0 0-2.225-5.111z"/>
|
||||
<path d="M 8.41,4.35 C 7.89,3.856 7.255,4.57 7.727,5.08 A 4,4 0 0 1 9,8 4,4 0 0 1 7.723,10.926 c -0.473,0.43 0.14,1.152 0.68,0.73 A 5,5 0 0 0 10,8 5,5 0 0 0 8.41,4.35 Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 834 B |
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m12.738 1.291c-0.37563 0.026826-0.62454 0.48828-0.2832 0.86914 1.6202 1.5104 2.5416 3.6249 2.5449 5.8398-0.0026 2.2205-0.92792 4.3401-2.5547 5.8516-0.44531 0.47165 0.18064 1.1484 0.67774 0.72852 1.8304-1.6992 2.8725-4.0825 2.877-6.5801-0.0026-2.4925-1.0386-4.8722-2.8613-6.5723-0.13636-0.10693-0.27518-0.14566-0.40039-0.13672zm-2.3906 1.416c-0.39562 0.011891-0.64227 0.53363-0.25586 0.91406 1.2147 1.1326 1.9056 2.7181 1.9082 4.3789-0.0019 1.6654-0.69596 3.2551-1.916 4.3887-0.46835 0.44623 0.17346 1.1467 0.67969 0.72852 1.423-1.3216 2.233-3.1751 2.2363-5.1172-0.0019-1.9383-0.8074-3.789-2.2246-5.1113-0.14685-0.13372-0.29586-0.1856-0.42774-0.18164zm-4.3477 0.29297-3 3h-2c-0.554 0-1 0.446-1 1v2c0 0.554 0.446 1 1 1h2l3 3v-10zm2.0176 1.1836c-0.37603 0.016385-0.64465 0.51365-0.29102 0.89648 0.81045 0.75501 1.2715 1.8123 1.2734 2.9199-0.00128 1.1103-0.464 2.1701-1.2773 2.9258-0.47259 0.42993 0.13957 1.1522 0.67969 0.73047 1.0168-0.94425 1.5955-2.2686 1.5977-3.6562-0.00172-1.3844-0.57742-2.7062-1.5898-3.6504-0.13024-0.12342-0.26724-0.17148-0.39258-0.16602z" fill="#ffffff" fill-rule="evenodd" opacity=".5" style="paint-order:normal"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
viewBox="0 0 22 22"
|
||||
id="svg17"
|
||||
sodipodi:docname="view-list-tree.svg"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||
<metadata
|
||||
id="metadata21">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="2160"
|
||||
inkscape:window-height="1312"
|
||||
id="namedview19"
|
||||
showgrid="false"
|
||||
inkscape:zoom="33.409091"
|
||||
inkscape:cx="11"
|
||||
inkscape:cy="11"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg17" />
|
||||
<defs
|
||||
id="defs3">
|
||||
<style
|
||||
id="current-color-scheme"
|
||||
type="text/css">.ColorScheme-Text {
|
||||
color:#FFFFFF;
|
||||
}</style>
|
||||
</defs>
|
||||
<rect
|
||||
class="ColorScheme-Text"
|
||||
x="7"
|
||||
y="5"
|
||||
width="12"
|
||||
height="1"
|
||||
ry="0"
|
||||
fill="currentColor"
|
||||
id="rect5" />
|
||||
<rect
|
||||
class="ColorScheme-Text"
|
||||
x="7"
|
||||
y="11"
|
||||
width="12"
|
||||
height="1"
|
||||
ry="0"
|
||||
fill="currentColor"
|
||||
id="rect9" />
|
||||
<rect
|
||||
class="ColorScheme-Text"
|
||||
x="7"
|
||||
y="17"
|
||||
width="12"
|
||||
height="1"
|
||||
ry="0"
|
||||
fill="currentColor"
|
||||
id="rect13" />
|
||||
<rect
|
||||
style="fill:#FFFFFF;fill-opacity:1;stroke-width:0.768904"
|
||||
id="rect855"
|
||||
width="3"
|
||||
height="3"
|
||||
x="3"
|
||||
y="4"
|
||||
ry="1.5" />
|
||||
<rect
|
||||
style="fill:#FFFFFF;fill-opacity:1;stroke-width:0.768904"
|
||||
id="rect855-3"
|
||||
width="3"
|
||||
height="3"
|
||||
x="3"
|
||||
y="10"
|
||||
ry="1.5" />
|
||||
<rect
|
||||
style="fill:#FFFFFF;fill-opacity:1;stroke-width:0.768904"
|
||||
id="rect855-3-6"
|
||||
width="3"
|
||||
height="3"
|
||||
x="3"
|
||||
y="16"
|
||||
ry="1.5" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@ -0,0 +1,6 @@
|
||||
<svg width="16" height="16" enable-background="new" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="matrix(1.25,0,0,1.25,-2,-2)" fill="#fff" stroke-width="1.8257">
|
||||
<rect x="4" y="3" width="2" height="10" rx="1" ry="1"/>
|
||||
<rect x="10" y="3" width="2" height="10" rx="1" ry="1"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 311 B |
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" enable-background="new" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m4.1288 1.6066c-0.3219 0.039894-0.58908 0.17974-0.80457 0.42182s-0.32418 0.52688-0.32418 0.85144v10.241c0 0.32456 0.10871 0.60936 0.32418 0.85144 0.21549 0.24208 0.48272 0.38191 0.80457 0.42182 0.3219 0.03991 0.61401-0.03125 0.8827-0.21481l7.4286-5.1202c0.23677-0.16228 0.40168-0.38357 0.4921-0.65225 0.09047-0.27134 0.09047-0.53977 0-0.80849-0.090471-0.26869-0.25408-0.48733-0.48821-0.65225l-7.4326-5.1243c-0.2678-0.18622-0.56169-0.25561-0.8827-0.21481z" fill="#fff" stroke-width="1.9996"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 611 B |
@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" enable-background="new" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m13.119 3.0087c0.2513 0.031145 0.45989 0.14032 0.62812 0.32931s0.25308 0.41133 0.25308 0.66471v7.9948c0 0.25338-0.08487 0.47572-0.25308 0.66471-0.16823 0.18899-0.37685 0.29815-0.62812 0.32931-0.2513 0.03116-0.47935-0.0244-0.68911-0.1677l-5.7994-3.9973c-0.18484-0.12669-0.31359-0.29945-0.38418-0.5092-0.07063-0.21183-0.07063-0.42139 0-0.63118 0.07063-0.20976 0.19836-0.38045 0.38114-0.5092l5.8025-4.0005c0.20907-0.14538 0.4385-0.19955 0.68911-0.1677z" fill="#FFFFFF" stroke-width="1.5611"/>
|
||||
<rect x="2" y="3" width="2" height="10" rx="1" ry="1" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4164"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 750 B |
@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" enable-background="new" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m2.8812 3.0087c-0.2513 0.031145-0.45989 0.14032-0.62812 0.32931s-0.25308 0.41133-0.25308 0.66471v7.9948c0 0.25338 0.08487 0.47572 0.25308 0.66471 0.16823 0.18899 0.37685 0.29815 0.62812 0.32931 0.2513 0.03116 0.47935-0.0244 0.68911-0.1677l5.7994-3.9973c0.18484-0.12669 0.31359-0.29945 0.38418-0.5092 0.07063-0.21183 0.07063-0.42139 0-0.63118-0.07063-0.20976-0.19836-0.38045-0.38114-0.5092l-5.8025-4.0005c-0.20907-0.14538-0.4385-0.19955-0.68911-0.1677z" fill="#FFFFFF" stroke-width="1.5611"/>
|
||||
<rect transform="scale(-1,1)" x="-14" y="3" width="2" height="10" rx="1" ry="1" fill="#FFFFFF" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4164"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 778 B |
@ -0,0 +1,11 @@
|
||||
<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0 -.00047914)" fill="#363636">
|
||||
<rect y="6" width="5" height="4" ry="1" fill-rule="evenodd"/>
|
||||
<path d="m6 3-3 3v4l3 3z"/>
|
||||
<g fill-rule="evenodd">
|
||||
<path d="M 13.139,1.428 C 12.594,1 12,1.652 12.455,2.16 A 8,8 0 0 1 15,8 8,8 0 0 1 12.446,13.852 C 12,14.323 12.626,15 13.123,14.58 A 9,9 0 0 0 16,8 9,9 0 0 0 13.139,1.428 Z"/>
|
||||
<path d="m10.775 2.889c-0.587-0.535-1.199 0.225-0.684 0.732a6 6 0 0 1 1.909 4.379 6 6 0 0 1-1.916 4.389c-0.469 0.446 0.173 1.146 0.68 0.728a7 7 0 0 0 2.236-5.117 7 7 0 0 0-2.225-5.111z"/>
|
||||
<path d="M 8.41,4.35 C 7.89,3.856 7.255,4.57 7.727,5.08 A 4,4 0 0 1 9,8 4,4 0 0 1 7.723,10.926 c -0.473,0.43 0.14,1.152 0.68,0.73 A 5,5 0 0 0 10,8 5,5 0 0 0 8.41,4.35 Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 820 B |
@ -0,0 +1,11 @@
|
||||
<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0 -.00047914)" fill="#363636">
|
||||
<rect y="6" width="5" height="4" ry="1" fill-rule="evenodd"/>
|
||||
<path d="m6 3-3 3v4l3 3z"/>
|
||||
<g fill-rule="evenodd">
|
||||
<path d="M 13.139,1.428 C 12.594,1 12,1.652 12.455,2.16 A 8,8 0 0 1 15,8 8,8 0 0 1 12.446,13.852 C 12,14.323 12.626,15 13.123,14.58 A 9,9 0 0 0 16,8 9,9 0 0 0 13.139,1.428 Z" opacity=".35"/>
|
||||
<path d="m10.775 2.889c-0.587-0.535-1.199 0.225-0.684 0.732a6 6 0 0 1 1.909 4.379 6 6 0 0 1-1.916 4.389c-0.469 0.446 0.173 1.146 0.68 0.728a7 7 0 0 0 2.236-5.117 7 7 0 0 0-2.225-5.111z" opacity=".35"/>
|
||||
<path d="M 8.41,4.35 C 7.89,3.856 7.255,4.57 7.727,5.08 A 4,4 0 0 1 9,8 4,4 0 0 1 7.723,10.926 c -0.473,0.43 0.14,1.152 0.68,0.73 A 5,5 0 0 0 10,8 5,5 0 0 0 8.41,4.35 Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 848 B |
@ -0,0 +1,11 @@
|
||||
<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(0 -.00047914)" fill="#363636">
|
||||
<rect y="6" width="5" height="4" ry="1" fill-rule="evenodd"/>
|
||||
<path d="m6 3-3 3v4l3 3z"/>
|
||||
<g fill-rule="evenodd">
|
||||
<path d="M 13.139,1.428 C 12.594,1 12,1.652 12.455,2.16 A 8,8 0 0 1 15,8 8,8 0 0 1 12.446,13.852 C 12,14.323 12.626,15 13.123,14.58 A 9,9 0 0 0 16,8 9,9 0 0 0 13.139,1.428 Z" opacity=".35"/>
|
||||
<path d="m10.775 2.889c-0.587-0.535-1.199 0.225-0.684 0.732a6 6 0 0 1 1.909 4.379 6 6 0 0 1-1.916 4.389c-0.469 0.446 0.173 1.146 0.68 0.728a7 7 0 0 0 2.236-5.117 7 7 0 0 0-2.225-5.111z"/>
|
||||
<path d="M 8.41,4.35 C 7.89,3.856 7.255,4.57 7.727,5.08 A 4,4 0 0 1 9,8 4,4 0 0 1 7.723,10.926 c -0.473,0.43 0.14,1.152 0.68,0.73 A 5,5 0 0 0 10,8 5,5 0 0 0 8.41,4.35 Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 834 B |
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m12.738 1.291c-0.37563 0.026826-0.62454 0.48828-0.2832 0.86914 1.6202 1.5104 2.5416 3.6249 2.5449 5.8398-0.0026 2.2205-0.92792 4.3401-2.5547 5.8516-0.44531 0.47165 0.18064 1.1484 0.67774 0.72852 1.8304-1.6992 2.8725-4.0825 2.877-6.5801-0.0026-2.4925-1.0386-4.8722-2.8613-6.5723-0.13636-0.10693-0.27518-0.14566-0.40039-0.13672zm-2.3906 1.416c-0.39562 0.011891-0.64227 0.53363-0.25586 0.91406 1.2147 1.1326 1.9056 2.7181 1.9082 4.3789-0.0019 1.6654-0.69596 3.2551-1.916 4.3887-0.46835 0.44623 0.17346 1.1467 0.67969 0.72852 1.423-1.3216 2.233-3.1751 2.2363-5.1172-0.0019-1.9383-0.8074-3.789-2.2246-5.1113-0.14685-0.13372-0.29586-0.1856-0.42774-0.18164zm-4.3477 0.29297-3 3h-2c-0.554 0-1 0.446-1 1v2c0 0.554 0.446 1 1 1h2l3 3v-10zm2.0176 1.1836c-0.37603 0.016385-0.64465 0.51365-0.29102 0.89648 0.81045 0.75501 1.2715 1.8123 1.2734 2.9199-0.00128 1.1103-0.464 2.1701-1.2773 2.9258-0.47259 0.42993 0.13957 1.1522 0.67969 0.73047 1.0168-0.94425 1.5955-2.2686 1.5977-3.6562-0.00172-1.3844-0.57742-2.7062-1.5898-3.6504-0.13024-0.12342-0.26724-0.17148-0.39258-0.16602z" fill="#363636" fill-rule="evenodd" opacity=".5" style="paint-order:normal"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
viewBox="0 0 22 22"
|
||||
id="svg17"
|
||||
sodipodi:docname="view-list-tree.svg"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||
<metadata
|
||||
id="metadata21">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="2160"
|
||||
inkscape:window-height="1312"
|
||||
id="namedview19"
|
||||
showgrid="false"
|
||||
inkscape:zoom="33.409091"
|
||||
inkscape:cx="11"
|
||||
inkscape:cy="11"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="30"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg17" />
|
||||
<defs
|
||||
id="defs3">
|
||||
<style
|
||||
id="current-color-scheme"
|
||||
type="text/css">.ColorScheme-Text {
|
||||
color:#363636;
|
||||
}</style>
|
||||
</defs>
|
||||
<rect
|
||||
class="ColorScheme-Text"
|
||||
x="7"
|
||||
y="5"
|
||||
width="12"
|
||||
height="1"
|
||||
ry="0"
|
||||
fill="currentColor"
|
||||
id="rect5" />
|
||||
<rect
|
||||
class="ColorScheme-Text"
|
||||
x="7"
|
||||
y="11"
|
||||
width="12"
|
||||
height="1"
|
||||
ry="0"
|
||||
fill="currentColor"
|
||||
id="rect9" />
|
||||
<rect
|
||||
class="ColorScheme-Text"
|
||||
x="7"
|
||||
y="17"
|
||||
width="12"
|
||||
height="1"
|
||||
ry="0"
|
||||
fill="currentColor"
|
||||
id="rect13" />
|
||||
<rect
|
||||
style="fill:#363636;fill-opacity:1;stroke-width:0.768904"
|
||||
id="rect855"
|
||||
width="3"
|
||||
height="3"
|
||||
x="3"
|
||||
y="4"
|
||||
ry="1.5" />
|
||||
<rect
|
||||
style="fill:#363636;fill-opacity:1;stroke-width:0.768904"
|
||||
id="rect855-3"
|
||||
width="3"
|
||||
height="3"
|
||||
x="3"
|
||||
y="10"
|
||||
ry="1.5" />
|
||||
<rect
|
||||
style="fill:#363636;fill-opacity:1;stroke-width:0.768904"
|
||||
id="rect855-3-6"
|
||||
width="3"
|
||||
height="3"
|
||||
x="3"
|
||||
y="16"
|
||||
ry="1.5" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@ -0,0 +1,6 @@
|
||||
<svg width="16" height="16" enable-background="new" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="matrix(1.25,0,0,1.25,-2,-2)" fill="#363636" stroke-width="1.8257">
|
||||
<rect x="4" y="3" width="2" height="10" rx="1" ry="1"/>
|
||||
<rect x="10" y="3" width="2" height="10" rx="1" ry="1"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 314 B |
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" enable-background="new" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m4.1288 1.6066c-0.3219 0.039894-0.58908 0.17974-0.80457 0.42182s-0.32418 0.52688-0.32418 0.85144v10.241c0 0.32456 0.10871 0.60936 0.32418 0.85144 0.21549 0.24208 0.48272 0.38191 0.80457 0.42182 0.3219 0.03991 0.61401-0.03125 0.8827-0.21481l7.4286-5.1202c0.23677-0.16228 0.40168-0.38357 0.4921-0.65225 0.09047-0.27134 0.09047-0.53977 0-0.80849-0.090471-0.26869-0.25408-0.48733-0.48821-0.65225l-7.4326-5.1243c-0.2678-0.18622-0.56169-0.25561-0.8827-0.21481z" fill="#363636" stroke-width="1.9996"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 614 B |
@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" enable-background="new" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m13.119 3.0087c0.2513 0.031145 0.45989 0.14032 0.62812 0.32931s0.25308 0.41133 0.25308 0.66471v7.9948c0 0.25338-0.08487 0.47572-0.25308 0.66471-0.16823 0.18899-0.37685 0.29815-0.62812 0.32931-0.2513 0.03116-0.47935-0.0244-0.68911-0.1677l-5.7994-3.9973c-0.18484-0.12669-0.31359-0.29945-0.38418-0.5092-0.07063-0.21183-0.07063-0.42139 0-0.63118 0.07063-0.20976 0.19836-0.38045 0.38114-0.5092l5.8025-4.0005c0.20907-0.14538 0.4385-0.19955 0.68911-0.1677z" fill="#363636" stroke-width="1.5611"/>
|
||||
<rect x="2" y="3" width="2" height="10" rx="1" ry="1" fill="#363636" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4164"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 750 B |
@ -0,0 +1,4 @@
|
||||
<svg width="16" height="16" enable-background="new" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m2.8812 3.0087c-0.2513 0.031145-0.45989 0.14032-0.62812 0.32931s-0.25308 0.41133-0.25308 0.66471v7.9948c0 0.25338 0.08487 0.47572 0.25308 0.66471 0.16823 0.18899 0.37685 0.29815 0.62812 0.32931 0.2513 0.03116 0.47935-0.0244 0.68911-0.1677l5.7994-3.9973c0.18484-0.12669 0.31359-0.29945 0.38418-0.5092 0.07063-0.21183 0.07063-0.42139 0-0.63118-0.07063-0.20976-0.19836-0.38045-0.38114-0.5092l-5.8025-4.0005c-0.20907-0.14538-0.4385-0.19955-0.68911-0.1677z" fill="#363636" stroke-width="1.5611"/>
|
||||
<rect transform="scale(-1,1)" x="-14" y="3" width="2" height="10" rx="1" ry="1" fill="#363636" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.4164"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 778 B |
@ -1,3 +0,0 @@
|
||||
SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
@ -0,0 +1,30 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>qml/main.qml</file>
|
||||
<file>qml/MpvVideo.qml</file>
|
||||
<file>qml/Footer.qml</file>
|
||||
<file>qml/HProgressBar.qml</file>
|
||||
<file>qml/PlayList.qml</file>
|
||||
<file>qml/PlayListItem.qml</file>
|
||||
<file>qml/Actions.qml</file>
|
||||
<file>images/cutefish-videoplayer.svg</file>
|
||||
<file>images/light/media-playback-pause-symbolic.svg</file>
|
||||
<file>images/light/media-playback-start-symbolic.svg</file>
|
||||
<file>images/light/media-skip-backward-symbolic.svg</file>
|
||||
<file>images/light/media-skip-forward-symbolic.svg</file>
|
||||
<file>images/dark/media-playback-pause-symbolic.svg</file>
|
||||
<file>images/dark/media-playback-start-symbolic.svg</file>
|
||||
<file>images/dark/media-skip-backward-symbolic.svg</file>
|
||||
<file>images/dark/media-skip-forward-symbolic.svg</file>
|
||||
<file>images/dark/audio-volume-high-symbolic.svg</file>
|
||||
<file>images/dark/audio-volume-low-symbolic.svg</file>
|
||||
<file>images/dark/audio-volume-medium-symbolic.svg</file>
|
||||
<file>images/dark/audio-volume-muted-symbolic.svg</file>
|
||||
<file>images/light/audio-volume-high-symbolic.svg</file>
|
||||
<file>images/light/audio-volume-low-symbolic.svg</file>
|
||||
<file>images/light/audio-volume-medium-symbolic.svg</file>
|
||||
<file>images/light/audio-volume-muted-symbolic.svg</file>
|
||||
<file>images/dark/list.svg</file>
|
||||
<file>images/light/list.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
QtObject {
|
||||
id: root
|
||||
|
||||
property var list: ({})
|
||||
|
||||
property Action togglePlaylistAction: Action {
|
||||
id: togglePlaylistAction
|
||||
|
||||
Component.onCompleted: list["togglePlaylistAction"] = togglePlaylistAction
|
||||
|
||||
onTriggered: {
|
||||
if (playList.state === "visible") {
|
||||
playList.state = "hidden"
|
||||
} else {
|
||||
playList.state = "visible"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property Action playPreviousAction: Action {
|
||||
id: playPreviousAction
|
||||
// property var qaction: app.action("playPrevious")
|
||||
// text: qaction.text
|
||||
// shortcut: qaction.shortcutName
|
||||
// icon.name: qaction.iconName()
|
||||
|
||||
Component.onCompleted: list["playPreviousAction"] = playPreviousAction
|
||||
|
||||
onTriggered: {
|
||||
if (mpv.playlistModel.getPlayingVideo() !== 0) {
|
||||
const previousFileRow = mpv.playlistModel.getPlayingVideo() - 1
|
||||
const previousFile = mpv.playlistModel.getPath(previousFileRow)
|
||||
const updateLastPlayedFile = !playList.isYouTubePlaylist
|
||||
mpv.playlistModel.setPlayingVideo(previousFileRow)
|
||||
mpv.loadFile(previousFile, updateLastPlayedFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
property Action muteAction: Action {
|
||||
id: muteAction
|
||||
// property var qaction: app.action("mute")
|
||||
// text: qaction.text
|
||||
// shortcut: qaction.shortcutName
|
||||
// icon.name: qaction.iconName()
|
||||
|
||||
Component.onCompleted: list["muteAction"] = muteAction
|
||||
|
||||
onTriggered: {
|
||||
mpv.setProperty("mute", !mpv.getProperty("mute"))
|
||||
if (mpv.getProperty("mute")) {
|
||||
text = qsTr("Unmute")
|
||||
icon.name = "player-volume-muted"
|
||||
} /*else {
|
||||
text = qaction.text
|
||||
icon.name = qaction.iconName()
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
property Action playNextAction: Action {
|
||||
id: playNextAction
|
||||
// property var qaction: app.action("playNext")
|
||||
// text: qaction.text
|
||||
// shortcut: qaction.shortcutName
|
||||
// icon.name: qaction.iconName()
|
||||
|
||||
Component.onCompleted: list["playNextAction"] = playNextAction
|
||||
|
||||
onTriggered: {
|
||||
const nextFileRow = mpv.playlistModel.getPlayingVideo() + 1
|
||||
const updateLastPlayedFile = !playList.isYouTubePlaylist
|
||||
if (nextFileRow < playList.playlistView.count) {
|
||||
const nextFile = mpv.playlistModel.getPath(nextFileRow)
|
||||
mpv.playlistModel.setPlayingVideo(nextFileRow)
|
||||
mpv.loadFile(nextFile, updateLastPlayedFile)
|
||||
} else {
|
||||
// Last file in playlist
|
||||
// if (PlaylistSettings.repeat) {
|
||||
mpv.playlistModel.setPlayingVideo(0)
|
||||
mpv.loadFile(mpv.playlistModel.getPath(0), updateLastPlayedFile)
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property Action playPauseAction: Action {
|
||||
id: playPauseAction
|
||||
text: qsTr("Play/Pause")
|
||||
icon.name: "media-playback-pause"
|
||||
shortcut: "Space"
|
||||
|
||||
Component.onCompleted: list["playPauseAction"] = playPauseAction
|
||||
|
||||
onTriggered: {
|
||||
mpv.setProperty("pause", !mpv.getProperty("pause"))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtGraphicalEffects 1.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
|
||||
Item {
|
||||
id: control
|
||||
|
||||
property alias progressBar: progressBar
|
||||
property alias footerRow: footerRow
|
||||
property alias timeInfo: timeInfo
|
||||
property alias volume: volume
|
||||
|
||||
height: mainLayout.childrenRect.height + FishUI.Units.smallSpacing
|
||||
enabled: opacity !== 0
|
||||
visible: mpv.mouseY > rootWindow.height - footer.height && playList.state === "hidden"
|
||||
|
||||
ShaderEffectSource {
|
||||
id: shaderEffect
|
||||
visible: true
|
||||
anchors.fill: parent
|
||||
sourceItem: mpv
|
||||
sourceRect: Qt.rect(0, 0, control.width, control.height)
|
||||
}
|
||||
|
||||
FastBlur {
|
||||
visible: true
|
||||
anchors.fill: shaderEffect
|
||||
source: shaderEffect
|
||||
radius: 100
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: _background
|
||||
anchors.fill: parent
|
||||
color: FishUI.Theme.backgroundColor
|
||||
opacity: 0.7
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 0
|
||||
anchors.bottomMargin: FishUI.Units.smallSpacing
|
||||
spacing: FishUI.Units.smallSpacing
|
||||
|
||||
HProgressBar {
|
||||
id: progressBar
|
||||
Layout.fillWidth: true
|
||||
enabled: playList.playlistView.count >= 1
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: footerRow
|
||||
|
||||
Item {
|
||||
width: FishUI.Units.smallSpacing
|
||||
height: 30
|
||||
}
|
||||
|
||||
Item {
|
||||
id: leftItem
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Label {
|
||||
id: timeInfo
|
||||
text: app.formatTime(mpv.position) + " / " + app.formatTime(mpv.duration)
|
||||
font.pointSize: 10
|
||||
visible: playList.playlistView.count >= 1
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: middleItem
|
||||
Layout.preferredWidth: middleLayout.childrenRect.width
|
||||
Layout.fillHeight: true
|
||||
|
||||
RowLayout {
|
||||
id: middleLayout
|
||||
anchors.fill: parent
|
||||
|
||||
FishUI.RoundImageButton {
|
||||
width: 32
|
||||
height: 32
|
||||
iconMargins: FishUI.Units.smallSpacing
|
||||
source: "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/media-skip-backward-symbolic.svg"
|
||||
onClicked: actions.playPauseAction.triggered()
|
||||
visible: playList.playlistView.count > 1
|
||||
}
|
||||
|
||||
FishUI.RoundImageButton {
|
||||
width: 32
|
||||
height: 32
|
||||
iconMargins: FishUI.Units.smallSpacing
|
||||
source: mpv.pause ? "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/media-playback-start-symbolic.svg"
|
||||
: "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/media-playback-pause-symbolic.svg"
|
||||
onClicked: actions.playPauseAction.triggered()
|
||||
}
|
||||
|
||||
FishUI.RoundImageButton {
|
||||
width: 32
|
||||
height: 32
|
||||
iconMargins: FishUI.Units.smallSpacing
|
||||
source: "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/media-skip-forward-symbolic.svg"
|
||||
onClicked: actions.playPauseAction.triggered()
|
||||
visible: playList.playlistView.count > 1
|
||||
}
|
||||
|
||||
// ToolButton {
|
||||
// id: playPreviousFile
|
||||
// action: actions.playPreviousAction
|
||||
// text: ""
|
||||
// focusPolicy: Qt.NoFocus
|
||||
// enabled: playList.playlistView.count > 1
|
||||
// }
|
||||
|
||||
// ToolButton {
|
||||
// id: playPauseButton
|
||||
// action: actions.playPauseAction
|
||||
// text: ""
|
||||
// icon.name: "media-playback-pause"
|
||||
// focusPolicy: Qt.NoFocus
|
||||
// }
|
||||
|
||||
// ToolButton {
|
||||
// id: playNextFile
|
||||
// action: actions.playNextAction
|
||||
// text: ""
|
||||
// focusPolicy: Qt.NoFocus
|
||||
// enabled: playList.playlistView.count > 1
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: rightItem
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
spacing: FishUI.Units.smallSpacing
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
FishUI.RoundImageButton {
|
||||
id: mute
|
||||
width: 32
|
||||
height: 32
|
||||
iconMargins: FishUI.Units.smallSpacing + 3
|
||||
source: mpv.getProperty("mute") ? "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/audio-volume-muted-symbolic.svg"
|
||||
: "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/audio-volume-high-symbolic.svg"
|
||||
onClicked: {
|
||||
mpv.setProperty("mute", !mpv.getProperty("mute"))
|
||||
if (mpv.getProperty("mute")) {
|
||||
mute.source = "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/audio-volume-muted-symbolic.svg"
|
||||
} else {
|
||||
mute.source = "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/audio-volume-high-symbolic.svg"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: volume
|
||||
from: 0
|
||||
to: 100
|
||||
value: mpv.volume
|
||||
implicitWidth: 100
|
||||
implicitHeight: 25
|
||||
wheelEnabled: true
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
|
||||
onValueChanged: {
|
||||
mpv.volume = value.toFixed(0)
|
||||
// Settings.volume = value.toFixed(0)
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 1
|
||||
}
|
||||
|
||||
FishUI.RoundImageButton {
|
||||
width: 32
|
||||
height: 32
|
||||
iconMargins: FishUI.Units.smallSpacing + 2
|
||||
source: "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/list.svg"
|
||||
onClicked: actions.togglePlaylistAction.triggered()
|
||||
}
|
||||
|
||||
Item {
|
||||
width: FishUI.Units.smallSpacing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Window 2.12
|
||||
import FishUI 1.0 as FishUI
|
||||
import mpv 1.0
|
||||
|
||||
MpvObject {
|
||||
id: control
|
||||
|
||||
property int mouseX: mouseArea.mouseX
|
||||
property int mouseY: mouseArea.mouseY
|
||||
|
||||
onReady: {
|
||||
if (app.argument(0) !== "") {
|
||||
rootWindow.openFile(app.argument(0), true)
|
||||
}
|
||||
}
|
||||
|
||||
onFileLoaded: {
|
||||
// loadingIndicatorParent.visible = false
|
||||
// header.audioTracks = getProperty("track-list").filter(track => track["type"] === "audio")
|
||||
// header.subtitleTracks = getProperty("track-list").filter(track => track["type"] === "sub")
|
||||
|
||||
if (playList.playlistView.count <= 1) {
|
||||
setProperty("loop-file", "inf")
|
||||
}
|
||||
|
||||
setProperty("ab-loop-a", "no")
|
||||
setProperty("ab-loop-b", "no")
|
||||
|
||||
mpv.pause = loadTimePosition() !== 0
|
||||
position = loadTimePosition()
|
||||
}
|
||||
|
||||
onEndFile: {
|
||||
if (reason === "error") {
|
||||
if (playlistModel.rowCount() === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// osd.message(i18n("Could not play: %1").arg(title))
|
||||
}
|
||||
const nextFileRow = playlistModel.getPlayingVideo() + 1
|
||||
if (nextFileRow < playList.playlistView.count) {
|
||||
const nextFile = playlistModel.getPath(nextFileRow)
|
||||
playlistModel.setPlayingVideo(nextFileRow)
|
||||
loadFile(nextFile)
|
||||
} else {
|
||||
// Last file in playlist
|
||||
if (PlaylistSettings.repeat) {
|
||||
playlistModel.setPlayingVideo(0)
|
||||
loadFile(playlistModel.getPath(0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onPauseChanged: {
|
||||
if (pause) {
|
||||
lockManager.setInhibitionOff()
|
||||
} else {
|
||||
lockManager.setInhibitionOn()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: hideCursorTimer
|
||||
|
||||
property double tx: mouseArea.mouseX
|
||||
property double ty: mouseArea.mouseY
|
||||
property int timeNotMoved: 0
|
||||
|
||||
running: rootWindow.isFullScreen() && mouseArea.containsMouse
|
||||
repeat: true
|
||||
interval: 50
|
||||
|
||||
onTriggered: {
|
||||
if (mouseArea.mouseX === tx && mouseArea.mouseY === ty) {
|
||||
if (timeNotMoved > 2000) {
|
||||
app.hideCursor()
|
||||
}
|
||||
} else {
|
||||
app.showCursor()
|
||||
timeNotMoved = 0
|
||||
}
|
||||
tx = mouseArea.mouseX
|
||||
ty = mouseArea.mouseY
|
||||
timeNotMoved += interval
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: mediaPlayer2Player
|
||||
|
||||
function onPlaypause() {
|
||||
actions.playPauseAction.trigger()
|
||||
}
|
||||
|
||||
function onPlay() {
|
||||
control.pause = false
|
||||
}
|
||||
|
||||
function onPause() {
|
||||
control.pause = true
|
||||
}
|
||||
|
||||
function onStop() {
|
||||
control.position = 0
|
||||
control.pause = true
|
||||
}
|
||||
|
||||
function onNext() {
|
||||
actions.playNextAction.trigger()
|
||||
}
|
||||
|
||||
function onPrevious() {
|
||||
actions.playPreviousAction.trigger()
|
||||
}
|
||||
|
||||
function onSeek() {
|
||||
control.command(["add", "time-pos", offset])
|
||||
}
|
||||
|
||||
function onOpenUri() {
|
||||
control.command(["add", "time-pos", offset])
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
mediaPlayer2Player.mpv = control
|
||||
}
|
||||
|
||||
// Window move
|
||||
DragHandler {
|
||||
acceptedDevices: PointerDevice.GenericPointer
|
||||
grabPermissions: PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType | PointerHandler.ApprovesTakeOverByAnything
|
||||
onActiveChanged: if (active) rootWindow.helper.startSystemMove(rootWindow)
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
|
||||
onDoubleClicked: {
|
||||
if (mouse.button == Qt.LeftButton)
|
||||
rootWindow.toggleFullScreen()
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (mouse.button == Qt.RightButton)
|
||||
actions.playPauseAction.triggered()
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
playList.state = "hidden"
|
||||
}
|
||||
}
|
||||
|
||||
DropArea {
|
||||
id: dropArea
|
||||
anchors.fill: parent
|
||||
keys: ["text/uri-list"]
|
||||
|
||||
property var acceptedSubtitleTypes: ["application/x-subrip", "text/x-ssa"]
|
||||
|
||||
onDropped: {
|
||||
if (acceptedSubtitleTypes.includes(app.mimeType(drop.urls[0]))) {
|
||||
const subFile = drop.urls[0].replace("file://", "")
|
||||
command(["sub-add", drop.urls[0], "select"])
|
||||
}
|
||||
|
||||
if (app.mimeType(drop.urls[0]).startsWith("video/") || app.mimeType(drop.urls[0]).startsWith("audio/")) {
|
||||
rootWindow.openFile(drop.urls[0], true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2021 Reion Wong <aj@cutefishos.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtGraphicalEffects 1.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
import mpv 1.0
|
||||
|
||||
Item {
|
||||
id: control
|
||||
height: mpv.height - FishUI.Units.largeSpacing * 6
|
||||
width: FishUI.Units.gridUnit * 16
|
||||
z: 9999
|
||||
x: parent.width
|
||||
y: rootWindow.header.height + FishUI.Units.largeSpacing
|
||||
state: "hidden"
|
||||
|
||||
property string position: "right"
|
||||
property alias scrollPositionTimer: scrollPositionTimer
|
||||
property alias playlistView: playlistView
|
||||
|
||||
Label {
|
||||
anchors.centerIn: parent
|
||||
z: 999
|
||||
text: qsTr("Playlist is empty")
|
||||
visible: playlistView.count == 0
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
id: playlistScrollView
|
||||
|
||||
z: 20
|
||||
anchors.fill: parent
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||
|
||||
ListView {
|
||||
id: playlistView
|
||||
model: mpv.playlistModel
|
||||
spacing: 1
|
||||
delegate: PlayListItem {
|
||||
onDoubleClicked: control.state = "hidden"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: scrollPositionTimer
|
||||
interval: 50
|
||||
running: true
|
||||
repeat: true
|
||||
|
||||
onTriggered: {
|
||||
setPlayListScrollPosition()
|
||||
scrollPositionTimer.stop()
|
||||
}
|
||||
}
|
||||
|
||||
ShaderEffectSource {
|
||||
id: shaderEffect
|
||||
|
||||
anchors.fill: playlistScrollView
|
||||
sourceItem: mpv
|
||||
sourceRect: position === "right"
|
||||
? Qt.rect(mpv.width - control.width, mpv.y, control.width, control.height)
|
||||
: Qt.rect(0, 0, control.width, control.height)
|
||||
}
|
||||
|
||||
FastBlur {
|
||||
anchors.fill: shaderEffect
|
||||
radius: 100
|
||||
source: shaderEffect
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: FishUI.Theme.backgroundColor
|
||||
opacity: 0.7
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "hidden"
|
||||
PropertyChanges { target: control; x: position === "right" ? parent.width : -width }
|
||||
PropertyChanges { target: control; visible: false }
|
||||
},
|
||||
State {
|
||||
name : "visible"
|
||||
PropertyChanges { target: control; x: position === "right" ? parent.width - control.width - FishUI.Units.largeSpacing : 0 }
|
||||
PropertyChanges { target: control; visible: true }
|
||||
}
|
||||
]
|
||||
|
||||
transitions: [
|
||||
Transition {
|
||||
from: "visible"
|
||||
to: "hidden"
|
||||
|
||||
SequentialAnimation {
|
||||
NumberAnimation {
|
||||
target: control
|
||||
property: "x"
|
||||
duration: 150
|
||||
easing.type: Easing.InQuad
|
||||
}
|
||||
PropertyAction {
|
||||
target: control
|
||||
property: "visible"
|
||||
value: false
|
||||
}
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
from: "hidden"
|
||||
to: "visible"
|
||||
|
||||
SequentialAnimation {
|
||||
PropertyAction {
|
||||
target: control
|
||||
property: "visible"
|
||||
value: true
|
||||
}
|
||||
NumberAnimation {
|
||||
target: control
|
||||
property: "x"
|
||||
duration: 150
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: Item {
|
||||
width: control.width
|
||||
height: control.height
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: FishUI.Theme.bigRadius
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setPlayListScrollPosition() {
|
||||
playlistView.positionViewAtIndex(playlistView.model.playingVideo, ListView.Beginning)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,152 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Reion Wong <reion@cutefishos.com>
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Window 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtGraphicalEffects 1.12
|
||||
import Qt.labs.platform 1.0 as Platform
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
import mpv 1.0
|
||||
|
||||
FishUI.Window {
|
||||
id: rootWindow
|
||||
width: 720
|
||||
height: 480
|
||||
minimumWidth: 700
|
||||
minimumHeight: 450
|
||||
color: FishUI.Theme.backgroundColor
|
||||
|
||||
header.visible: mpv.mouseY >= 0 && mpv.mouseY <= header.height
|
||||
headerBackground.color: FishUI.Theme.secondBackgroundColor
|
||||
headerBackground.opacity: 0.95
|
||||
|
||||
contentTopMargin: 0
|
||||
|
||||
property int preFullScreenVisibility
|
||||
|
||||
onVisibilityChanged: {
|
||||
if (!rootWindow.isFullScreen()) {
|
||||
preFullScreenVisibility = visibility
|
||||
}
|
||||
}
|
||||
|
||||
headerItem: Item {
|
||||
Label {
|
||||
id: headerLabel
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: FishUI.Units.smallSpacing * 1.5
|
||||
anchors.leftMargin: FishUI.Units.largeSpacing
|
||||
text: mpv.mediaTitle
|
||||
color: "white"
|
||||
z: 100
|
||||
}
|
||||
|
||||
DropShadow {
|
||||
anchors.fill: headerLabel
|
||||
source: headerLabel
|
||||
z: -1
|
||||
horizontalOffset: 1
|
||||
verticalOffset: 1
|
||||
radius: Math.round(6 * FishUI.Units.devicePixelRatio)
|
||||
samples: radius * 2 + 1
|
||||
spread: 0.35
|
||||
color: Qt.rgba(0, 0, 0, 0.5)
|
||||
opacity: 0.4
|
||||
visible: true
|
||||
}
|
||||
}
|
||||
|
||||
Actions {
|
||||
id: actions
|
||||
}
|
||||
|
||||
MpvVideo {
|
||||
id: mpv
|
||||
anchors.fill: parent
|
||||
|
||||
Image {
|
||||
id: _logo
|
||||
anchors.centerIn: parent
|
||||
width: 128
|
||||
height: 128
|
||||
source: "qrc:/images/cutefish-videoplayer.svg"
|
||||
sourceSize: Qt.size(width, height)
|
||||
visible: playList.playlistView.count === 0
|
||||
}
|
||||
|
||||
Button {
|
||||
visible: _logo.visible
|
||||
anchors.top: _logo.bottom
|
||||
anchors.topMargin: FishUI.Units.largeSpacing
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("Open")
|
||||
onClicked: fileDialog.open()
|
||||
}
|
||||
}
|
||||
|
||||
Platform.FileDialog {
|
||||
id: fileDialog
|
||||
|
||||
property url location: ""
|
||||
|
||||
folder: location
|
||||
title: "Select file"
|
||||
fileMode: Platform.FileDialog.OpenFile
|
||||
|
||||
onAccepted: {
|
||||
openFile(fileDialog.file.toString(), true)
|
||||
// the timer scrolls the playlist to the playing file
|
||||
// once the table view rows are loaded
|
||||
playList.scrollPositionTimer.start()
|
||||
mpv.focus = true
|
||||
}
|
||||
onRejected: mpv.focus = true
|
||||
}
|
||||
|
||||
PlayList {
|
||||
id: playList
|
||||
}
|
||||
|
||||
Footer {
|
||||
id: footer
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: mpv.bottom
|
||||
}
|
||||
|
||||
function openFile(path, startPlayback) {
|
||||
mpv.playlistModel.addVideo(path)
|
||||
// mpv.playlistModel.clear()
|
||||
mpv.pause = !startPlayback
|
||||
// mpv.playlistModel.getVideos(path)
|
||||
mpv.loadFile(path)
|
||||
}
|
||||
|
||||
function isFullScreen() {
|
||||
return rootWindow.visibility === Window.FullScreen
|
||||
}
|
||||
|
||||
function toggleFullScreen() {
|
||||
if (!isFullScreen()) {
|
||||
rootWindow.showFullScreen()
|
||||
} else {
|
||||
if (rootWindow.preFullScreenVisibility === Window.Windowed) {
|
||||
rootWindow.showNormal()
|
||||
}
|
||||
if (rootWindow.preFullScreenVisibility === Window.Maximized) {
|
||||
rootWindow.show()
|
||||
rootWindow.showMaximized()
|
||||
}
|
||||
}
|
||||
app.showCursor()
|
||||
playList.scrollPositionTimer.start()
|
||||
}
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
#
|
||||
|
||||
qt5_add_dbus_interface(screensaver_inhibit_SRCS ../org.freedesktop.ScreenSaver.xml screensaverdbusinterface)
|
||||
|
||||
add_executable(cutefish-videoplayer)
|
||||
|
||||
target_sources(cutefish-videoplayer
|
||||
PRIVATE
|
||||
application.cpp
|
||||
global.cpp
|
||||
haction.cpp
|
||||
lockmanager.cpp
|
||||
main.cpp
|
||||
models/customcommandsmodel.cpp
|
||||
models/subtitlesfoldersmodel.cpp
|
||||
models/tracksmodel.cpp
|
||||
models/playlistmodel.cpp
|
||||
mpris2/mediaplayer2.cpp
|
||||
mpris2/mediaplayer2player.cpp
|
||||
mpvobject.cpp
|
||||
qthelper.h
|
||||
playlistitem.cpp
|
||||
thumbnailimageprovider.cpp
|
||||
track.cpp
|
||||
worker.cpp
|
||||
qml.qrc
|
||||
${screensaver_inhibit_SRCS}
|
||||
)
|
||||
|
||||
kconfig_add_kcfg_files(cutefish-videoplayer GENERATE_MOC settings/audiosettings.kcfgc)
|
||||
kconfig_add_kcfg_files(cutefish-videoplayer GENERATE_MOC settings/generalsettings.kcfgc)
|
||||
kconfig_add_kcfg_files(cutefish-videoplayer GENERATE_MOC settings/mousesettings.kcfgc)
|
||||
kconfig_add_kcfg_files(cutefish-videoplayer GENERATE_MOC settings/playbacksettings.kcfgc)
|
||||
kconfig_add_kcfg_files(cutefish-videoplayer GENERATE_MOC settings/playlistsettings.kcfgc)
|
||||
kconfig_add_kcfg_files(cutefish-videoplayer GENERATE_MOC settings/subtitlessettings.kcfgc)
|
||||
kconfig_add_kcfg_files(cutefish-videoplayer GENERATE_MOC settings/videosettings.kcfgc)
|
||||
|
||||
target_include_directories(cutefish-videoplayer PRIVATE models mpris2)
|
||||
|
||||
target_compile_definitions(cutefish-videoplayer PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
|
||||
|
||||
target_link_libraries(cutefish-videoplayer PRIVATE
|
||||
Qt5::Core
|
||||
Qt5::DBus
|
||||
Qt5::Qml
|
||||
Qt5::Quick
|
||||
Qt5::QuickControls2
|
||||
|
||||
KF5::ConfigCore
|
||||
KF5::ConfigGui
|
||||
KF5::CoreAddons
|
||||
KF5::DocTools
|
||||
KF5::FileMetaData
|
||||
KF5::KIOCore
|
||||
KF5::KIOFileWidgets
|
||||
KF5::KIOWidgets
|
||||
KF5::KIONTLM
|
||||
# KF5::Kirigami2
|
||||
KF5::XmlGui
|
||||
|
||||
Libmpv::Libmpv
|
||||
)
|
||||
|
||||
install(TARGETS cutefish-videoplayer DESTINATION ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
@ -1,15 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef __DEBUG_H
|
||||
#define __DEBUG_H
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#define DEBUG qDebug() << Q_FUNC_INFO << ':'
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,43 +0,0 @@
|
||||
#include "global.h"
|
||||
|
||||
#include "_debug.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
Global* Global::sm_instance = nullptr;
|
||||
|
||||
Global *Global::instance()
|
||||
{
|
||||
if (!sm_instance) {
|
||||
sm_instance = new Global();
|
||||
}
|
||||
return sm_instance;
|
||||
}
|
||||
|
||||
Global::Global()
|
||||
{
|
||||
m_config = KSharedConfig::openConfig("haruna/haruna.conf");
|
||||
m_ccConfig = KSharedConfig::openConfig("haruna/haruna-custom-commands.conf");
|
||||
}
|
||||
|
||||
const QString Global::systemConfigPath()
|
||||
{
|
||||
return QStandardPaths::writableLocation(m_config->locationType()).append("/");
|
||||
}
|
||||
|
||||
const QString Global::appConfigDirPath()
|
||||
{
|
||||
QFileInfo configFile(QString(systemConfigPath()).append(m_config->name()));
|
||||
return configFile.absolutePath();
|
||||
}
|
||||
|
||||
const QString Global::appConfigFilePath(ConfigFile configFile)
|
||||
{
|
||||
switch (configFile) {
|
||||
case ConfigFile::Main:
|
||||
return QString(systemConfigPath()).append(m_config->name());
|
||||
case ConfigFile::CustomCommands:
|
||||
return QString(systemConfigPath()).append(m_ccConfig->name());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
#ifndef GLOBALS_H
|
||||
#define GLOBALS_H
|
||||
|
||||
#include <QStandardPaths>
|
||||
#include <KSharedConfig>
|
||||
|
||||
class Global
|
||||
{
|
||||
public:
|
||||
Global();
|
||||
|
||||
enum ConfigFile {
|
||||
Main,
|
||||
CustomCommands
|
||||
};
|
||||
|
||||
const QString systemConfigPath();
|
||||
const QString appConfigDirPath();
|
||||
const QString appConfigFilePath(ConfigFile configFile = ConfigFile::Main);
|
||||
|
||||
static Global *instance();
|
||||
|
||||
private:
|
||||
KSharedConfig::Ptr m_config;
|
||||
KSharedConfig::Ptr m_ccConfig;
|
||||
static Global *sm_instance;
|
||||
};
|
||||
|
||||
#endif // GLOBALS_H
|
||||
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "haction.h"
|
||||
|
||||
#include <QKeySequence>
|
||||
|
||||
HAction::HAction(QObject *parent) : QAction(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString HAction::shortcutName()
|
||||
{
|
||||
return shortcut().toString();
|
||||
}
|
||||
|
||||
QString HAction::iconName()
|
||||
{
|
||||
return icon().name();
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef HACTION_H
|
||||
#define HACTION_H
|
||||
|
||||
#include <QAction>
|
||||
|
||||
/*
|
||||
* Needed because QAction fails to trigger for non english languages
|
||||
*/
|
||||
|
||||
class HAction : public QAction
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString shortcutName READ shortcutName NOTIFY changed)
|
||||
public:
|
||||
explicit HAction(QObject *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
QString shortcutName();
|
||||
QString iconName();
|
||||
|
||||
};
|
||||
|
||||
#endif // HACTION_H
|
||||
@ -1,157 +0,0 @@
|
||||
#include "customcommandsmodel.h"
|
||||
|
||||
#include "_debug.h"
|
||||
|
||||
#include <KConfigGroup>
|
||||
#include <global.h>
|
||||
|
||||
CustomCommandsModel::CustomCommandsModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
QString ccConfig = Global::instance()->appConfigFilePath(Global::ConfigFile::CustomCommands);
|
||||
m_customCommandsConfig = KSharedConfig::openConfig(ccConfig, KConfig::SimpleConfig);
|
||||
QStringList groups = m_customCommandsConfig->groupList();
|
||||
|
||||
beginInsertRows(QModelIndex(), 0, groups.size());
|
||||
for (const QString &groupName : qAsConst((groups))) {
|
||||
auto configGroup = m_customCommandsConfig->group(groupName);
|
||||
auto c = new Command();
|
||||
c->commandId = groupName;
|
||||
c->command = configGroup.readEntry("Command", QString());
|
||||
c->osdMessage = configGroup.readEntry("OsdMessage", QString());
|
||||
c->type = configGroup.readEntry("Type", QString());
|
||||
c->order = configGroup.readEntry("Order", 0);
|
||||
m_customCommands << c;
|
||||
}
|
||||
|
||||
std::sort(m_customCommands.begin(), m_customCommands.end(), [=](Command *c1, Command *c2) {
|
||||
return c1->order < c2->order;
|
||||
});
|
||||
|
||||
endInsertRows();
|
||||
|
||||
connect(this, &QAbstractListModel::rowsMoved, this, [=]() {
|
||||
for (int i = 0; i < m_customCommands.size(); ++i) {
|
||||
auto configGroup = m_customCommandsConfig->group(m_customCommands[i]->commandId);
|
||||
configGroup.writeEntry("Order", i);
|
||||
configGroup.sync();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
int CustomCommandsModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
|
||||
return m_customCommands.size();
|
||||
}
|
||||
|
||||
QVariant CustomCommandsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
Command *command = m_customCommands[index.row()];
|
||||
|
||||
switch (role) {
|
||||
case CommandIdRole:
|
||||
return QVariant(command->commandId);
|
||||
case CommandRole:
|
||||
return QVariant(command->command);
|
||||
case OsdMessageRole:
|
||||
return QVariant(command->osdMessage);
|
||||
case TypeRole:
|
||||
return QVariant(command->type);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QHash<int, QByteArray> CustomCommandsModel::roleNames() const
|
||||
{
|
||||
QHash<int, QByteArray> roles;
|
||||
roles[CommandIdRole] = "commandId";
|
||||
roles[OsdMessageRole] = "osdMessage";
|
||||
roles[CommandRole] = "command";
|
||||
roles[TypeRole] = "type";
|
||||
return roles;
|
||||
}
|
||||
|
||||
void CustomCommandsModel::moveRows(int oldIndex, int newIndex)
|
||||
{
|
||||
if (oldIndex < newIndex) {
|
||||
beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newIndex + 1);
|
||||
} else {
|
||||
beginMoveRows(QModelIndex(), oldIndex, oldIndex, QModelIndex(), newIndex);
|
||||
}
|
||||
Command *c = m_customCommands.takeAt(oldIndex);
|
||||
m_customCommands.insert(newIndex, c);
|
||||
endMoveRows();
|
||||
}
|
||||
|
||||
void CustomCommandsModel::saveCustomCommand(const QString &command, const QString &osdMessage, const QString &type)
|
||||
{
|
||||
int counter = m_customCommandsConfig->group(QString()).readEntry("Counter", 0);
|
||||
const QString &groupName = QString("Command_%1").arg(counter);
|
||||
|
||||
if (m_customCommandsConfig->group(groupName).exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_customCommandsConfig->group(groupName).writeEntry(QStringLiteral("Command"), command);
|
||||
m_customCommandsConfig->group(groupName).writeEntry(QStringLiteral("OsdMessage"), osdMessage);
|
||||
m_customCommandsConfig->group(groupName).writeEntry(QStringLiteral("Type"), type);
|
||||
m_customCommandsConfig->group(groupName).writeEntry(QStringLiteral("Order"), rowCount());
|
||||
m_customCommandsConfig->group(QString()).writeEntry(QStringLiteral("Counter"), counter + 1);
|
||||
m_customCommandsConfig->sync();
|
||||
|
||||
beginInsertRows(QModelIndex(), rowCount(), rowCount());
|
||||
auto configGroup = m_customCommandsConfig->group(groupName);
|
||||
auto p = new Command();
|
||||
p->commandId = groupName;
|
||||
p->command = configGroup.readEntry("Command", QString());
|
||||
p->osdMessage = configGroup.readEntry("OsdMessage", QString()),
|
||||
p->type = configGroup.readEntry("Type", QString());
|
||||
m_customCommands << p;
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void CustomCommandsModel::editCustomCommand(int row, const QString &command,
|
||||
const QString &osdMessage, const QString &type)
|
||||
{
|
||||
auto customCommand = m_customCommands[row];
|
||||
customCommand->command = command;
|
||||
customCommand->osdMessage = osdMessage;
|
||||
customCommand->type = type;
|
||||
|
||||
QString groupName = customCommand->commandId;
|
||||
m_customCommandsConfig->group(groupName).writeEntry(QStringLiteral("Command"), command);
|
||||
m_customCommandsConfig->group(groupName).writeEntry(QStringLiteral("OsdMessage"), osdMessage);
|
||||
m_customCommandsConfig->group(groupName).writeEntry(QStringLiteral("Type"), type);
|
||||
m_customCommandsConfig->sync();
|
||||
|
||||
emit dataChanged(index(row, 0), index(row, 0));
|
||||
}
|
||||
|
||||
void CustomCommandsModel::deleteCustomCommand(const QString &groupName, int row)
|
||||
{
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
m_customCommandsConfig->deleteGroup(groupName);
|
||||
m_customCommandsConfig->sync();
|
||||
m_customCommands.removeAt(row);
|
||||
endRemoveRows();
|
||||
|
||||
KSharedConfig::Ptr config = KSharedConfig::openConfig(Global::instance()->appConfigFilePath());
|
||||
config->group("Shortcuts").deleteEntry(groupName);
|
||||
config->sync();
|
||||
}
|
||||
|
||||
ProxyCustomCommandsModel::ProxyCustomCommandsModel(QObject *parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{
|
||||
setDynamicSortFilter(true);
|
||||
setFilterRole(CustomCommandsModel::TypeRole);
|
||||
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||
setFilterFixedString(QStringLiteral("shortcut"));
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
#ifndef CUSTOMCOMMANDSMODEL_H
|
||||
#define CUSTOMCOMMANDSMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <KSharedConfig>
|
||||
|
||||
class ProxyCustomCommandsModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProxyCustomCommandsModel(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
class CustomCommandsModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
struct Command {
|
||||
QString commandId;
|
||||
QString command;
|
||||
QString osdMessage;
|
||||
QString type;
|
||||
int order;
|
||||
};
|
||||
|
||||
public:
|
||||
explicit CustomCommandsModel(QObject *parent = nullptr);
|
||||
|
||||
enum Roles {
|
||||
CommandIdRole = Qt::UserRole + 1,
|
||||
CommandRole,
|
||||
OsdMessageRole,
|
||||
TypeRole,
|
||||
};
|
||||
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
QHash<int, QByteArray> roleNames() const;
|
||||
|
||||
Q_INVOKABLE void moveRows(int oldIndex, int newIndex);
|
||||
Q_INVOKABLE void saveCustomCommand(const QString &command,
|
||||
const QString &osdMessage,
|
||||
const QString &type);
|
||||
Q_INVOKABLE void editCustomCommand(int row,
|
||||
const QString &command,
|
||||
const QString &osdMessage,
|
||||
const QString &type);
|
||||
Q_INVOKABLE void deleteCustomCommand(const QString &groupName, int row);
|
||||
|
||||
private:
|
||||
KSharedConfig::Ptr m_customCommandsConfig;
|
||||
QList<Command *> m_customCommands;
|
||||
};
|
||||
|
||||
#endif // CUSTOMCOMMANDSMODEL_H
|
||||
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#include "_debug.h"
|
||||
#include "subtitlesfoldersmodel.h"
|
||||
#include "subtitlessettings.h"
|
||||
|
||||
#include <KConfig>
|
||||
#include <KConfigDialog>
|
||||
#include <KConfigGroup>
|
||||
#include <global.h>
|
||||
|
||||
SubtitlesFoldersModel::SubtitlesFoldersModel(QObject *parent)
|
||||
: QAbstractListModel(parent)
|
||||
{
|
||||
m_config = KSharedConfig::openConfig(Global::instance()->appConfigFilePath());
|
||||
m_list = m_config->group("Subtitles").readPathEntry("Folders", QStringList());
|
||||
}
|
||||
|
||||
int SubtitlesFoldersModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
// For list models only the root node (an invalid parent) should return the list's size. For all
|
||||
// other (valid) parents, rowCount() should return 0 so that it does not become a tree model.
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
|
||||
return m_list.size();
|
||||
}
|
||||
|
||||
QVariant SubtitlesFoldersModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
|
||||
QString path = m_list[index.row()];
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
return QVariant(path);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void SubtitlesFoldersModel::updateFolder(const QString &folder, int row)
|
||||
{
|
||||
m_list.replace(row, folder);
|
||||
QStringList newList = m_list;
|
||||
// remove empty strings
|
||||
// removing directly from m_list messes with the ui logic
|
||||
newList.removeAll(QString(""));
|
||||
|
||||
SubtitlesSettings::self()->setSubtitlesFolders(newList);
|
||||
SubtitlesSettings::self()->save();
|
||||
}
|
||||
|
||||
void SubtitlesFoldersModel::deleteFolder(int row)
|
||||
{
|
||||
beginRemoveRows(QModelIndex(), row, row);
|
||||
m_list.removeAt(row);
|
||||
endRemoveRows();
|
||||
m_config->group("Subtitles").writePathEntry("Folders", m_list);
|
||||
m_config->sync();
|
||||
}
|
||||
|
||||
void SubtitlesFoldersModel::addFolder()
|
||||
{
|
||||
beginInsertRows(QModelIndex(), m_list.size(), m_list.size());
|
||||
m_list.append(QStringLiteral());
|
||||
endInsertRows();
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef SUBTITLESFOLDERSMODEL_H
|
||||
#define SUBTITLESFOLDERSMODEL_H
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <KSharedConfig>
|
||||
|
||||
class SubtitlesFoldersModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SubtitlesFoldersModel(QObject *parent = nullptr);
|
||||
|
||||
// Basic functionality:
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
public slots:
|
||||
void updateFolder(const QString &folder, int row);
|
||||
void deleteFolder(int row);
|
||||
void addFolder();
|
||||
|
||||
private:
|
||||
QStringList m_list;
|
||||
KSharedConfig::Ptr m_config;
|
||||
};
|
||||
|
||||
#endif // SUBTITLESFOLDERSMODEL_H
|
||||
@ -1,40 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>qml/main.qml</file>
|
||||
<file>qml/PlayListItem.qml</file>
|
||||
<file>qml/PlayList.qml</file>
|
||||
<file>qml/MpvVideo.qml</file>
|
||||
<file>qml/HProgressBar.qml</file>
|
||||
<file>qml/Header.qml</file>
|
||||
<file>qml/Footer.qml</file>
|
||||
<file>qml/Osd.qml</file>
|
||||
<file>qml/Actions.qml</file>
|
||||
<file>qml/VolumeSlider.qml</file>
|
||||
<file>qml/Settings/SettingsEditor.qml</file>
|
||||
<file>qml/Haruna/Components/SubtitlesFolders.qml</file>
|
||||
<file alias="General.qml">qml/Settings/General.qml</file>
|
||||
<file alias="Mouse.qml">qml/Settings/Mouse.qml</file>
|
||||
<file alias="Navigation.qml">qml/Settings/Navigation.qml</file>
|
||||
<file alias="Playlist.qml">qml/Settings/Playlist.qml</file>
|
||||
<file alias="Audio.qml">qml/Settings/Audio.qml</file>
|
||||
<file alias="Subtitles.qml">qml/Settings/Subtitles.qml</file>
|
||||
<file alias="Playback.qml">qml/Settings/Playback.qml</file>
|
||||
<file>qml/Menus/FileMenu.qml</file>
|
||||
<file>qml/Menus/PlaybackMenu.qml</file>
|
||||
<file>qml/Menus/SubtitlesMenu.qml</file>
|
||||
<file>qml/Menus/SettingsMenu.qml</file>
|
||||
<file>qml/Menus/AudioMenu.qml</file>
|
||||
<file>qml/Menus/ViewMenu.qml</file>
|
||||
<file>qml/Menus/TrackMenuItems.qml</file>
|
||||
<file>qml/Haruna/Components/SelectActionPopup.qml</file>
|
||||
<file alias="VideoSettings.qml">qml/Settings/VideoSettings.qml</file>
|
||||
<file>qml/Menus/HelpMenu.qml</file>
|
||||
<file>qml/Haruna/Components/LabelWithTooltip.qml</file>
|
||||
<file>qml/Haruna/Components/SettingsHeader.qml</file>
|
||||
<file>qml/Haruna/Components/SettingsBasePage.qml</file>
|
||||
<file>qml/Haruna/Components/qmldir</file>
|
||||
<file>qml/Haruna/Components/ImageAdjustmentSlider.qml</file>
|
||||
<file alias="CustomCommands.qml">qml/Settings/CustomCommands.qml</file>
|
||||
<file alias="EditCustomCommand.qml">qml/Settings/EditCustomCommand.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@ -1,3 +0,0 @@
|
||||
SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: CC-BY-4.0
|
||||
@ -1,209 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2021 Reion Wong <aj@cutefishos.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtGraphicalEffects 1.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
|
||||
import org.kde.haruna 1.0
|
||||
import Haruna.Components 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property alias progressBar: progressBar
|
||||
property alias footerRow: footerRow
|
||||
property alias timeInfo: timeInfo
|
||||
property alias playPauseButton: playPauseButton
|
||||
property alias volume: volume
|
||||
|
||||
height: progressBar.height + 50 + FishUI.Units.smallSpacing
|
||||
// height: mainLayout.childrenRect.height + FishUI.Units.smallSpacing
|
||||
opacity: mpv.mouseY > window.height - footer.height - FishUI.Units.largeSpacing * 3
|
||||
&& playList.state === "hidden" ? 1 : 0
|
||||
enabled: opacity !== 0
|
||||
visible: true
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
duration: 180
|
||||
}
|
||||
}
|
||||
|
||||
ShaderEffectSource {
|
||||
id: shaderEffect
|
||||
visible: true
|
||||
anchors.fill: parent
|
||||
sourceItem: mpv
|
||||
sourceRect: Qt.rect(0, 0, root.width, root.height)
|
||||
}
|
||||
|
||||
FastBlur {
|
||||
visible: true
|
||||
anchors.fill: shaderEffect
|
||||
source: shaderEffect
|
||||
radius: 100
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: _background
|
||||
anchors.fill: parent
|
||||
color: FishUI.Theme.backgroundColor
|
||||
opacity: 0.8
|
||||
}
|
||||
|
||||
// layer.enabled: true
|
||||
// layer.effect: OpacityMask {
|
||||
// maskSource: Item {
|
||||
// width: root.width
|
||||
// height: root.height
|
||||
|
||||
// Rectangle {
|
||||
// anchors.fill: parent
|
||||
// radius: FishUI.Theme.bigRadius
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
Component {
|
||||
id: togglePlaylistButton
|
||||
|
||||
ToolButton {
|
||||
action: actions.togglePlaylistAction
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: mainLayout
|
||||
anchors.fill: parent
|
||||
anchors.topMargin: 0
|
||||
anchors.bottomMargin: FishUI.Units.smallSpacing
|
||||
spacing: FishUI.Units.smallSpacing
|
||||
|
||||
HProgressBar {
|
||||
id: progressBar
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: footerRow
|
||||
|
||||
Item {
|
||||
width: FishUI.Units.smallSpacing
|
||||
}
|
||||
|
||||
Item {
|
||||
id: leftItem
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Label {
|
||||
id: timeInfo
|
||||
text: app.formatTime(mpv.position) + " / " + app.formatTime(mpv.duration)
|
||||
font.pointSize: FishUI.Units.gridUnit - 6
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: middleItem
|
||||
Layout.preferredWidth: middleLayout.childrenRect.width
|
||||
Layout.fillHeight: true
|
||||
|
||||
RowLayout {
|
||||
id: middleLayout
|
||||
anchors.fill: parent
|
||||
|
||||
ToolButton {
|
||||
id: playPreviousFile
|
||||
action: actions.playPreviousAction
|
||||
text: ""
|
||||
focusPolicy: Qt.NoFocus
|
||||
enabled: playList.playlistView.count > 1
|
||||
|
||||
ToolTip {
|
||||
text: qsTr("Play previous file")
|
||||
}
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: playPauseButton
|
||||
action: actions.playPauseAction
|
||||
text: ""
|
||||
icon.name: "media-playback-start"
|
||||
focusPolicy: Qt.NoFocus
|
||||
|
||||
ToolTip {
|
||||
id: playPauseButtonToolTip
|
||||
text: mpv.pause ? qsTr("Start Playback") : qsTr("Pause Playback")
|
||||
}
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: playNextFile
|
||||
action: actions.playNextAction
|
||||
text: ""
|
||||
focusPolicy: Qt.NoFocus
|
||||
enabled: playList.playlistView.count > 1
|
||||
|
||||
ToolTip {
|
||||
text: qsTr("Play next file")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: rightItem
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
spacing: FishUI.Units.smallSpacing
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: mute
|
||||
action: actions.muteAction
|
||||
text: ""
|
||||
focusPolicy: Qt.NoFocus
|
||||
|
||||
ToolTip {
|
||||
text: actions.muteAction.text
|
||||
}
|
||||
}
|
||||
|
||||
VolumeSlider { id: volume }
|
||||
|
||||
Item {
|
||||
width: 1
|
||||
}
|
||||
|
||||
Loader {
|
||||
sourceComponent: togglePlaylistButton
|
||||
visible: true
|
||||
}
|
||||
|
||||
Item {
|
||||
width: FishUI.Units.smallSpacing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
|
||||
RowLayout {
|
||||
id: root
|
||||
|
||||
property int value: 0
|
||||
signal sliderValueChanged(int value)
|
||||
|
||||
Slider {
|
||||
id: slider
|
||||
|
||||
from: -100
|
||||
to: 100
|
||||
value: root.value
|
||||
wheelEnabled: true
|
||||
stepSize: 1
|
||||
onValueChanged: root.sliderValueChanged(value.toFixed(0))
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.MiddleButton
|
||||
onClicked: slider.value = 0
|
||||
}
|
||||
|
||||
Component.onCompleted: background.activeControl = ""
|
||||
}
|
||||
|
||||
Label {
|
||||
text: slider.value
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: 40
|
||||
}
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12 as QQC2
|
||||
import QtQuick.Layouts 1.12
|
||||
|
||||
QQC2.Label {
|
||||
id: root
|
||||
|
||||
property string toolTipText
|
||||
property int toolTipFontSize
|
||||
property bool alwaysShowToolTip
|
||||
|
||||
QQC2.ToolTip {
|
||||
id: toolTip
|
||||
|
||||
visible: (root.alwaysShowToolTip && mouseArea.containsMouse) || (mouseArea.containsMouse && root.truncated)
|
||||
text: root.toolTipText ? root.toolTipText : root.text
|
||||
font.pointSize: root.toolTipFontSize ? root.toolTipFontSize : root.font.pointSize
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.NoButton
|
||||
hoverEnabled: true
|
||||
}
|
||||
}
|
||||
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import org.kde.kirigami 2.11 as Kirigami
|
||||
|
||||
Popup {
|
||||
id: root
|
||||
|
||||
property string headerTitle
|
||||
property int buttonIndex: -1
|
||||
|
||||
signal actionSelected(string actionName)
|
||||
|
||||
implicitHeight: parent.height * 0.9
|
||||
implicitWidth: parent.width * 0.9
|
||||
modal: true
|
||||
anchors.centerIn: parent
|
||||
focus: true
|
||||
|
||||
onOpened: {
|
||||
filterActionsField.text = ""
|
||||
filterActionsField.focus = true
|
||||
}
|
||||
|
||||
onActionSelected: close()
|
||||
|
||||
Action {
|
||||
shortcut: "ctrl+f"
|
||||
onTriggered: filterActionsField.forceActiveFocus(Qt.ShortcutFocusReason)
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Kirigami.Heading {
|
||||
text: root.headerTitle
|
||||
}
|
||||
|
||||
Label {
|
||||
text: i18n("Double click to set action")
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: filterActionsField
|
||||
|
||||
placeholderText: i18n("Type to filter...")
|
||||
focus: true
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop
|
||||
KeyNavigation.up: actionsListView
|
||||
KeyNavigation.down: clearActionButton
|
||||
|
||||
onTextChanged: {
|
||||
const menuModel = actionsListView.actionsList
|
||||
actionsListView.model = menuModel.filter(action => action.toLowerCase().includes(text))
|
||||
}
|
||||
}
|
||||
Button {
|
||||
id: clearActionButton
|
||||
|
||||
Layout.fillWidth: true
|
||||
text: i18n("Clear current action")
|
||||
KeyNavigation.up: filterActionsField
|
||||
KeyNavigation.down: actionsListView
|
||||
onClicked: actionSelected("")
|
||||
Keys.onEnterPressed: actionSelected("")
|
||||
Keys.onReturnPressed: actionSelected("")
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: actionsListView
|
||||
|
||||
property var actionsList: Object.keys(window.appActions).sort()
|
||||
|
||||
implicitHeight: 30 * model.count
|
||||
model: actionsList
|
||||
spacing: 1
|
||||
clip: true
|
||||
currentIndex: focus ? 0 : -1
|
||||
delegate: Kirigami.BasicListItem {
|
||||
height: 30
|
||||
width: root.width
|
||||
label: modelData
|
||||
reserveSpaceForIcon: false
|
||||
onDoubleClicked: actionSelected(modelData)
|
||||
Keys.onEnterPressed: actionSelected(modelData)
|
||||
Keys.onReturnPressed: actionSelected(modelData)
|
||||
}
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
Layout.alignment: Qt.AlignTop
|
||||
KeyNavigation.up: clearActionButton
|
||||
KeyNavigation.down: filterActionsField
|
||||
Keys.onPressed: {
|
||||
if (event.key === Qt.Key_End) {
|
||||
actionsListView.currentIndex = actionsListView.count - 1
|
||||
actionsListView.positionViewAtIndex(actionsListView.currentIndex,ListView.Center)
|
||||
}
|
||||
if (event.key === Qt.Key_Home) {
|
||||
actionsListView.currentIndex = 0
|
||||
actionsListView.positionViewAtIndex(actionsListView.currentIndex,ListView.Center)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQml 2.12
|
||||
|
||||
import org.kde.kirigami 2.11 as Kirigami
|
||||
import org.kde.haruna 1.0
|
||||
|
||||
Kirigami.ScrollablePage {
|
||||
id: root
|
||||
|
||||
property bool hasHelp: false
|
||||
property string helpFile: ""
|
||||
property string docPage: ""
|
||||
|
||||
actions {
|
||||
contextualActions: [
|
||||
Kirigami.Action {
|
||||
text: qsTr("Help!")
|
||||
iconName: "system-help"
|
||||
Kirigami.Action {
|
||||
text: qsTr("Haruna help window (english only)")
|
||||
enabled: root.hasHelp
|
||||
onTriggered: root.hasHelp ? helpWindow.show() : undefined
|
||||
}
|
||||
Kirigami.Action {
|
||||
text: qsTr("KHelpCenter")
|
||||
enabled: root.docPage !== ""
|
||||
onTriggered: enabled ? app.openDocs(root.docPage) : undefined
|
||||
}
|
||||
},
|
||||
Kirigami.Action {
|
||||
text: qsTr("Open config ...")
|
||||
iconName: "folder"
|
||||
Kirigami.Action {
|
||||
text: qsTr("File")
|
||||
onTriggered: Qt.openUrlExternally(app.configFilePath)
|
||||
}
|
||||
Kirigami.Action {
|
||||
text: qsTr("Folder")
|
||||
onTriggered: Qt.openUrlExternally(app.configFolderPath)
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import org.kde.kirigami 2.11 as Kirigami
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
property string text: ""
|
||||
property int topMargin: Kirigami.Units.gridUnit
|
||||
|
||||
spacing: 0
|
||||
|
||||
Item {
|
||||
width: 1
|
||||
height: root.topMargin
|
||||
visible: root.topMargin > 0
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Rectangle {
|
||||
width: Kirigami.Units.gridUnit
|
||||
height: 1
|
||||
color: Kirigami.Theme.alternateBackgroundColor
|
||||
}
|
||||
|
||||
Kirigami.Heading {
|
||||
text: root.text
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
height: 1
|
||||
color: Kirigami.Theme.alternateBackgroundColor
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,165 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import org.kde.kirigami 2.11 as Kirigami
|
||||
|
||||
// Subtitles Folders
|
||||
Item {
|
||||
id: root
|
||||
|
||||
// prevent creating multiple empty items
|
||||
// until the new one has been saved
|
||||
property bool canAddFolder: true
|
||||
|
||||
Layout.fillWidth: true
|
||||
implicitHeight: sectionTitle.height + sfListView.implicitHeight + sfAddFolder.height + 25
|
||||
|
||||
Label {
|
||||
id: sectionTitle
|
||||
|
||||
text: i18n("Load subtitles from")
|
||||
bottomPadding: 10
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: sfListView
|
||||
property int sfDelegateHeight: 40
|
||||
|
||||
anchors.top: sectionTitle.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
implicitHeight: count > 5
|
||||
? 5 * sfListView.sfDelegateHeight + (sfListView.spacing * 4)
|
||||
: count * sfListView.sfDelegateHeight + (sfListView.spacing * (count - 1))
|
||||
spacing: 5
|
||||
clip: true
|
||||
model: subsFoldersModel
|
||||
Layout.fillWidth: true
|
||||
ScrollBar.vertical: ScrollBar { id: scrollBar }
|
||||
delegate: Rectangle {
|
||||
id: sfDelegate
|
||||
width: root.width
|
||||
height: sfListView.sfDelegateHeight
|
||||
color: Kirigami.Theme.alternateBackgroundColor
|
||||
|
||||
Loader {
|
||||
id: sfLoader
|
||||
anchors.fill: parent
|
||||
sourceComponent: model.display === "" ? sfEditComponent : sfDisplayComponent
|
||||
}
|
||||
|
||||
Component {
|
||||
id: sfDisplayComponent
|
||||
|
||||
RowLayout {
|
||||
|
||||
Label {
|
||||
id: sfLabel
|
||||
text: model.display
|
||||
leftPadding: 10
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Button {
|
||||
icon.name: "edit-entry"
|
||||
flat: true
|
||||
onClicked: {
|
||||
sfLoader.sourceComponent = sfEditComponent
|
||||
}
|
||||
}
|
||||
|
||||
Item { width: scrollBar.width }
|
||||
}
|
||||
} // Component: display
|
||||
|
||||
Component {
|
||||
id: sfEditComponent
|
||||
|
||||
RowLayout {
|
||||
|
||||
TextField {
|
||||
id: editField
|
||||
leftPadding: 10
|
||||
text: model.display
|
||||
Layout.leftMargin: 5
|
||||
Layout.fillWidth: true
|
||||
Component.onCompleted: editField.forceActiveFocus(Qt.MouseFocusReason)
|
||||
}
|
||||
|
||||
Button {
|
||||
property bool canDelete: editField.text === ""
|
||||
icon.name: "delete"
|
||||
flat: true
|
||||
onClicked: {
|
||||
if (!canDelete) {
|
||||
text = i18n("Confirm deletion")
|
||||
canDelete = true
|
||||
return
|
||||
}
|
||||
|
||||
if (model.row === sfListView.count - 1) {
|
||||
root.canAddFolder = true
|
||||
}
|
||||
subsFoldersModel.deleteFolder(model.row)
|
||||
const rows = sfListView.count
|
||||
sfListView.implicitHeight = rows > 5
|
||||
? 5 * sfListView.sfDelegateHeight + (sfListView.spacing * 4)
|
||||
: rows * sfListView.sfDelegateHeight + (sfListView.spacing * (rows - 1))
|
||||
|
||||
}
|
||||
ToolTip {
|
||||
text: i18n("Delete this folder from list")
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
icon.name: "dialog-ok"
|
||||
flat: true
|
||||
enabled: editField.text !== "" ? true : false
|
||||
onClicked: {
|
||||
subsFoldersModel.updateFolder(editField.text, model.row)
|
||||
sfLoader.sourceComponent = sfDisplayComponent
|
||||
if (model.row === sfListView.count - 1) {
|
||||
root.canAddFolder = true
|
||||
}
|
||||
}
|
||||
ToolTip {
|
||||
text: i18n("Save changes")
|
||||
}
|
||||
}
|
||||
|
||||
Item { width: scrollBar.width }
|
||||
}
|
||||
} // Component: edit
|
||||
} // delegate: Rectangle
|
||||
}
|
||||
|
||||
Item {
|
||||
id: spacer
|
||||
anchors.top: sfListView.bottom
|
||||
height: 5
|
||||
}
|
||||
|
||||
Button {
|
||||
id: sfAddFolder
|
||||
anchors.top: spacer.bottom
|
||||
icon.name: "list-add"
|
||||
text: i18n("Add new folder")
|
||||
enabled: root.canAddFolder
|
||||
onClicked: {
|
||||
subsFoldersModel.addFolder()
|
||||
const rows = sfListView.count
|
||||
sfListView.implicitHeight = rows > 5
|
||||
? 5 * sfListView.sfDelegateHeight + (sfListView.spacing * 4)
|
||||
: rows * sfListView.sfDelegateHeight + (sfListView.spacing * (rows - 1))
|
||||
root.canAddFolder = false
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2021 George Florea Bănuș <georgefb899@gmail.com>
|
||||
#
|
||||
# SPDX-License-Identifier: CC-BY-4.0
|
||||
#
|
||||
|
||||
module Haruna.Components
|
||||
LabelWithTooltip 1.0 LabelWithTooltip.qml
|
||||
ImageAdjustmentSlider 1.0 ImageAdjustmentSlider.qml
|
||||
SettingsBasePage 1.0 SettingsBasePage.qml
|
||||
SettingsHeader 1.0 SettingsHeader.qml
|
||||
SubtitlesFolders 1.0 SubtitlesFolders.qml
|
||||
SelectActionPopup 1.0 SelectActionPopup.qml
|
||||
@ -1,179 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQml 2.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
import org.kde.haruna 1.0
|
||||
|
||||
import "Menus"
|
||||
|
||||
ToolBar {
|
||||
id: root
|
||||
|
||||
property var audioTracks
|
||||
property var subtitleTracks
|
||||
|
||||
position: ToolBar.Header
|
||||
visible: !window.isFullScreen() && GeneralSettings.showHeader
|
||||
|
||||
RowLayout {
|
||||
id: headerRow
|
||||
|
||||
width: parent.width
|
||||
|
||||
ToolButton {
|
||||
action: actions.openAction
|
||||
focusPolicy: Qt.NoFocus
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
action: actions.openUrlAction
|
||||
focusPolicy: Qt.NoFocus
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.MiddleButton
|
||||
onClicked: {
|
||||
openUrlTextField.clear()
|
||||
openUrlTextField.paste()
|
||||
window.openFile(openUrlTextField.text, true, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ToolSeparator {
|
||||
padding: vertical ? 10 : 2
|
||||
topPadding: vertical ? 2 : 10
|
||||
bottomPadding: vertical ? 2 : 10
|
||||
|
||||
contentItem: Rectangle {
|
||||
implicitWidth: parent.vertical ? 1 : 24
|
||||
implicitHeight: parent.vertical ? 24 : 1
|
||||
color: FishUI.Theme.textColor
|
||||
}
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: subtitleMenuButton
|
||||
|
||||
property var model: 0
|
||||
|
||||
text: qsTr("Subtitles")
|
||||
icon.name: "add-subtitle"
|
||||
focusPolicy: Qt.NoFocus
|
||||
|
||||
onClicked: {
|
||||
if (subtitleMenuButton.model === 0) {
|
||||
subtitleMenuButton.model = mpv.subtitleTracksModel
|
||||
}
|
||||
|
||||
subtitleMenu.visible = !subtitleMenu.visible
|
||||
}
|
||||
|
||||
Menu {
|
||||
id: subtitleMenu
|
||||
|
||||
y: parent.height
|
||||
|
||||
Menu {
|
||||
id: secondarySubtitleMenu
|
||||
|
||||
title: qsTr("Secondary Subtitle")
|
||||
|
||||
Instantiator {
|
||||
id: secondarySubtitleMenuInstantiator
|
||||
model: subtitleMenuButton.model
|
||||
onObjectAdded: secondarySubtitleMenu.insertItem( index, object )
|
||||
onObjectRemoved: secondarySubtitleMenu.removeItem( object )
|
||||
delegate: MenuItem {
|
||||
enabled: model.id !== mpv.subtitleId || model.id === 0
|
||||
checkable: true
|
||||
checked: model.id === mpv.secondarySubtitleId
|
||||
text: model.text
|
||||
onTriggered: mpv.secondarySubtitleId = model.id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Primary Subtitle")
|
||||
hoverEnabled: false
|
||||
}
|
||||
|
||||
Instantiator {
|
||||
id: primarySubtitleMenuInstantiator
|
||||
model: subtitleMenuButton.model
|
||||
onObjectAdded: subtitleMenu.addItem( object )
|
||||
onObjectRemoved: subtitleMenu.removeItem( object )
|
||||
delegate: MenuItem {
|
||||
enabled: model.id !== mpv.secondarySubtitleId || model.id === 0
|
||||
checkable: true
|
||||
checked: model.id === mpv.subtitleId
|
||||
text: model.text
|
||||
onTriggered: mpv.subtitleId = model.id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
text: qsTr("Audio")
|
||||
icon.name: "audio-volume-high"
|
||||
focusPolicy: Qt.NoFocus
|
||||
|
||||
onClicked: {
|
||||
if (audioMenuInstantiator.model === 0) {
|
||||
audioMenuInstantiator.model = mpv.audioTracksModel
|
||||
}
|
||||
audioMenu.visible = !audioMenu.visible
|
||||
}
|
||||
|
||||
Menu {
|
||||
id: audioMenu
|
||||
|
||||
y: parent.height
|
||||
|
||||
Instantiator {
|
||||
id: audioMenuInstantiator
|
||||
|
||||
model: 0
|
||||
onObjectAdded: audioMenu.insertItem( index, object )
|
||||
onObjectRemoved: audioMenu.removeItem( object )
|
||||
delegate: MenuItem {
|
||||
id: audioMenuItem
|
||||
checkable: true
|
||||
checked: model.id === mpv.audioId
|
||||
text: model.text
|
||||
onTriggered: mpv.audioId = model.id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
action: actions.configureAction
|
||||
focusPolicy: Qt.NoFocus
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
// using `action: actions.quitApplicationAction` breaks the action
|
||||
// doens't work on the first try in certain circumstances
|
||||
text: actions.quitApplicationAction.text
|
||||
icon: actions.quitApplicationAction.icon
|
||||
focusPolicy: Qt.NoFocus
|
||||
onClicked: actions.quitApplicationAction.trigger()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQml 2.12
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
Menu {
|
||||
id: root
|
||||
|
||||
title: i18n("&Audio")
|
||||
|
||||
Menu {
|
||||
id: audioMenu
|
||||
|
||||
title: i18n("&Primary Track")
|
||||
|
||||
Instantiator {
|
||||
id: audioMenuInstantiator
|
||||
model: 0
|
||||
onObjectAdded: audioMenu.insertItem( index, object )
|
||||
onObjectRemoved: audioMenu.removeItem( object )
|
||||
delegate: MenuItem {
|
||||
id: audioMenuItem
|
||||
checkable: true
|
||||
checked: model.id === mpv.audioId
|
||||
text: model.text
|
||||
onTriggered: mpv.audioId = model.id
|
||||
}
|
||||
}
|
||||
Connections {
|
||||
target: mpv
|
||||
onFileLoaded: {
|
||||
audioMenuInstantiator.model = mpv.audioTracksModel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
MenuItem { action: actions["muteAction"] }
|
||||
MenuItem { action: actions["volumeUpAction"] }
|
||||
MenuItem { action: actions["volumeDownAction"] }
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
Menu {
|
||||
id: root
|
||||
|
||||
title: i18n("&File")
|
||||
|
||||
MenuItem { action: actions["openAction"] }
|
||||
MenuItem { action: actions["openUrlAction"] }
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
MenuItem { action: actions["quitApplicationAction"] }
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
Menu {
|
||||
id: root
|
||||
|
||||
title: i18n("&Help")
|
||||
|
||||
MenuItem { action: actions["aboutHarunaAction"] }
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
Menu {
|
||||
id: root
|
||||
|
||||
title: i18n("&Playback")
|
||||
|
||||
MenuItem { action: actions["playPauseAction"] }
|
||||
MenuItem { action: actions["playNextAction"] }
|
||||
MenuItem { action: actions["playPreviousAction"] }
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
MenuItem { action: actions["increasePlayBackSpeedAction"] }
|
||||
MenuItem { action: actions["decreasePlayBackSpeedAction"] }
|
||||
MenuItem { action: actions["resetPlayBackSpeedAction"] }
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
Menu {
|
||||
title: "Seek"
|
||||
MenuItem { action: actions["seekForwardSmallAction"] }
|
||||
MenuItem { action: actions["seekBackwardSmallAction"] }
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
MenuItem { action: actions["seekForwardMediumAction"] }
|
||||
MenuItem { action: actions["seekBackwardMediumAction"] }
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
MenuItem { action: actions["seekForwardBigAction"] }
|
||||
MenuItem { action: actions["seekBackwardBigAction"] }
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
MenuItem { action: actions["seekNextSubtitleAction"] }
|
||||
MenuItem { action: actions["seekPrevSubtitleAction"] }
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
MenuItem { action: actions["seekPreviousChapterAction"] }
|
||||
MenuItem { action: actions["seekNextChapterAction"] }
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
MenuItem { action: actions["frameStepAction"] }
|
||||
MenuItem { action: actions["frameBackStepAction"] }
|
||||
}
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
Menu {
|
||||
id: root
|
||||
|
||||
title: i18n("&Settings")
|
||||
|
||||
MenuItem { action: actions["configureAction"] }
|
||||
MenuItem { action: actions["configureShortcutsAction"] }
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQml 2.12
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
Menu {
|
||||
id: root
|
||||
|
||||
title: i18n("&Subtitles")
|
||||
|
||||
Menu {
|
||||
id: primarySubtitleMenu
|
||||
|
||||
title: i18n("Primary Subtitle")
|
||||
onOpened: primarySubtitleMenuInstantiator.model = mpv.subtitleTracksModel
|
||||
|
||||
Instantiator {
|
||||
id: primarySubtitleMenuInstantiator
|
||||
model: 0
|
||||
onObjectAdded: primarySubtitleMenu.insertItem( index, object )
|
||||
onObjectRemoved: primarySubtitleMenu.removeItem( object )
|
||||
delegate: MenuItem {
|
||||
enabled: model.id !== mpv.secondarySubtitleId || model.id === 0
|
||||
checkable: true
|
||||
checked: model.id === mpv.subtitleId
|
||||
text: model.text
|
||||
onTriggered: mpv.subtitleId = model.id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Menu {
|
||||
id: secondarySubtitleMenu
|
||||
|
||||
title: i18n("Secondary Subtitle")
|
||||
onOpened: secondarySubtitleMenuInstantiator.model = mpv.subtitleTracksModel
|
||||
|
||||
Instantiator {
|
||||
id: secondarySubtitleMenuInstantiator
|
||||
model: 0
|
||||
onObjectAdded: secondarySubtitleMenu.insertItem( index, object )
|
||||
onObjectRemoved: secondarySubtitleMenu.removeItem( object )
|
||||
delegate: MenuItem {
|
||||
enabled: model.id !== mpv.subtitleId || model.id === 0
|
||||
checkable: true
|
||||
checked: model.id === mpv.secondarySubtitleId
|
||||
text: model.text
|
||||
onTriggered: mpv.secondarySubtitleId = model.id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MenuSeparator {}
|
||||
|
||||
MenuItem { action: actions["subtitleQuickenAction"] }
|
||||
MenuItem { action: actions["subtitleDelayAction"] }
|
||||
MenuItem { action: actions["subtitleToggleAction"] }
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQml 2.12
|
||||
|
||||
Instantiator {
|
||||
id: root
|
||||
|
||||
property bool isFirst: true
|
||||
property var menu
|
||||
|
||||
signal subtitleChanged(int id, int index)
|
||||
|
||||
model: 0
|
||||
onObjectAdded: menu.addItem( object )
|
||||
onObjectRemoved: menu.removeItem( object )
|
||||
delegate: MenuItem {
|
||||
checkable: true
|
||||
checked: isFirst ? model.isFirstTrack : model.isSecondTrack
|
||||
text: model.text
|
||||
onTriggered: subtitleChanged(model.id, model.index)
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
Menu {
|
||||
id: root
|
||||
|
||||
title: i18n("&View")
|
||||
|
||||
MenuItem {
|
||||
action: actions["toggleMenuBarAction"]
|
||||
text: menuBar.visible ? i18n("Hide Menu Bar") : i18n("Show Menu Bar")
|
||||
}
|
||||
MenuItem {
|
||||
action: actions["toggleHeaderAction"]
|
||||
text: header.visible ? i18n("Hide Header") : i18n("Show Header")
|
||||
}
|
||||
}
|
||||
@ -1,392 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Window 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import mpv 1.0
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
|
||||
import org.kde.haruna 1.0
|
||||
|
||||
MpvObject {
|
||||
id: root
|
||||
|
||||
property int mouseX: mouseArea.mouseX
|
||||
property int mouseY: mouseArea.mouseY
|
||||
|
||||
signal setSubtitle(int id)
|
||||
signal setSecondarySubtitle(int id)
|
||||
signal setAudio(int id)
|
||||
|
||||
width: parent.width
|
||||
height: window.isFullScreen() ? parent.height : parent.height - footer.height
|
||||
anchors.left: PlaylistSettings.overlayVideo
|
||||
? parent.left
|
||||
: (PlaylistSettings.position === "left" ? playList.right : parent.left)
|
||||
anchors.right: PlaylistSettings.overlayVideo
|
||||
? parent.right
|
||||
: (PlaylistSettings.position === "right" ? playList.left : parent.right)
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
volume: GeneralSettings.volume
|
||||
|
||||
onSetSubtitle: {
|
||||
setProperty("sid", id)
|
||||
}
|
||||
|
||||
onSetSecondarySubtitle: {
|
||||
setProperty("secondary-sid", id)
|
||||
}
|
||||
|
||||
onSetAudio: {
|
||||
setProperty("aid", id)
|
||||
}
|
||||
|
||||
onReady: {
|
||||
setProperty("screenshot-template", VideoSettings.screenshotTemplate)
|
||||
setProperty("screenshot-format", VideoSettings.screenshotFormat)
|
||||
const preferredAudioTrack = AudioSettings.preferredTrack
|
||||
setProperty("aid", preferredAudioTrack === 0 ? "auto" : preferredAudioTrack)
|
||||
setProperty("alang", AudioSettings.preferredLanguage)
|
||||
|
||||
const preferredSubTrack = SubtitlesSettings.preferredTrack
|
||||
setProperty("sid", preferredSubTrack === 0 ? "auto" : preferredSubTrack)
|
||||
setProperty("slang", SubtitlesSettings.preferredLanguage)
|
||||
setProperty("sub-file-paths", SubtitlesSettings.subtitlesFolders.join(":"))
|
||||
|
||||
if (app.argument(0) !== "") {
|
||||
window.openFile(app.argument(0), true, PlaylistSettings.loadSiblings)
|
||||
} else {
|
||||
// open last played file
|
||||
if (app.isYoutubePlaylist(GeneralSettings.lastPlayedFile)) {
|
||||
getYouTubePlaylist(GeneralSettings.lastPlayedFile)
|
||||
playList.isYouTubePlaylist = true
|
||||
} else {
|
||||
// file is local, open normally
|
||||
window.openFile(GeneralSettings.lastPlayedFile, false, PlaylistSettings.loadSiblings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onYoutubePlaylistLoaded: {
|
||||
mpv.command(["loadfile", playlistModel.getPath(GeneralSettings.lastPlaylistIndex)])
|
||||
playlistModel.setPlayingVideo(GeneralSettings.lastPlaylistIndex)
|
||||
|
||||
playList.setPlayListScrollPosition()
|
||||
}
|
||||
|
||||
onFileStarted: {
|
||||
if (typeof getProperty("path") === "string" && getProperty("path").startsWith("http")) {
|
||||
loadingIndicatorParent.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
onFileLoaded: {
|
||||
loadingIndicatorParent.visible = false
|
||||
header.audioTracks = getProperty("track-list").filter(track => track["type"] === "audio")
|
||||
header.subtitleTracks = getProperty("track-list").filter(track => track["type"] === "sub")
|
||||
|
||||
if (playList.playlistView.count <= 1) {
|
||||
setProperty("loop-file", "inf")
|
||||
}
|
||||
|
||||
setProperty("ab-loop-a", "no")
|
||||
setProperty("ab-loop-b", "no")
|
||||
|
||||
mpv.pause = loadTimePosition() !== 0
|
||||
position = loadTimePosition()
|
||||
}
|
||||
|
||||
onChapterChanged: {
|
||||
if (!PlaybackSettings.skipChapters) {
|
||||
return
|
||||
}
|
||||
|
||||
const chapters = mpv.getProperty("chapter-list")
|
||||
const chaptersToSkip = PlaybackSettings.chaptersToSkip
|
||||
if (chapters.length === 0 || chaptersToSkip === "") {
|
||||
return
|
||||
}
|
||||
|
||||
const words = chaptersToSkip.split(",")
|
||||
for (let i = 0; i < words.length; ++i) {
|
||||
if (chapters[mpv.chapter] && chapters[mpv.chapter].title.toLowerCase().includes(words[i].trim())) {
|
||||
actions.seekNextChapterAction.trigger()
|
||||
if (PlaybackSettings.showOsdOnSkipChapters) {
|
||||
osd.message(i18n("Skipped chapter: %1").arg(chapters[mpv.chapter-1].title))
|
||||
}
|
||||
// a chapter title can match multiple words
|
||||
// return to prevent skipping multiple chapters
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onEndFile: {
|
||||
if (reason === "error") {
|
||||
if (playlistModel.rowCount() === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const title = playlistModel.getItem(playlistModel.getPlayingVideo()).mediaTitle()
|
||||
osd.message(i18n("Could not play: %1").arg(title))
|
||||
// only skip to next video if it's a youtube playList
|
||||
// to do: figure out why playback fails and act accordingly
|
||||
if (!playList.isYouTubePlaylist) {
|
||||
return
|
||||
}
|
||||
}
|
||||
const nextFileRow = playlistModel.getPlayingVideo() + 1
|
||||
if (nextFileRow < playList.playlistView.count) {
|
||||
const nextFile = playlistModel.getPath(nextFileRow)
|
||||
playlistModel.setPlayingVideo(nextFileRow)
|
||||
loadFile(nextFile, !playList.isYouTubePlaylist)
|
||||
} else {
|
||||
// Last file in playlist
|
||||
if (PlaylistSettings.repeat) {
|
||||
playlistModel.setPlayingVideo(0)
|
||||
loadFile(playlistModel.getPath(0), !playList.isYouTubePlaylist)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onPauseChanged: {
|
||||
if (pause) {
|
||||
footer.playPauseButton.icon.name = "media-playback-start"
|
||||
lockManager.setInhibitionOff()
|
||||
} else {
|
||||
footer.playPauseButton.icon.name = "media-playback-pause"
|
||||
lockManager.setInhibitionOn()
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: saveWatchLaterFileTimer
|
||||
|
||||
interval: 1000
|
||||
running: !mpv.pause
|
||||
repeat: true
|
||||
|
||||
onTriggered: handleTimePosition()
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: hideCursorTimer
|
||||
|
||||
property double tx: mouseArea.mouseX
|
||||
property double ty: mouseArea.mouseY
|
||||
property int timeNotMoved: 0
|
||||
|
||||
running: window.isFullScreen() && mouseArea.containsMouse
|
||||
repeat: true
|
||||
interval: 50
|
||||
|
||||
onTriggered: {
|
||||
if (mouseArea.mouseX === tx && mouseArea.mouseY === ty) {
|
||||
if (timeNotMoved > 2000) {
|
||||
app.hideCursor()
|
||||
}
|
||||
} else {
|
||||
app.showCursor()
|
||||
timeNotMoved = 0
|
||||
}
|
||||
tx = mouseArea.mouseX
|
||||
ty = mouseArea.mouseY
|
||||
timeNotMoved += interval
|
||||
}
|
||||
}
|
||||
|
||||
// Window move
|
||||
DragHandler {
|
||||
acceptedDevices: PointerDevice.GenericPointer
|
||||
grabPermissions: PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType | PointerHandler.ApprovesTakeOverByAnything
|
||||
onActiveChanged: if (active) window.helper.startSystemMove(window)
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MiddleButton
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
onPositionChanged: {
|
||||
if (!playList.canToggleWithMouse || playList.playlistView.count <= 1) {
|
||||
return
|
||||
}
|
||||
// if (playList.position === "right") {
|
||||
// if (mouseX > width - 50) {
|
||||
// playList.state = "visible"
|
||||
// }
|
||||
// if (mouseX < width - playList.width - 20) {
|
||||
// playList.state = "hidden"
|
||||
// }
|
||||
// } else {
|
||||
// if (mouseX < 50) {
|
||||
// playList.state = "visible"
|
||||
// }
|
||||
// if (mouseX > playList.width + 20) {
|
||||
// playList.state = "hidden"
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
onWheel: {
|
||||
if (wheel.angleDelta.y > 0) {
|
||||
if (MouseSettings.scrollUp) {
|
||||
actions[MouseSettings.scrollUp].trigger()
|
||||
}
|
||||
} else if (wheel.angleDelta.y) {
|
||||
if (MouseSettings.scrollDown) {
|
||||
actions[MouseSettings.scrollDown].trigger()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onPressed: {
|
||||
focus = true
|
||||
|
||||
// Hide play list
|
||||
playList.state = "hidden"
|
||||
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
if (MouseSettings.left) {
|
||||
actions[MouseSettings.left].trigger()
|
||||
}
|
||||
} else if (mouse.button === Qt.MiddleButton) {
|
||||
if (MouseSettings.middle) {
|
||||
actions[MouseSettings.middle].trigger()
|
||||
}
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
if (MouseSettings.right) {
|
||||
actions[MouseSettings.right].trigger()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onDoubleClicked: {
|
||||
if (mouse.button === Qt.LeftButton) {
|
||||
if (MouseSettings.leftx2) {
|
||||
actions[MouseSettings.leftx2].trigger()
|
||||
}
|
||||
} else if (mouse.button === Qt.MiddleButton) {
|
||||
if (MouseSettings.middlex2) {
|
||||
actions[MouseSettings.middlex2].trigger()
|
||||
}
|
||||
} else if (mouse.button === Qt.RightButton) {
|
||||
if (MouseSettings.rightx2) {
|
||||
actions[MouseSettings.rightx2].trigger()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DropArea {
|
||||
id: dropArea
|
||||
|
||||
property var acceptedSubtitleTypes: ["application/x-subrip", "text/x-ssa"]
|
||||
|
||||
anchors.fill: parent
|
||||
keys: ["text/uri-list"]
|
||||
|
||||
onDropped: {
|
||||
if (acceptedSubtitleTypes.includes(app.mimeType(drop.urls[0]))) {
|
||||
const subFile = drop.urls[0].replace("file://", "")
|
||||
command(["sub-add", drop.urls[0], "select"])
|
||||
}
|
||||
|
||||
if (app.mimeType(drop.urls[0]).startsWith("video/") || app.mimeType(drop.urls[0]).startsWith("audio/")) {
|
||||
window.openFile(drop.urls[0], true, PlaylistSettings.loadSiblings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: mediaPlayer2Player
|
||||
|
||||
function onPlaypause() {
|
||||
actions.playPauseAction.trigger()
|
||||
}
|
||||
|
||||
function onPlay() {
|
||||
root.pause = false
|
||||
}
|
||||
|
||||
function onPause() {
|
||||
root.pause = true
|
||||
}
|
||||
|
||||
function onStop() {
|
||||
root.position = 0
|
||||
root.pause = true
|
||||
}
|
||||
|
||||
function onNext() {
|
||||
actions.playNextAction.trigger()
|
||||
}
|
||||
|
||||
function onPrevious() {
|
||||
actions.playPreviousAction.trigger()
|
||||
}
|
||||
|
||||
function onSeek() {
|
||||
root.command(["add", "time-pos", offset])
|
||||
}
|
||||
|
||||
function onOpenUri() {
|
||||
root.command(["add", "time-pos", offset])
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: loadingIndicatorParent
|
||||
|
||||
visible: false
|
||||
anchors.centerIn: parent
|
||||
color: {
|
||||
let color = FishUI.Theme.backgroundColor
|
||||
Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, 0.2)
|
||||
}
|
||||
|
||||
FishUI.IconItem {
|
||||
id: loadingIndicator
|
||||
|
||||
source: "view-refresh"
|
||||
anchors.centerIn: parent
|
||||
width: FishUI.Units.iconSizes.large
|
||||
height: FishUI.Units.iconSizes.large
|
||||
|
||||
RotationAnimator {
|
||||
target: loadingIndicator;
|
||||
from: 0;
|
||||
to: 360;
|
||||
duration: 1500
|
||||
loops: Animation.Infinite
|
||||
running: true
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
parent.width = width + 10
|
||||
parent.height = height + 10
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
mediaPlayer2Player.mpv = root
|
||||
}
|
||||
|
||||
function handleTimePosition() {
|
||||
if (mpv.position < mpv.duration - 10) {
|
||||
saveTimePosition()
|
||||
} else {
|
||||
resetTimePosition()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
import org.kde.haruna 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property alias label: label
|
||||
|
||||
Label {
|
||||
id: label
|
||||
x: 10
|
||||
y: 10
|
||||
visible: false
|
||||
color: FishUI.Theme.textColor
|
||||
background: Rectangle {
|
||||
color: FishUI.Theme.backgroundColor
|
||||
}
|
||||
padding: 5
|
||||
font.pointSize: parseInt(GeneralSettings.osdFontSize)
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
running: false
|
||||
repeat: false
|
||||
interval: 3000
|
||||
|
||||
onTriggered: {
|
||||
label.visible = false
|
||||
}
|
||||
}
|
||||
|
||||
function message(text) {
|
||||
const osdFontSize = parseInt(GeneralSettings.osdFontSize)
|
||||
label.text = text
|
||||
if (osdFontSize === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(label.visible) {
|
||||
timer.restart()
|
||||
} else {
|
||||
timer.start()
|
||||
}
|
||||
label.visible = true
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,164 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
* SPDX-FileCopyrightText: 2021 Reion Wong <aj@cutefishos.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtGraphicalEffects 1.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
import org.kde.haruna 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property alias scrollPositionTimer: scrollPositionTimer
|
||||
property alias playlistView: playlistView
|
||||
// property bool canToggleWithMouse: PlaylistSettings.canToggleWithMouse
|
||||
property bool canToggleWithMouse: true
|
||||
property string position: PlaylistSettings.position
|
||||
property int rowHeight: PlaylistSettings.rowHeight
|
||||
property int bigFont: PlaylistSettings.bigFontFullscreen
|
||||
property bool isYouTubePlaylist: false
|
||||
|
||||
z: 9999
|
||||
|
||||
height: mpv.height - FishUI.Units.largeSpacing * 6
|
||||
width: {
|
||||
if (PlaylistSettings.style === "compact") {
|
||||
return FishUI.Units.gridUnit * 20
|
||||
} else {
|
||||
const w = FishUI.Units.gridUnit * 30
|
||||
return (parent.width * 0.33) < w ? w : parent.width * 0.33
|
||||
}
|
||||
}
|
||||
x: position === "right" ? parent.width : -width
|
||||
y: FishUI.Units.largeSpacing * 3
|
||||
state: "hidden"
|
||||
|
||||
ScrollView {
|
||||
id: playlistScrollView
|
||||
|
||||
z: 20
|
||||
anchors.fill: parent
|
||||
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
|
||||
|
||||
ListView {
|
||||
id: playlistView
|
||||
model: mpv.playlistModel
|
||||
spacing: 1
|
||||
delegate: PlayListItem {
|
||||
onDoubleClicked: root.state = "hidden"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: scrollPositionTimer
|
||||
interval: 50
|
||||
running: true
|
||||
repeat: true
|
||||
|
||||
onTriggered: {
|
||||
setPlayListScrollPosition()
|
||||
scrollPositionTimer.stop()
|
||||
}
|
||||
}
|
||||
|
||||
ShaderEffectSource {
|
||||
id: shaderEffect
|
||||
|
||||
visible: PlaylistSettings.overlayVideo
|
||||
anchors.fill: playlistScrollView
|
||||
sourceItem: mpv
|
||||
sourceRect: position === "right"
|
||||
? Qt.rect(mpv.width - root.width, mpv.y, root.width, root.height)
|
||||
: Qt.rect(0, 0, root.width, root.height)
|
||||
}
|
||||
|
||||
FastBlur {
|
||||
visible: PlaylistSettings.overlayVideo
|
||||
anchors.fill: shaderEffect
|
||||
radius: 100
|
||||
source: shaderEffect
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: FishUI.Theme.backgroundColor
|
||||
opacity: 0.7
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "hidden"
|
||||
PropertyChanges { target: root; x: position === "right" ? parent.width : -width }
|
||||
PropertyChanges { target: root; visible: false }
|
||||
},
|
||||
State {
|
||||
name : "visible"
|
||||
PropertyChanges { target: root; x: position === "right" ? parent.width - root.width - FishUI.Units.largeSpacing : 0 }
|
||||
PropertyChanges { target: root; visible: true }
|
||||
}
|
||||
]
|
||||
|
||||
transitions: [
|
||||
Transition {
|
||||
from: "visible"
|
||||
to: "hidden"
|
||||
|
||||
SequentialAnimation {
|
||||
NumberAnimation {
|
||||
target: root
|
||||
property: "x"
|
||||
duration: 150
|
||||
easing.type: Easing.InQuad
|
||||
}
|
||||
PropertyAction {
|
||||
target: root
|
||||
property: "visible"
|
||||
value: false
|
||||
}
|
||||
}
|
||||
},
|
||||
Transition {
|
||||
from: "hidden"
|
||||
to: "visible"
|
||||
|
||||
SequentialAnimation {
|
||||
PropertyAction {
|
||||
target: root
|
||||
property: "visible"
|
||||
value: true
|
||||
}
|
||||
NumberAnimation {
|
||||
target: root
|
||||
property: "x"
|
||||
duration: 150
|
||||
easing.type: Easing.OutQuad
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
layer.enabled: true
|
||||
layer.effect: OpacityMask {
|
||||
maskSource: Item {
|
||||
width: root.width
|
||||
height: root.height
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: FishUI.Theme.bigRadius
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setPlayListScrollPosition() {
|
||||
playlistView.positionViewAtIndex(playlistView.model.playingVideo, ListView.Beginning)
|
||||
}
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
import org.kde.haruna 1.0
|
||||
import Haruna.Components 1.0
|
||||
|
||||
SettingsBasePage {
|
||||
id: root
|
||||
|
||||
hasHelp: false
|
||||
helpFile: ""
|
||||
|
||||
GridLayout {
|
||||
id: content
|
||||
|
||||
columns: 2
|
||||
|
||||
Label {
|
||||
text: i18n("Preferred language")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
TextField {
|
||||
text: AudioSettings.preferredLanguage
|
||||
placeholderText: "eng,ger etc."
|
||||
Layout.fillWidth: true
|
||||
onTextEdited: {
|
||||
AudioSettings.preferredLanguage = text
|
||||
AudioSettings.save()
|
||||
mpv.setProperty("alang", text)
|
||||
}
|
||||
|
||||
ToolTip {
|
||||
text: i18n("Do not use spaces.")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Label {
|
||||
text: i18n("Preferred track")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
SpinBox {
|
||||
from: 0
|
||||
to: 100
|
||||
value: AudioSettings.preferredTrack
|
||||
editable: true
|
||||
onValueChanged: {
|
||||
AudioSettings.preferredTrack = value
|
||||
AudioSettings.save()
|
||||
if (value === 0) {
|
||||
mpv.setProperty("aid", "auto")
|
||||
} else {
|
||||
mpv.setProperty("aid", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: FishUI.Units.gridUnit
|
||||
height: FishUI.Units.gridUnit
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import org.kde.kirigami 2.11 as Kirigami
|
||||
import org.kde.haruna 1.0
|
||||
import Haruna.Components 1.0
|
||||
|
||||
SettingsBasePage {
|
||||
id: root
|
||||
|
||||
hasHelp: true
|
||||
helpFile: ":/CustomCommandsSettings.html"
|
||||
docPage: "help:/haruna/CustomCommandsSettings.html"
|
||||
|
||||
Component {
|
||||
id: customCommandDelegate
|
||||
|
||||
Kirigami.AbstractListItem {
|
||||
id: customCommandItem
|
||||
|
||||
height: Kirigami.Units.gridUnit * 3
|
||||
padding: 0
|
||||
|
||||
contentItem: RowLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
Kirigami.ListItemDragHandle {
|
||||
listItem: customCommandItem
|
||||
listView: customCommandsView
|
||||
onMoveRequested: customCommandsModel.moveRows(oldIndex, newIndex)
|
||||
}
|
||||
|
||||
Kirigami.Icon {
|
||||
source: model.type === "shortcut" ? "configure-shortcuts" : "code-context"
|
||||
width: Kirigami.Units.iconSizes.small
|
||||
height: Kirigami.Units.iconSizes.small
|
||||
}
|
||||
|
||||
LabelWithTooltip {
|
||||
text: model.command
|
||||
elide: Text.ElideRight
|
||||
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
|
||||
Layout.fillWidth: true
|
||||
Layout.margins: Kirigami.Units.largeSpacing
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
text: i18n("Shortcut")
|
||||
icon.name: "configure-shortcuts"
|
||||
visible: model.type === "shortcut"
|
||||
onClicked: app.configureShortcuts(model.command)
|
||||
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
icon.name: "edit-entry"
|
||||
Layout.rightMargin: Kirigami.Units.largeSpacing
|
||||
onClicked: applicationWindow().pageStack.replace("qrc:/EditCustomCommand.qml",
|
||||
{
|
||||
command: model.command,
|
||||
osdMessage: model.osdMessage,
|
||||
type: model.type,
|
||||
commandId: model.commandId,
|
||||
index: model.index,
|
||||
mode: EditCustomCommand.Mode.Edit
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: customCommandsView
|
||||
|
||||
model: customCommandsModel
|
||||
delegate: Kirigami.DelegateRecycler {
|
||||
width: customCommandsView.width
|
||||
sourceComponent: customCommandDelegate
|
||||
}
|
||||
}
|
||||
|
||||
footer: ToolBar {
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
ToolButton {
|
||||
id: addButton
|
||||
|
||||
text: i18n("&Add")
|
||||
icon.name: "list-add"
|
||||
onClicked: applicationWindow().pageStack.replace("qrc:/EditCustomCommand.qml")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,168 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
import org.kde.haruna 1.0
|
||||
import Haruna.Components 1.0
|
||||
|
||||
SettingsBasePage {
|
||||
id: root
|
||||
|
||||
property string command: ""
|
||||
property string osdMessage: ""
|
||||
property string type: "shortcut"
|
||||
property string commandId: ""
|
||||
property int index: -1
|
||||
property int mode: EditCustomCommand.Mode.Create
|
||||
|
||||
enum Mode {
|
||||
Create = 0,
|
||||
Edit
|
||||
}
|
||||
|
||||
hasHelp: true
|
||||
helpFile: ":/CustomCommandsSettings.html"
|
||||
|
||||
Action {
|
||||
shortcut: "esc"
|
||||
onTriggered: applicationWindow().pageStack.replace("qrc:/CustomCommands.qml")
|
||||
}
|
||||
|
||||
GridLayout {
|
||||
columns: 2
|
||||
|
||||
Label {
|
||||
text: i18n("Command")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: commandTextField
|
||||
|
||||
text: root.command
|
||||
placeholderText: "add volume +10"
|
||||
Layout.fillWidth: true
|
||||
Component.onCompleted: forceActiveFocus()
|
||||
}
|
||||
|
||||
Label {
|
||||
text: i18n("OSD Message")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: osdMessageTextField
|
||||
|
||||
text: root.osdMessage
|
||||
enabled: typeGroup.checkedButton.optionName === "shortcut"
|
||||
placeholderText: "Filename: ${filename}"
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Label {
|
||||
text: i18n("Type")
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignTop
|
||||
}
|
||||
|
||||
ButtonGroup {
|
||||
id: typeGroup
|
||||
|
||||
buttons: typeGroupItems.children
|
||||
}
|
||||
|
||||
Column {
|
||||
id: typeGroupItems
|
||||
|
||||
spacing: FishUI.Units.largeSpacing
|
||||
|
||||
RadioButton {
|
||||
property string optionName: "shortcut"
|
||||
|
||||
checked: optionName === root.type
|
||||
text: i18n("Keyboard shortcut")
|
||||
}
|
||||
|
||||
RadioButton {
|
||||
property string optionName: "startup"
|
||||
|
||||
checked: optionName === root.type
|
||||
text: i18n("Run at startup")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer: ToolBar {
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
ToolButton {
|
||||
text: i18n("Delete")
|
||||
icon.name: "delete"
|
||||
visible: root.mode === EditCustomCommand.Mode.Edit
|
||||
onClicked: {
|
||||
customCommandsModel.deleteCustomCommand(root.commandId, root.index)
|
||||
applicationWindow().pageStack.replace("qrc:/CustomCommands.qml")
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
text: i18n("Cancel")
|
||||
icon.name: "dialog-cancel"
|
||||
onClicked: applicationWindow().pageStack.replace("qrc:/CustomCommands.qml")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
text: i18n("&Save")
|
||||
icon.name: "document-save"
|
||||
enabled: commandTextField.text !== ""
|
||||
onClicked: saveCustomCommand()
|
||||
|
||||
Layout.alignment: Qt.AlignRight
|
||||
|
||||
function saveCustomCommand() {
|
||||
if (commandTextField.text === "") {
|
||||
return
|
||||
}
|
||||
if (typeGroup.checkedButton.optionName === "shortcut") {
|
||||
// creates action and adds it to the action collection
|
||||
// so that its shortcut can be set by the user
|
||||
app.createUserAction(commandTextField.text)
|
||||
} else {
|
||||
// execute the user command
|
||||
mpv.userCommand(commandTextField.text)
|
||||
}
|
||||
switch (root.mode) {
|
||||
case EditCustomCommand.Mode.Create:
|
||||
// save new command to config file
|
||||
customCommandsModel.saveCustomCommand(commandTextField.text,
|
||||
osdMessageTextField.text,
|
||||
typeGroup.checkedButton.optionName)
|
||||
break
|
||||
case EditCustomCommand.Mode.Edit:
|
||||
// update existing command
|
||||
customCommandsModel.editCustomCommand(root.index,
|
||||
commandTextField.text,
|
||||
osdMessageTextField.text,
|
||||
typeGroup.checkedButton.optionName)
|
||||
break
|
||||
}
|
||||
applicationWindow().pageStack.replace("qrc:/CustomCommands.qml")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,336 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import org.kde.kirigami 2.11 as Kirigami
|
||||
import org.kde.haruna 1.0
|
||||
|
||||
import Haruna.Components 1.0
|
||||
|
||||
SettingsBasePage {
|
||||
id: root
|
||||
|
||||
hasHelp: true
|
||||
helpFile: ":/GeneralSettings.html"
|
||||
docPage: "help:/haruna/GeneralSettings.html"
|
||||
|
||||
GridLayout {
|
||||
id: content
|
||||
|
||||
columns: 2
|
||||
|
||||
// OSD Font Size
|
||||
Label {
|
||||
text: qsTr("Osd font size")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
Item {
|
||||
height: osdFontSize.height
|
||||
SpinBox {
|
||||
id: osdFontSize
|
||||
|
||||
// used to prevent osd showing when opening the page
|
||||
property bool completed: false
|
||||
|
||||
editable: true
|
||||
from: 0
|
||||
to: 100
|
||||
value: GeneralSettings.osdFontSize
|
||||
onValueChanged: {
|
||||
if (completed) {
|
||||
osd.label.font.pointSize = osdFontSize.value
|
||||
osd.message("Test osd font size")
|
||||
GeneralSettings.osdFontSize = osdFontSize.value
|
||||
GeneralSettings.save()
|
||||
}
|
||||
}
|
||||
Component.onCompleted: completed = true
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// Volume Step
|
||||
Label {
|
||||
text: qsTr("Volume step")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
Item {
|
||||
height: volumeStep.height
|
||||
SpinBox {
|
||||
id: volumeStep
|
||||
editable: true
|
||||
from: 0
|
||||
to: 100
|
||||
value: GeneralSettings.volumeStep
|
||||
onValueChanged: {
|
||||
if (root.visible) {
|
||||
GeneralSettings.volumeStep = volumeStep.value
|
||||
GeneralSettings.save()
|
||||
}
|
||||
}
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// Seek Small Step
|
||||
Label {
|
||||
text: qsTr("Seek small step")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
Item {
|
||||
height: seekSmallStep.height
|
||||
SpinBox {
|
||||
id: seekSmallStep
|
||||
editable: true
|
||||
from: 0
|
||||
to: 100
|
||||
value: GeneralSettings.seekSmallStep
|
||||
onValueChanged: {
|
||||
GeneralSettings.seekSmallStep = seekSmallStep.value
|
||||
GeneralSettings.save()
|
||||
}
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// Seek Medium Step
|
||||
Label {
|
||||
text: qsTr("Seek medium step")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
Item {
|
||||
height: seekMediumStep.height
|
||||
RowLayout {
|
||||
|
||||
SpinBox {
|
||||
id: seekMediumStep
|
||||
editable: true
|
||||
from: 0
|
||||
to: 100
|
||||
value: GeneralSettings.seekMediumStep
|
||||
onValueChanged: {
|
||||
GeneralSettings.seekMediumStep = seekMediumStep.value
|
||||
GeneralSettings.save()
|
||||
}
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
icon.name: "documentinfo"
|
||||
checkable: true
|
||||
checked: false
|
||||
|
||||
ToolTip {
|
||||
text: qsTr("This is also used for mouse wheel seeking, when mouse is over the progress bar")
|
||||
visible: parent.checked
|
||||
delay: 0
|
||||
timeout: -1
|
||||
closePolicy: Popup.NoAutoClose
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// Seek Big Step
|
||||
Label {
|
||||
text: qsTr("Seek big step")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
Item {
|
||||
height: seekBigStep.height
|
||||
SpinBox {
|
||||
id: seekBigStep
|
||||
editable: true
|
||||
from: 0
|
||||
to: 100
|
||||
value: GeneralSettings.seekBigStep
|
||||
onValueChanged: {
|
||||
GeneralSettings.seekBigStep = seekBigStep.value
|
||||
GeneralSettings.save()
|
||||
}
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("File dialog location")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
Item {
|
||||
height: fileDialogLocation.height
|
||||
Layout.fillWidth: true
|
||||
|
||||
TextField {
|
||||
id: fileDialogLocation
|
||||
|
||||
text: GeneralSettings.fileDialogLocation
|
||||
onEditingFinished: {
|
||||
GeneralSettings.fileDialogLocation = fileDialogLocation.text
|
||||
GeneralSettings.save()
|
||||
}
|
||||
|
||||
ToolTip {
|
||||
text: qsTr("If empty the file dialog will remember the last opened location.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SettingsHeader {
|
||||
text: qsTr("Interface")
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
text: qsTr("Show MenuBar")
|
||||
checked: GeneralSettings.showMenuBar
|
||||
onCheckedChanged: {
|
||||
GeneralSettings.showMenuBar = checked
|
||||
GeneralSettings.save()
|
||||
}
|
||||
Layout.row: 8
|
||||
Layout.column: 1
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
text: qsTr("Show Header")
|
||||
checked: GeneralSettings.showHeader
|
||||
onCheckedChanged: {
|
||||
GeneralSettings.showHeader = checked
|
||||
GeneralSettings.save()
|
||||
}
|
||||
Layout.row: 9
|
||||
Layout.column: 1
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
text: qsTr("Show chapter markers")
|
||||
checked: GeneralSettings.showChapterMarkers
|
||||
onCheckedChanged: {
|
||||
GeneralSettings.showChapterMarkers = checked
|
||||
GeneralSettings.save()
|
||||
}
|
||||
Layout.row: 10
|
||||
Layout.column: 1
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Color scheme")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: colorThemeSwitcher
|
||||
|
||||
textRole: "display"
|
||||
model: app.colorSchemesModel
|
||||
delegate: ItemDelegate {
|
||||
Kirigami.Theme.colorSet: Kirigami.Theme.View
|
||||
width: colorThemeSwitcher.width
|
||||
highlighted: model.display === GeneralSettings.colorScheme
|
||||
contentItem: RowLayout {
|
||||
Kirigami.Icon {
|
||||
source: model.decoration
|
||||
Layout.preferredHeight: Kirigami.Units.iconSizes.small
|
||||
Layout.preferredWidth: Kirigami.Units.iconSizes.small
|
||||
}
|
||||
Label {
|
||||
text: model.display
|
||||
color: highlighted ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onActivated: {
|
||||
GeneralSettings.colorScheme = colorThemeSwitcher.textAt(index)
|
||||
GeneralSettings.save()
|
||||
app.activateColorScheme(GeneralSettings.colorScheme)
|
||||
}
|
||||
|
||||
Component.onCompleted: currentIndex = find(GeneralSettings.colorScheme)
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("GUI Style")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: guiStyleComboBox
|
||||
|
||||
textRole: "key"
|
||||
model: ListModel {
|
||||
id: stylesModel
|
||||
|
||||
ListElement { key: "Default"; }
|
||||
}
|
||||
|
||||
onActivated: {
|
||||
GeneralSettings.guiStyle = model.get(index).key
|
||||
app.setGuiStyle(GeneralSettings.guiStyle)
|
||||
// some themes can cause a crash
|
||||
// the timer prevents saving the crashing theme,
|
||||
// which would cause the app to crash on startup
|
||||
saveGuiStyleTimer.start()
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: saveGuiStyleTimer
|
||||
|
||||
interval: 1000
|
||||
running: false
|
||||
repeat: false
|
||||
onTriggered: GeneralSettings.save()
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
// populate the model with the available styles
|
||||
for (let i = 0; i < app.availableGuiStyles().length; ++i) {
|
||||
stylesModel.append({key: app.availableGuiStyles()[i]})
|
||||
}
|
||||
|
||||
// set the saved style as the current item in the combo box
|
||||
for (let j = 0; j < stylesModel.count; ++j) {
|
||||
if (stylesModel.get(j).key === GeneralSettings.guiStyle) {
|
||||
currentIndex = j
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
text: qsTr("Use Breeze icon theme")
|
||||
checked: GeneralSettings.useBreezeIconTheme
|
||||
onCheckedChanged: {
|
||||
GeneralSettings.useBreezeIconTheme = checked
|
||||
GeneralSettings.save()
|
||||
}
|
||||
Layout.row: 14
|
||||
Layout.column: 1
|
||||
|
||||
ToolTip {
|
||||
text: qsTr("Sets the icon theme to breeze.\nRequires restart.")
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: Kirigami.Units.gridUnit
|
||||
height: Kirigami.Units.gridUnit
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,111 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQml 2.12
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import org.kde.kirigami 2.11 as Kirigami
|
||||
import org.kde.haruna 1.0
|
||||
import Haruna.Components 1.0
|
||||
|
||||
SettingsBasePage {
|
||||
id: root
|
||||
|
||||
hasHelp: false
|
||||
helpFile: ""
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
|
||||
spacing: Kirigami.Units.largeSpacing
|
||||
|
||||
ListModel {
|
||||
id: mouseActionsModel
|
||||
|
||||
ListElement {
|
||||
label: "Left"
|
||||
key: "left"
|
||||
}
|
||||
ListElement {
|
||||
label: "Left double click"
|
||||
key: "leftx2"
|
||||
}
|
||||
ListElement {
|
||||
label: "Right"
|
||||
key: "right"
|
||||
}
|
||||
ListElement {
|
||||
label: "Right double click"
|
||||
key: "rightx2"
|
||||
}
|
||||
ListElement {
|
||||
label: "Middle"
|
||||
key: "middle"
|
||||
}
|
||||
ListElement {
|
||||
label: "Middle double click"
|
||||
key: "middlex2"
|
||||
}
|
||||
ListElement {
|
||||
label: "ScrollUp"
|
||||
key: "scrollUp"
|
||||
}
|
||||
ListElement {
|
||||
label: "ScrollDown"
|
||||
key: "scrollDown"
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: mouseButtonsListView
|
||||
|
||||
property int delegateHeight
|
||||
|
||||
implicitHeight: delegateHeight * (mouseButtonsListView.count + 1)
|
||||
model: mouseActionsModel
|
||||
|
||||
delegate: Kirigami.BasicListItem {
|
||||
id: delegate
|
||||
|
||||
label: model.label
|
||||
subtitle: MouseSettings[model.key] ? MouseSettings[model.key] : "No action set"
|
||||
icon: MouseSettings[model.key] ? "checkmark" : ""
|
||||
reserveSpaceForIcon: true
|
||||
width: content.width
|
||||
highlighted: false
|
||||
|
||||
onClicked: openSelectActionPopup()
|
||||
Component.onCompleted: mouseButtonsListView.delegateHeight = height
|
||||
|
||||
Connections {
|
||||
target: selectActionPopup
|
||||
onActionSelected: {
|
||||
if (selectActionPopup.buttonIndex === model.index) {
|
||||
MouseSettings[model.key] = actionName
|
||||
MouseSettings.save()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function openSelectActionPopup() {
|
||||
selectActionPopup.buttonIndex = model.index
|
||||
selectActionPopup.headerTitle = model.label
|
||||
selectActionPopup.open()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Item {
|
||||
width: Kirigami.Units.gridUnit
|
||||
height: Kirigami.Units.gridUnit
|
||||
}
|
||||
|
||||
SelectActionPopup { id: selectActionPopup }
|
||||
}
|
||||
}
|
||||
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
import org.kde.kirigami 2.11 as Kirigami
|
||||
|
||||
Kirigami.Page
|
||||
{
|
||||
padding: 0
|
||||
leftPadding: 0
|
||||
topPadding: 0
|
||||
rightPadding: 0
|
||||
bottomPadding: 0
|
||||
|
||||
Component.onCompleted: applicationWindow().pageStack.columnView.columnWidth = 250
|
||||
|
||||
|
||||
footer: ToolBar {
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
ToolButton {
|
||||
text: qsTr("Configure shortcuts")
|
||||
icon.name: "configure-shortcuts"
|
||||
onClicked: appActions.configureShortcutsAction.trigger()
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: settingsPagesModel
|
||||
ListElement {
|
||||
name: "General"
|
||||
iconName: "configure"
|
||||
page: "qrc:/General.qml"
|
||||
}
|
||||
ListElement {
|
||||
name: "Playback"
|
||||
iconName: "media-playback-start"
|
||||
page: "qrc:/Playback.qml"
|
||||
}
|
||||
ListElement {
|
||||
name: "Video"
|
||||
iconName: "video-x-generic"
|
||||
page: "qrc:/VideoSettings.qml"
|
||||
}
|
||||
ListElement {
|
||||
name: "Audio"
|
||||
iconName: "player-volume"
|
||||
page: "qrc:/Audio.qml"
|
||||
}
|
||||
ListElement {
|
||||
name: "Subtitles"
|
||||
iconName: "add-subtitle"
|
||||
page: "qrc:/Subtitles.qml"
|
||||
}
|
||||
ListElement {
|
||||
name: "Playlist"
|
||||
iconName: "view-media-playlist"
|
||||
page: "qrc:/Playlist.qml"
|
||||
}
|
||||
ListElement {
|
||||
name: "Mouse"
|
||||
iconName: "input-mouse"
|
||||
page: "qrc:/Mouse.qml"
|
||||
}
|
||||
ListElement {
|
||||
name: "Custom commands"
|
||||
iconName: "configure"
|
||||
page: "qrc:/CustomCommands.qml"
|
||||
}
|
||||
}
|
||||
|
||||
ListView {
|
||||
id: settingsPagesList
|
||||
|
||||
anchors.fill: parent
|
||||
model: settingsPagesModel
|
||||
delegate: Kirigami.BasicListItem {
|
||||
text: qsTr(name)
|
||||
icon: iconName
|
||||
onClicked: applicationWindow().pageStack.push(model.page)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,281 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
import org.kde.haruna 1.0
|
||||
import Haruna.Components 1.0
|
||||
|
||||
SettingsBasePage {
|
||||
id: root
|
||||
|
||||
hasHelp: true
|
||||
helpFile: ":/PlaybackSettings.html"
|
||||
docPage: "help:/haruna/PlaybackSettings.html"
|
||||
|
||||
GridLayout {
|
||||
id: content
|
||||
|
||||
columns: 2
|
||||
|
||||
CheckBox {
|
||||
id: hwDecodingCheckBox
|
||||
text: i18n("Use hardware decoding")
|
||||
checked: PlaybackSettings.useHWDecoding
|
||||
onCheckedChanged: {
|
||||
mpv.hwDecoding = checked
|
||||
PlaybackSettings.useHWDecoding = checked
|
||||
PlaybackSettings.save()
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: hwDecodingComboBox
|
||||
|
||||
enabled: hwDecodingCheckBox.checked
|
||||
textRole: "key"
|
||||
model: ListModel {
|
||||
id: hwDecModel
|
||||
ListElement { key: "auto"; }
|
||||
ListElement { key: "auto-safe"; }
|
||||
ListElement { key: "auto-copy"; }
|
||||
ListElement { key: "vdpau"; }
|
||||
ListElement { key: "vdpau-copy"; }
|
||||
ListElement { key: "vaapi"; }
|
||||
ListElement { key: "vaapi-copy"; }
|
||||
ListElement { key: "videotoolbox"; }
|
||||
ListElement { key: "videotoolbox-copy"; }
|
||||
ListElement { key: "dxva2"; }
|
||||
ListElement { key: "dxva2-copy"; }
|
||||
ListElement { key: "d3d11va"; }
|
||||
ListElement { key: "d3d11va-copy"; }
|
||||
ListElement { key: "mediacodec"; }
|
||||
ListElement { key: "mediacodec-copy"; }
|
||||
ListElement { key: "mmal"; }
|
||||
ListElement { key: "mmal-copy"; }
|
||||
ListElement { key: "nvdec"; }
|
||||
ListElement { key: "nvdec-copy"; }
|
||||
ListElement { key: "cuda"; }
|
||||
ListElement { key: "cuda-copy"; }
|
||||
ListElement { key: "crystalhd"; }
|
||||
ListElement { key: "rkmpp"; }
|
||||
}
|
||||
|
||||
onActivated: {
|
||||
PlaybackSettings.hWDecoding = model.get(index).key
|
||||
PlaybackSettings.save()
|
||||
mpv.setProperty("hwdec", PlaybackSettings.hWDecoding)
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
for (let i = 0; i < hwDecModel.count; ++i) {
|
||||
if (hwDecModel.get(i).key === PlaybackSettings.hWDecoding) {
|
||||
currentIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: i18n("Remember time position")
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
SpinBox {
|
||||
id: timePositionSaving
|
||||
from: -1
|
||||
to: 9999
|
||||
value: PlaybackSettings.minDurationToSavePosition
|
||||
|
||||
onValueChanged: {
|
||||
PlaybackSettings.minDurationToSavePosition = value
|
||||
PlaybackSettings.save()
|
||||
}
|
||||
}
|
||||
|
||||
LabelWithTooltip {
|
||||
text: {
|
||||
if (timePositionSaving.value === -1) {
|
||||
return i18n("Disabled")
|
||||
} else if (timePositionSaving.value === 0) {
|
||||
return i18n("For all files")
|
||||
} else if (timePositionSaving.value === 1) {
|
||||
return i18n("For files longer than %1 minute").arg(timePositionSaving.value)
|
||||
} else {
|
||||
return i18n("For files longer than %1 minutes").arg(timePositionSaving.value)
|
||||
}
|
||||
}
|
||||
elide: Text.ElideRight
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
id: skipChaptersCheckBox
|
||||
text: i18n("Skip chapters")
|
||||
checked: PlaybackSettings.skipChapters
|
||||
onCheckedChanged: {
|
||||
PlaybackSettings.skipChapters = checked
|
||||
PlaybackSettings.save()
|
||||
}
|
||||
Layout.columnSpan: 2
|
||||
}
|
||||
|
||||
Label {
|
||||
text: i18n("Skip chapters containing the following words")
|
||||
enabled: skipChaptersCheckBox.checked
|
||||
Layout.columnSpan: 2
|
||||
}
|
||||
|
||||
TextField {
|
||||
text: PlaybackSettings.chaptersToSkip
|
||||
placeholderText: "op, ed, chapter 1"
|
||||
enabled: skipChaptersCheckBox.checked
|
||||
Layout.fillWidth: true
|
||||
onEditingFinished: {
|
||||
PlaybackSettings.chaptersToSkip = text
|
||||
PlaybackSettings.save()
|
||||
}
|
||||
Layout.columnSpan: 2
|
||||
|
||||
ToolTip {
|
||||
text: i18n("Separate words with a comma")
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
text: i18n("Show an osd message when skipping chapters")
|
||||
enabled: skipChaptersCheckBox.checked
|
||||
checked: PlaybackSettings.showOsdOnSkipChapters
|
||||
onCheckedChanged: {
|
||||
PlaybackSettings.showOsdOnSkipChapters = checked
|
||||
PlaybackSettings.save()
|
||||
}
|
||||
Layout.columnSpan: 2
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
// Youtube-dl format settings
|
||||
// ------------------------------------
|
||||
|
||||
SettingsHeader {
|
||||
text: i18n("Youtube-dl")
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Label {
|
||||
text: i18n("Format selection")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
Item {
|
||||
height: ytdlFormatComboBox.height
|
||||
ComboBox {
|
||||
id: ytdlFormatComboBox
|
||||
property string hCurrentvalue: ""
|
||||
textRole: "key"
|
||||
model: ListModel {
|
||||
id: leftButtonModel
|
||||
ListElement { key: "Custom"; value: "" }
|
||||
ListElement { key: "2160"; value: "bestvideo[height<=2160]+bestaudio/best" }
|
||||
ListElement { key: "1440"; value: "bestvideo[height<=1440]+bestaudio/best" }
|
||||
ListElement { key: "1080"; value: "bestvideo[height<=1080]+bestaudio/best" }
|
||||
ListElement { key: "720"; value: "bestvideo[height<=720]+bestaudio/best" }
|
||||
ListElement { key: "480"; value: "bestvideo[height<=480]+bestaudio/best" }
|
||||
}
|
||||
ToolTip {
|
||||
text: i18n("Selects the best video with a height lower than or equal to the selected value.")
|
||||
}
|
||||
|
||||
onActivated: {
|
||||
hCurrentvalue = model.get(index).value
|
||||
if (index === 0) {
|
||||
ytdlFormatField.text = PlaybackSettings.ytdlFormat
|
||||
}
|
||||
if(index > 0) {
|
||||
ytdlFormatField.focus = true
|
||||
ytdlFormatField.text = model.get(index).value
|
||||
}
|
||||
PlaybackSettings.ytdlFormat = ytdlFormatField.text
|
||||
PlaybackSettings.save()
|
||||
mpv.setProperty("ytdl-format", PlaybackSettings.ytdlFormat)
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
let i = hIndexOfValue(PlaybackSettings.ytdlFormat)
|
||||
currentIndex = (i === -1) ? 0 : i
|
||||
}
|
||||
|
||||
function hIndexOfValue(value) {
|
||||
if (value === "bestvideo[height<=2160]+bestaudio/best") {
|
||||
return 1
|
||||
}
|
||||
if (value === "bestvideo[height<=1440]+bestaudio/best") {
|
||||
return 2
|
||||
}
|
||||
if (value === "bestvideo[height<=1080]+bestaudio/best") {
|
||||
return 3
|
||||
}
|
||||
if (value === "bestvideo[height<=720]+bestaudio/best") {
|
||||
return 4
|
||||
}
|
||||
if (value === "bestvideo[height<=480]+bestaudio/best") {
|
||||
return 5
|
||||
}
|
||||
return 0
|
||||
}
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: ytdlFormatField
|
||||
text: PlaybackSettings.ytdlFormat
|
||||
onEditingFinished: {
|
||||
PlaybackSettings.ytdlFormat = text
|
||||
PlaybackSettings.save()
|
||||
}
|
||||
placeholderText: i18n("bestvideo+bestaudio/best")
|
||||
|
||||
onTextChanged: {
|
||||
if (ytdlFormatComboBox.hCurrentvalue !== ytdlFormatField.text) {
|
||||
ytdlFormatComboBox.currentIndex = 0
|
||||
return;
|
||||
}
|
||||
if (ytdlFormatComboBox.hIndexOfValue(ytdlFormatField.text) !== -1) {
|
||||
ytdlFormatComboBox.currentIndex = ytdlFormatComboBox.hIndexOfValue(ytdlFormatField.text)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.columnSpan: 2
|
||||
}
|
||||
TextEdit {
|
||||
text: i18n("Leave empty for default value: <i>bestvideo+bestaudio/best</i>")
|
||||
color: FishUI.Theme.textColor
|
||||
readOnly: true
|
||||
wrapMode: Text.WordWrap
|
||||
textFormat: TextEdit.RichText
|
||||
selectByMouse: true
|
||||
Layout.fillWidth: true
|
||||
Layout.columnSpan: 2
|
||||
}
|
||||
// ------------------------------------
|
||||
// END - Youtube-dl format settings
|
||||
// ------------------------------------
|
||||
|
||||
Item {
|
||||
width: FishUI.Units.gridUnit
|
||||
height: FishUI.Units.gridUnit
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,179 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
import org.kde.haruna 1.0
|
||||
import Haruna.Components 1.0
|
||||
|
||||
SettingsBasePage {
|
||||
id: root
|
||||
|
||||
hasHelp: false
|
||||
helpFile: ""
|
||||
|
||||
GridLayout {
|
||||
id: content
|
||||
|
||||
columns: 2
|
||||
|
||||
Label {
|
||||
text: i18n("Position")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
textRole: "key"
|
||||
model: ListModel {
|
||||
ListElement { key: "Left"; value: "left" }
|
||||
ListElement { key: "Right"; value: "right" }
|
||||
}
|
||||
Component.onCompleted: {
|
||||
for (let i = 0; i < model.count; ++i) {
|
||||
if (model.get(i).value === PlaylistSettings.position) {
|
||||
currentIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
onActivated: {
|
||||
PlaylistSettings.position = model.get(index).value
|
||||
PlaylistSettings.save()
|
||||
playList.position = model.get(index).value
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: i18n("Row height")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
SpinBox {
|
||||
from: 0
|
||||
to: 100
|
||||
value: PlaylistSettings.rowHeight
|
||||
enabled: PlaylistSettings.style === "compact" ? false : true
|
||||
onValueChanged: {
|
||||
PlaylistSettings.rowHeight = value
|
||||
PlaylistSettings.save()
|
||||
playList.rowHeight = value
|
||||
playList.playlistView.forceLayout()
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: i18n("Playlist style")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
textRole: "display"
|
||||
model: ListModel {
|
||||
ListElement { display: "Default"; value: "default" }
|
||||
ListElement { display: "WithThumbnails"; value: "withThumbnails" }
|
||||
ListElement { display: "Compact"; value: "compact" }
|
||||
}
|
||||
Component.onCompleted: {
|
||||
for (let i = 0; i < model.count; ++i) {
|
||||
if (model.get(i).value === PlaylistSettings.style) {
|
||||
currentIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
onActivated: {
|
||||
PlaylistSettings.style = model.get(index).value
|
||||
PlaylistSettings.save()
|
||||
}
|
||||
}
|
||||
|
||||
Item { width: 1; height: 1 }
|
||||
CheckBox {
|
||||
checked: PlaylistSettings.overlayVideo
|
||||
text: i18n("Overlay video")
|
||||
onCheckStateChanged: {
|
||||
PlaylistSettings.overlayVideo = checked
|
||||
PlaylistSettings.save()
|
||||
}
|
||||
|
||||
ToolTip {
|
||||
text: i18n("When checked the playlist goes on top of the video\nWhen unchecked the video is resized")
|
||||
}
|
||||
}
|
||||
|
||||
Item { width: 1; height: 1 }
|
||||
CheckBox {
|
||||
checked: PlaylistSettings.showMediaTitle
|
||||
text: i18n("Show media title instead of file name")
|
||||
onCheckStateChanged: {
|
||||
PlaylistSettings.showMediaTitle = checked
|
||||
PlaylistSettings.save()
|
||||
}
|
||||
}
|
||||
|
||||
Item { width: 1; height: 1 }
|
||||
CheckBox {
|
||||
checked: PlaylistSettings.loadSiblings
|
||||
text: i18n("Auto load videos from same folder")
|
||||
onCheckStateChanged: {
|
||||
PlaylistSettings.loadSiblings = checked
|
||||
PlaylistSettings.save()
|
||||
}
|
||||
}
|
||||
|
||||
Item { width: 1; height: 1 }
|
||||
CheckBox {
|
||||
checked: PlaylistSettings.repeat
|
||||
text: i18n("Repeat")
|
||||
onCheckStateChanged: {
|
||||
PlaylistSettings.repeat = checked
|
||||
PlaylistSettings.save()
|
||||
}
|
||||
}
|
||||
|
||||
Item { width: 1; height: 1 }
|
||||
CheckBox {
|
||||
checked: PlaylistSettings.showRowNumber
|
||||
text: i18n("Show row number")
|
||||
onCheckStateChanged: {
|
||||
PlaylistSettings.showRowNumber = checked
|
||||
PlaylistSettings.save()
|
||||
}
|
||||
}
|
||||
|
||||
Item { width: 1; height: 1 }
|
||||
CheckBox {
|
||||
checked: PlaylistSettings.canToggleWithMouse
|
||||
text: i18n("Toggle with mouse")
|
||||
onCheckStateChanged: {
|
||||
PlaylistSettings.canToggleWithMouse = checked
|
||||
PlaylistSettings.save()
|
||||
playList.canToggleWithMouse = checked
|
||||
}
|
||||
}
|
||||
|
||||
Item { width: 1; height: 1 }
|
||||
CheckBox {
|
||||
text: i18n("Increase font size when fullscreen")
|
||||
checked: PlaylistSettings.bigFontFullscreen
|
||||
enabled: PlaylistSettings.style === "compact" ? false : true
|
||||
onCheckStateChanged: {
|
||||
PlaylistSettings.bigFontFullscreen = checked
|
||||
PlaylistSettings.save()
|
||||
playList.bigFont = checked
|
||||
playList.playlistView.forceLayout()
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: FishUI.Units.gridUnit
|
||||
height: FishUI.Units.gridUnit
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.10
|
||||
import QtQuick.Window 2.1
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtGraphicalEffects 1.12
|
||||
|
||||
import org.kde.kirigami 2.11 as Kirigami
|
||||
import org.kde.haruna 1.0 as Haruna
|
||||
|
||||
Kirigami.ApplicationWindow {
|
||||
id: root
|
||||
|
||||
width: 800
|
||||
height: 600
|
||||
title: qsTr("Haruna Settings")
|
||||
visible: false
|
||||
pageStack.initialPage: "qrc:/Navigation.qml"
|
||||
|
||||
Component.onCompleted: pageStack.push("qrc:/General.qml")
|
||||
|
||||
Window {
|
||||
id: helpWindow
|
||||
|
||||
width: 700
|
||||
height: 600
|
||||
title: qsTr("Help")
|
||||
color: Kirigami.Theme.backgroundColor
|
||||
onVisibleChanged: info.text = app.getFileContent(applicationWindow().pageStack.currentItem.helpFile)
|
||||
|
||||
Flickable {
|
||||
id: scrollView
|
||||
|
||||
property int scrollStepSize: 100
|
||||
|
||||
anchors.fill: parent
|
||||
contentHeight: info.height
|
||||
|
||||
ScrollBar.vertical: ScrollBar {
|
||||
id: scrollbar
|
||||
policy: ScrollBar.AlwaysOn
|
||||
stepSize: scrollView.scrollStepSize/scrollView.contentHeight
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onWheel: {
|
||||
if (wheel.angleDelta.y > 0) {
|
||||
scrollbar.decrease()
|
||||
} else {
|
||||
scrollbar.increase()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextArea {
|
||||
id: info
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
border.color: "transparent"
|
||||
}
|
||||
width: parent.width
|
||||
color: Kirigami.Theme.textColor
|
||||
readOnly: true
|
||||
textFormat: Text.RichText
|
||||
wrapMode: Text.WordWrap
|
||||
selectByMouse: true
|
||||
rightPadding: scrollbar.width
|
||||
onLinkActivated: Qt.openUrlExternally(link)
|
||||
onHoveredLinkChanged: hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
import org.kde.haruna 1.0
|
||||
import Haruna.Components 1.0
|
||||
|
||||
SettingsBasePage {
|
||||
id: root
|
||||
|
||||
hasHelp: false
|
||||
helpFile: ""
|
||||
|
||||
GridLayout {
|
||||
id: content
|
||||
|
||||
columns: 2
|
||||
|
||||
SubtitlesFolders {
|
||||
id: subtitleFolders
|
||||
implicitWidth: root.width
|
||||
Layout.fillWidth: true
|
||||
Layout.columnSpan: 2
|
||||
}
|
||||
|
||||
Label {
|
||||
text: i18n("Preferred language")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
TextField {
|
||||
text: SubtitlesSettings.preferredLanguage
|
||||
placeholderText: "eng,ger etc."
|
||||
Layout.fillWidth: true
|
||||
onTextEdited: {
|
||||
SubtitlesSettings.preferredLanguage = text
|
||||
SubtitlesSettings.save()
|
||||
mpv.setProperty("slang", text)
|
||||
}
|
||||
|
||||
ToolTip {
|
||||
text: i18n("Do not use spaces.")
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: i18n("Preferred track")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
SpinBox {
|
||||
from: 0
|
||||
to: 100
|
||||
value: SubtitlesSettings.preferredTrack
|
||||
editable: true
|
||||
onValueChanged: {
|
||||
SubtitlesSettings.preferredTrack = value
|
||||
SubtitlesSettings.save()
|
||||
if (value === 0) {
|
||||
mpv.setProperty("sid", "auto")
|
||||
} else {
|
||||
mpv.setProperty("sid", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: FishUI.Units.gridUnit
|
||||
height: FishUI.Units.gridUnit
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,178 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Controls 2.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
import org.kde.haruna 1.0
|
||||
import Haruna.Components 1.0
|
||||
|
||||
SettingsBasePage {
|
||||
id: root
|
||||
|
||||
hasHelp: true
|
||||
helpFile: ":/VideoSettings.html"
|
||||
docPage: "help:/haruna/VideoSettings.html"
|
||||
|
||||
GridLayout {
|
||||
id: content
|
||||
|
||||
columns: 2
|
||||
|
||||
SettingsHeader {
|
||||
text: i18n("Screenshots")
|
||||
topMargin: 0
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
// Screenshot Format
|
||||
// ------------------------------------
|
||||
Label {
|
||||
text: i18n("Format")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
Item {
|
||||
height: screenshotFormat.height
|
||||
ComboBox {
|
||||
id: screenshotFormat
|
||||
textRole: "key"
|
||||
model: ListModel {
|
||||
ListElement { key: "PNG"; }
|
||||
ListElement { key: "JPG"; }
|
||||
ListElement { key: "WebP"; }
|
||||
}
|
||||
|
||||
onActivated: {
|
||||
VideoSettings.screenshotFormat = model.get(index).key
|
||||
VideoSettings.save()
|
||||
mpv.setProperty("screenshot-format", VideoSettings.screenshotFormat)
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (VideoSettings.screenshotFormat === "PNG") {
|
||||
currentIndex = 0
|
||||
}
|
||||
if (VideoSettings.screenshotFormat === "JPG") {
|
||||
currentIndex = 1
|
||||
}
|
||||
if (VideoSettings.screenshotFormat === "WebP") {
|
||||
currentIndex = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
// Screenshot template
|
||||
// ------------------------------------
|
||||
Label {
|
||||
text: i18n("Template")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
Item {
|
||||
height: screenshotTemplate.height
|
||||
TextField {
|
||||
id: screenshotTemplate
|
||||
text: VideoSettings.screenshotTemplate
|
||||
onEditingFinished: {
|
||||
VideoSettings.screenshotTemplate = text
|
||||
VideoSettings.save()
|
||||
mpv.setProperty("screenshot-template", VideoSettings.screenshotTemplate)
|
||||
}
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
SettingsHeader {
|
||||
text: i18n("Image adjustments")
|
||||
Layout.columnSpan: 2
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------
|
||||
// CONTRAST
|
||||
// ------------------------------------
|
||||
Label {
|
||||
text: i18n("Contrast")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
ImageAdjustmentSlider {
|
||||
id: contrastSlider
|
||||
|
||||
value: mpv.contrast
|
||||
onSliderValueChanged: mpv.contrast = value.toFixed(0)
|
||||
|
||||
Layout.topMargin: FishUI.Units.largeSpacing
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
// BRIGHTNESS
|
||||
// ------------------------------------
|
||||
Label {
|
||||
text: i18n("Brightness")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
ImageAdjustmentSlider {
|
||||
id: brightnessSlider
|
||||
|
||||
value: mpv.brightness
|
||||
onSliderValueChanged: mpv.brightness = value.toFixed(0)
|
||||
|
||||
Layout.topMargin: FishUI.Units.largeSpacing
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
// GAMMA
|
||||
// ------------------------------------
|
||||
Label {
|
||||
text: i18n("Gamma")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
ImageAdjustmentSlider {
|
||||
id: gammaSlider
|
||||
|
||||
value: mpv.gamma
|
||||
onSliderValueChanged: mpv.gamma = value.toFixed(0)
|
||||
|
||||
Layout.topMargin: FishUI.Units.largeSpacing
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
// SATURATION
|
||||
// ------------------------------------
|
||||
Label {
|
||||
text: i18n("Saturation")
|
||||
Layout.alignment: Qt.AlignRight
|
||||
}
|
||||
|
||||
ImageAdjustmentSlider {
|
||||
id: saturationSlider
|
||||
|
||||
value: mpv.saturation
|
||||
onSliderValueChanged: mpv.saturation = value.toFixed(0)
|
||||
|
||||
Layout.topMargin: FishUI.Units.largeSpacing
|
||||
}
|
||||
|
||||
Label {
|
||||
text: i18n("Middle click on the sliders to reset them")
|
||||
Layout.columnSpan: 2
|
||||
Layout.topMargin: FishUI.Units.largeSpacing
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQml 2.12
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtQuick.Shapes 1.12
|
||||
import QtGraphicalEffects 1.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
import org.kde.haruna 1.0
|
||||
|
||||
Slider {
|
||||
id: root
|
||||
|
||||
from: 0
|
||||
to: 100
|
||||
value: mpv.volume
|
||||
implicitWidth: 100
|
||||
implicitHeight: 25
|
||||
wheelEnabled: true
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
|
||||
onValueChanged: {
|
||||
mpv.volume = value.toFixed(0)
|
||||
GeneralSettings.volume = value.toFixed(0)
|
||||
GeneralSettings.save()
|
||||
}
|
||||
}
|
||||
@ -1,236 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import QtQuick 2.12
|
||||
import QtQuick.Controls 2.12
|
||||
import QtQuick.Window 2.12
|
||||
import QtQuick.Layouts 1.12
|
||||
import QtGraphicalEffects 1.12
|
||||
import Qt.labs.platform 1.0 as Platform
|
||||
import QtQml 2.12
|
||||
|
||||
import FishUI 1.0 as FishUI
|
||||
|
||||
import org.kde.haruna 1.0
|
||||
|
||||
import mpv 1.0
|
||||
import "Menus"
|
||||
import "Settings"
|
||||
|
||||
FishUI.Window {
|
||||
id: window
|
||||
|
||||
property var configure: app.action("configure")
|
||||
property int preFullScreenVisibility
|
||||
property var appActions: actions.list
|
||||
|
||||
visible: true
|
||||
title: mpv.mediaTitle
|
||||
width: 1200
|
||||
minimumWidth: 700
|
||||
height: 720
|
||||
minimumHeight: 450
|
||||
color: FishUI.Theme.backgroundColor
|
||||
|
||||
header.visible: false
|
||||
|
||||
onVisibilityChanged: {
|
||||
if (!window.isFullScreen()) {
|
||||
preFullScreenVisibility = visibility
|
||||
}
|
||||
}
|
||||
|
||||
contentTopMargin: 0
|
||||
|
||||
Header { id: header }
|
||||
|
||||
// menuBar: MenuBar {
|
||||
// hoverEnabled: true
|
||||
// visible: !window.isFullScreen() && GeneralSettings.showMenuBar
|
||||
// background: Rectangle {
|
||||
// color: Kirigami.Theme.backgroundColor
|
||||
// }
|
||||
// Kirigami.Theme.colorSet: Kirigami.Theme.Header
|
||||
|
||||
// FileMenu {}
|
||||
// ViewMenu {}
|
||||
// PlaybackMenu {}
|
||||
// SubtitlesMenu {}
|
||||
// AudioMenu {}
|
||||
// SettingsMenu {}
|
||||
// HelpMenu {}
|
||||
// }
|
||||
|
||||
// Menu {
|
||||
// id: mpvContextMenu
|
||||
|
||||
// modal: true
|
||||
|
||||
// FileMenu {}
|
||||
// ViewMenu {}
|
||||
// PlaybackMenu {}
|
||||
// SubtitlesMenu {}
|
||||
// AudioMenu {}
|
||||
// SettingsMenu {}
|
||||
// HelpMenu {}
|
||||
// }
|
||||
|
||||
// SystemPalette { id: systemPalette; colorGroup: SystemPalette.Active }
|
||||
|
||||
SettingsEditor { id: settingsEditor }
|
||||
|
||||
Actions { id: actions }
|
||||
|
||||
MpvVideo {
|
||||
id: mpv
|
||||
|
||||
Osd { id: osd }
|
||||
}
|
||||
|
||||
PlayList { id: playList }
|
||||
|
||||
Footer {
|
||||
id: footer
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: mpv.bottom
|
||||
|
||||
// anchors.leftMargin: FishUI.Units.largeSpacing * 2
|
||||
// anchors.rightMargin: FishUI.Units.largeSpacing * 2
|
||||
// anchors.bottomMargin: FishUI.Units.largeSpacing * 2
|
||||
}
|
||||
|
||||
Instantiator {
|
||||
model: proxyCustomCommandsModel
|
||||
delegate: Action {
|
||||
property var qaction: app.action(model.commandId)
|
||||
text: qaction.text
|
||||
shortcut: qaction.shortcutName
|
||||
onTriggered: {
|
||||
mpv.userCommand(model.command)
|
||||
osd.message(mpv.command(["expand-text", model.osdMessage]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Platform.FileDialog {
|
||||
id: fileDialog
|
||||
|
||||
property url location: GeneralSettings.fileDialogLocation
|
||||
? app.pathToUrl(GeneralSettings.fileDialogLocation)
|
||||
: app.pathToUrl(GeneralSettings.fileDialogLastLocation)
|
||||
|
||||
folder: location
|
||||
title: "Select file"
|
||||
fileMode: Platform.FileDialog.OpenFile
|
||||
|
||||
onAccepted: {
|
||||
openFile(fileDialog.file.toString(), true, PlaylistSettings.loadSiblings)
|
||||
// the timer scrolls the playlist to the playing file
|
||||
// once the table view rows are loaded
|
||||
playList.scrollPositionTimer.start()
|
||||
mpv.focus = true
|
||||
|
||||
GeneralSettings.fileDialogLastLocation = app.parentUrl(fileDialog.file)
|
||||
GeneralSettings.save()
|
||||
}
|
||||
onRejected: mpv.focus = true
|
||||
}
|
||||
|
||||
Popup {
|
||||
id: openUrlPopup
|
||||
x: 10
|
||||
y: 10
|
||||
|
||||
onOpened: {
|
||||
openUrlTextField.forceActiveFocus(Qt.MouseFocusReason)
|
||||
openUrlTextField.selectAll()
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
Label {
|
||||
text: qsTr("<a href=\"https://youtube-dl.org\">Youtube-dl</a> was not found.")
|
||||
visible: !app.hasYoutubeDl()
|
||||
onLinkActivated: Qt.openUrlExternally(link)
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: openUrlTextField
|
||||
|
||||
visible: app.hasYoutubeDl()
|
||||
Layout.preferredWidth: 400
|
||||
Layout.fillWidth: true
|
||||
Component.onCompleted: text = GeneralSettings.lastUrl
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.key === Qt.Key_Enter
|
||||
|| event.key === Qt.Key_Return) {
|
||||
openUrlButton.clicked()
|
||||
}
|
||||
if (event.key === Qt.Key_Escape) {
|
||||
openUrlPopup.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
Button {
|
||||
id: openUrlButton
|
||||
|
||||
visible: app.hasYoutubeDl()
|
||||
text: qsTr("Open")
|
||||
|
||||
onClicked: {
|
||||
openFile(openUrlTextField.text, true, false)
|
||||
GeneralSettings.lastUrl = openUrlTextField.text
|
||||
// in case the url is a playList, it opens the first video
|
||||
GeneralSettings.lastPlaylistIndex = 0
|
||||
openUrlPopup.close()
|
||||
openUrlTextField.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: app.activateColorScheme(GeneralSettings.colorScheme)
|
||||
|
||||
function openFile(path, startPlayback, loadSiblings) {
|
||||
if (app.isYoutubePlaylist(path)) {
|
||||
mpv.getYouTubePlaylist(path);
|
||||
playList.isYouTubePlaylist = true
|
||||
} else {
|
||||
playList.isYouTubePlaylist = false
|
||||
}
|
||||
|
||||
mpv.playlistModel.clear()
|
||||
mpv.pause = !startPlayback
|
||||
if (loadSiblings) {
|
||||
// get video files from same folder as the opened file
|
||||
mpv.playlistModel.getVideos(path)
|
||||
}
|
||||
mpv.loadFile(path)
|
||||
}
|
||||
|
||||
function isFullScreen() {
|
||||
return window.visibility === Window.FullScreen
|
||||
}
|
||||
|
||||
function toggleFullScreen() {
|
||||
if (!isFullScreen()) {
|
||||
window.showFullScreen()
|
||||
} else {
|
||||
if (window.preFullScreenVisibility === Window.Windowed) {
|
||||
window.showNormal()
|
||||
}
|
||||
if (window.preFullScreenVisibility === Window.Maximized) {
|
||||
window.show()
|
||||
window.showMaximized()
|
||||
}
|
||||
}
|
||||
app.showCursor()
|
||||
playList.scrollPositionTimer.start()
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile name="haruna/haruna.conf" />
|
||||
<group name="Audio">
|
||||
<entry name="PreferredLanguage" type="String">
|
||||
<label>Preferred language</label>
|
||||
</entry>
|
||||
<entry name="PreferredTrack" type="Int">
|
||||
<label>Preferred track</label>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
@ -1,10 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
File=audiosettings.kcfg
|
||||
ClassName=AudioSettings
|
||||
Mutators=true
|
||||
DefaultValueGetters=true
|
||||
GenerateProperties=true
|
||||
ParentInConstructor=true
|
||||
Singleton=true
|
||||
@ -1,79 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile name="haruna/haruna.conf" />
|
||||
<include>QStandardPaths</include>
|
||||
<group name="General">
|
||||
<entry name="OsdFontSize" type="Int">
|
||||
<label>Osd font size</label>
|
||||
<default>25</default>
|
||||
</entry>
|
||||
<entry name="VolumeStep" type="Int">
|
||||
<label>Volume step</label>
|
||||
<default>5</default>
|
||||
</entry>
|
||||
<entry name="SeekSmallStep" type="Int">
|
||||
<label>Seek small step</label>
|
||||
<default>5</default>
|
||||
</entry>
|
||||
<entry name="SeekMediumStep" type="Int">
|
||||
<label>Seek medium step</label>
|
||||
<default>15</default>
|
||||
</entry>
|
||||
<entry name="SeekBigStep" type="Int">
|
||||
<label>Seek big step</label>
|
||||
<default>30</default>
|
||||
</entry>
|
||||
<entry name="ShowMenuBar" type="bool">
|
||||
<label>Show menu bar</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="ShowHeader" type="bool">
|
||||
<label>Show header</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="ShowChapterMarkers" type="bool">
|
||||
<label>Show chapter markers</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="ColorScheme" type="String">
|
||||
<label>Color scheme</label>
|
||||
</entry>
|
||||
<entry name="UseBreezeIconTheme" type="bool">
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="GuiStyle" type="String">
|
||||
<default>Default</default>
|
||||
</entry>
|
||||
<entry name="Volume" type="Int">
|
||||
<label>Volume</label>
|
||||
<default>80</default>
|
||||
</entry>
|
||||
<entry name="LastPlayedFile" type="String">
|
||||
<label>Last played file</label>
|
||||
</entry>
|
||||
<entry name="LastPlaylistIndex" type="Int">
|
||||
<default>0</default>
|
||||
</entry>
|
||||
<entry name="FileDialogLocation" type="String">
|
||||
<label>File default dialog location</label>
|
||||
</entry>
|
||||
<entry name="FileDialogLastLocation" type="String">
|
||||
<label>File dialog last location</label>
|
||||
<code>
|
||||
QString videoFolder = QStandardPaths::writableLocation(QStandardPaths::MoviesLocation);
|
||||
</code>
|
||||
<default code="true">videoFolder</default>
|
||||
</entry>
|
||||
<entry name="LastUrl" type="String">
|
||||
<label>Last url</label>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
@ -1,10 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
File=generalsettings.kcfg
|
||||
ClassName=GeneralSettings
|
||||
Mutators=true
|
||||
DefaultValueGetters=true
|
||||
GenerateProperties=true
|
||||
ParentInConstructor=true
|
||||
Singleton=true
|
||||
@ -1,44 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile name="haruna/haruna.conf" />
|
||||
<group name="Mouse">
|
||||
<entry name="Left" type="String">
|
||||
<label>Action for left click</label>
|
||||
</entry>
|
||||
<entry name="Leftx2" type="String">
|
||||
<label>Action for left double click</label>
|
||||
<default>toggleFullscreenAction</default>
|
||||
</entry>
|
||||
<entry name="Middle" type="String">
|
||||
<label>Action for middle click</label>
|
||||
<default>muteAction</default>
|
||||
</entry>
|
||||
<entry name="Middlex2" type="String">
|
||||
<label>Action for middle double click</label>
|
||||
<default>configureAction</default>
|
||||
</entry>
|
||||
<entry name="Right" type="String">
|
||||
<label>Action for right click</label>
|
||||
<default>playPauseAction</default>
|
||||
</entry>
|
||||
<entry name="Rightx2" type="String">
|
||||
<label>Action for right double click</label>
|
||||
</entry>
|
||||
<entry name="ScrollUp" type="String">
|
||||
<label>Action for scroll up</label>
|
||||
<default>volumeUpAction</default>
|
||||
</entry>
|
||||
<entry name="ScrollDown" type="String">
|
||||
<label>Action for scroll down</label>
|
||||
<default>volumeDownAction</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
@ -1,10 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
File=mousesettings.kcfg
|
||||
ClassName=MouseSettings
|
||||
Mutators=true
|
||||
DefaultValueGetters=true
|
||||
GenerateProperties=true
|
||||
ParentInConstructor=true
|
||||
Singleton=true
|
||||
@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile name="haruna/haruna.conf" />
|
||||
<group name="Playback">
|
||||
<entry name="MinDurationToSavePosition" type="int">
|
||||
<default>1</default>
|
||||
</entry>
|
||||
<entry name="SkipChapters" type="bool">
|
||||
<label>Skip chapters</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="ChaptersToSkip" type="String">
|
||||
<label>Chapters to skip</label>
|
||||
</entry>
|
||||
<entry name="ShowOsdOnSkipChapters" type="bool">
|
||||
<label>Show osd on skip chapters</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="YtdlFormat" type="String">
|
||||
<label>Ytdl format selection</label>
|
||||
</entry>
|
||||
<entry name="UseHWDecoding" type="bool">
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="HWDecoding" type="String">
|
||||
<default>auto</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
@ -1,10 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
File=playbacksettings.kcfg
|
||||
ClassName=PlaybackSettings
|
||||
Mutators=true
|
||||
DefaultValueGetters=true
|
||||
GenerateProperties=true
|
||||
ParentInConstructor=true
|
||||
Singleton=true
|
||||
@ -1,56 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile name="haruna/haruna.conf" />
|
||||
<group name="Playlist">
|
||||
<entry name="Position" type="String">
|
||||
<label>Position</label>
|
||||
<default>right</default>
|
||||
</entry>
|
||||
<entry name="RowHeight" type="Int">
|
||||
<label>Row height</label>
|
||||
<default>10</default>
|
||||
</entry>
|
||||
<entry name="Style" type="String">
|
||||
<default>default</default>
|
||||
</entry>
|
||||
<entry name="OverlayVideo" type="bool">
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="ShowThumbnails" type="bool">
|
||||
<label>Show thumbnails</label>
|
||||
<default>false</default>
|
||||
</entry>
|
||||
<entry name="ShowMediaTitle" type="bool">
|
||||
<label>Show media title instead of file name</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="LoadSiblings" type="bool">
|
||||
<label>Auto load videos from same folder</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="Repeat" type="bool">
|
||||
<label>Repeat</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="ShowRowNumber" type="bool">
|
||||
<label>Show row number</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="CanToggleWithMouse" type="bool">
|
||||
<label>Toggle with mouse</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry name="BigFontFullscreen" type="bool">
|
||||
<label>Increase font size when fullscreen</label>
|
||||
<default>true</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
@ -1,10 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
File=playlistsettings.kcfg
|
||||
ClassName=PlaylistSettings
|
||||
Mutators=true
|
||||
DefaultValueGetters=true
|
||||
GenerateProperties=true
|
||||
ParentInConstructor=true
|
||||
Singleton=true
|
||||
@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile name="haruna/haruna.conf" />
|
||||
<group name="Subtitles">
|
||||
<entry name="SubtitlesFolders" type="StringList">
|
||||
<label>Subtitles folders</label>
|
||||
<default>subs</default>
|
||||
</entry>
|
||||
<entry name="PreferredLanguage" type="String">
|
||||
<label>Preferred language</label>
|
||||
</entry>
|
||||
<entry name="PreferredTrack" type="Int">
|
||||
<label>Preferred track</label>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||
@ -1,10 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
File=subtitlessettings.kcfg
|
||||
ClassName=SubtitlesSettings
|
||||
Mutators=true
|
||||
DefaultValueGetters=true
|
||||
GenerateProperties=true
|
||||
ParentInConstructor=true
|
||||
Singleton=true
|
||||
@ -1,27 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-or-later
|
||||
-->
|
||||
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
|
||||
http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
|
||||
<kcfgfile name="haruna/haruna.conf" />
|
||||
<include>QStandardPaths</include>
|
||||
<group name="Video">
|
||||
<entry name="ScreenshotFormat" type="String">
|
||||
<label>Screenshot format</label>
|
||||
<default>jpg</default>
|
||||
</entry>
|
||||
<entry name="ScreenshotTemplate" type="String">
|
||||
<label>Screenshot template</label>
|
||||
<code>
|
||||
QString screenshotsFolder = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);
|
||||
screenshotsFolder.append("/Haruna screenshots/%F-%n");
|
||||
</code>
|
||||
<default code="true">screenshotsFolder</default>
|
||||
</entry>
|
||||
</group>
|
||||
</kcfg>
|
||||