Warning, /multimedia/haruna/src/qml/main.qml is written in an unsupported language. File is not indexed.
0001 /* 0002 * SPDX-FileCopyrightText: 2020 George Florea Bănuș <georgefb899@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 import QtQuick 0008 import QtQuick.Window 0009 import QtQuick.Layouts 0010 import Qt.labs.platform as Platform 0011 import QtQml 0012 0013 import org.kde.kirigami as Kirigami 0014 import org.kde.haruna 0015 import org.kde.haruna.settings 0016 0017 Kirigami.ApplicationWindow { 0018 id: window 0019 0020 property bool containsMouse: false 0021 0022 property int previousVisibility: Window.Windowed 0023 property var acceptedSubtitleTypes: ["application/x-subrip", "text/x-ssa"] 0024 0025 visible: true 0026 title: mpv.mediaTitle || i18nc("@title:window", "Haruna") 0027 width: Kirigami.Units.gridUnit * 66 0028 minimumWidth: Kirigami.Units.gridUnit * 36 0029 height: Kirigami.Units.gridUnit * 40 0030 minimumHeight: Kirigami.Units.gridUnit * 22 0031 color: Kirigami.Theme.backgroundColor 0032 0033 onClosing: app.saveWindowGeometry(window) 0034 onWidthChanged: saveWindowGeometryTimer.restart() 0035 onHeightChanged: saveWindowGeometryTimer.restart() 0036 onXChanged: saveWindowGeometryTimer.restart() 0037 onYChanged: saveWindowGeometryTimer.restart() 0038 0039 onVisibilityChanged: function(visibility) { 0040 if (PlaybackSettings.pauseWhileMinimized) { 0041 if (visibility === Window.Minimized) { 0042 if (mpv.pause) { 0043 mpv.preMinimizePlaybackState = MpvVideo.PlaybackState.Paused 0044 } else { 0045 mpv.preMinimizePlaybackState = MpvVideo.PlaybackState.Playing 0046 } 0047 mpv.pause = true 0048 } 0049 if (previousVisibility === Window.Minimized 0050 && visibility === Window.Windowed | Window.Maximized | Window.FullScreen) { 0051 if (mpv.preMinimizePlaybackState === MpvVideo.PlaybackState.Playing) { 0052 mpv.pause = false 0053 } 0054 } 0055 } 0056 0057 // used to restore window state, when exiting fullscreen, 0058 // to the one it had before going fullscreen 0059 if (visibility !== Window.FullScreen) { 0060 previousVisibility = visibility 0061 } 0062 } 0063 0064 header: Header { id: header } 0065 0066 menuBar: MenuBarLoader { 0067 id: menuBarLoader 0068 } 0069 0070 MpvVideo { 0071 id: mpv 0072 0073 width: window.contentItem.width 0074 height: window.isFullScreen() ? window.contentItem.height : window.contentItem.height - footer.height 0075 anchors.left: PlaylistSettings.overlayVideo 0076 ? window.contentItem.left 0077 : (PlaylistSettings.position === "left" ? playlist.right : window.contentItem.left) 0078 anchors.right: PlaylistSettings.overlayVideo 0079 ? window.contentItem.right 0080 : (PlaylistSettings.position === "right" ? playlist.left : window.contentItem.right) 0081 anchors.top: parent.top 0082 0083 onVideoReconfig: { 0084 resizeWindow() 0085 } 0086 0087 onAddToRecentFiles: function(url) { 0088 recentFilesModel.addUrl(url) 0089 } 0090 0091 Osd { 0092 id: osd 0093 0094 maxWidth: mpv.width 0095 } 0096 0097 SelectActionPopup { 0098 id: triggerActionPopup 0099 0100 property int minHeight: mpv.height * 0.5 0101 property int maxHeight: mpv.height * 0.9 0102 0103 x: mpv.width * 0.5 - width * 0.5 0104 y: Kirigami.Units.largeSpacing 0105 width: Kirigami.Units.gridUnit * 20 0106 height: minHeight < Kirigami.Units.gridUnit * 16 ? maxHeight : minHeight 0107 title: "" 0108 subtitle: "" 0109 0110 onActionSelected: function (actionName) { 0111 appActions[actionName].trigger() 0112 } 0113 } 0114 } 0115 0116 PlayList { 0117 id: playlist 0118 0119 anchors.top: mpv.top 0120 anchors.bottom: footer.top 0121 } 0122 0123 Footer { 0124 id: footer 0125 0126 m_mpv: mpv 0127 0128 anchors.left: window.contentItem.left 0129 anchors.right: window.contentItem.right 0130 anchors.bottom: window.isFullScreen() ? mpv.bottom : window.contentItem.bottom 0131 state: !window.isFullScreen() || (mpv.mouseY > window.height - footer.implicitHeight && window.containsMouse) 0132 ? "visible" : "hidden" 0133 } 0134 0135 Actions {} 0136 0137 ActionsModel { 0138 id: actionsModel 0139 } 0140 0141 ProxyActionsModel { 0142 id: proxyActionsModel 0143 0144 sourceModel: actionsModel 0145 } 0146 0147 CustomCommandsModel { 0148 id: customCommandsModel 0149 0150 appActionsModel: actionsModel 0151 Component.onCompleted: init() 0152 } 0153 0154 RecentFilesModel { 0155 id: recentFilesModel 0156 } 0157 0158 SubtitlesFoldersModel { 0159 id: subtitlesFoldersModel 0160 } 0161 0162 RowLayout { 0163 width: window.width * 0.8 > Kirigami.Units.gridUnit * 50 0164 ? Kirigami.Units.gridUnit * 50 0165 : window.width * 0.8 0166 anchors.centerIn: parent 0167 0168 Kirigami.InlineMessage { 0169 id: messageBox 0170 0171 Layout.fillWidth: true 0172 Layout.fillHeight: true 0173 type: Kirigami.MessageType.Error 0174 showCloseButton: true 0175 } 0176 } 0177 0178 Loader { 0179 id: mpvContextMenuLoader 0180 0181 active: false 0182 sourceComponent: ContextMenu { 0183 onClosed: mpvContextMenuLoader.active = false 0184 } 0185 } 0186 0187 Loader { 0188 id: settingsLoader 0189 0190 active: false 0191 sourceComponent: SettingsWindow {} 0192 } 0193 0194 Connections { 0195 target: app 0196 function onQmlApplicationMouseLeave() { 0197 if (PlaylistSettings.canToggleWithMouse && window.isFullScreen()) { 0198 playlist.state = "hidden" 0199 } 0200 window.containsMouse = false 0201 } 0202 function onQmlApplicationMouseEnter() { 0203 window.containsMouse = true 0204 } 0205 function onError(message) { 0206 messageBox.visible = true 0207 messageBox.text = message 0208 } 0209 function onOpenUrl(url) { 0210 if (GeneralSettings.appendVideoToSingleInstance) { 0211 mpv.playlistModel.appendItem(url.toString()) 0212 } else { 0213 openFile(url) 0214 } 0215 } 0216 } 0217 0218 Platform.FileDialog { 0219 id: fileDialog 0220 0221 property url location: GeneralSettings.fileDialogLocation 0222 ? app.pathToUrl(GeneralSettings.fileDialogLocation) 0223 : app.pathToUrl(GeneralSettings.fileDialogLastLocation) 0224 0225 folder: location 0226 title: i18nc("@title:window", "Select file") 0227 fileMode: Platform.FileDialog.OpenFile 0228 0229 onAccepted: { 0230 openFile(fileDialog.file.toString(), true) 0231 mpv.focus = true 0232 0233 GeneralSettings.fileDialogLastLocation = app.parentUrl(fileDialog.file) 0234 GeneralSettings.save() 0235 } 0236 onRejected: mpv.focus = true 0237 } 0238 0239 Platform.FileDialog { 0240 id: subtitlesFileDialog 0241 0242 property url location: { 0243 if (mpv.currentUrl) { 0244 return app.parentUrl(mpv.currentUrl) 0245 } else { 0246 return (GeneralSettings.fileDialogLocation 0247 ? app.pathToUrl(GeneralSettings.fileDialogLocation) 0248 : app.pathToUrl(GeneralSettings.fileDialogLastLocation)) 0249 } 0250 } 0251 0252 folder: location 0253 title: i18nc("@title:window", "Select subtitles file") 0254 fileMode: Platform.FileDialog.OpenFile 0255 nameFilters: ["Subtitles (*.srt *.ssa *.ass)"] 0256 0257 onAccepted: { 0258 if (acceptedSubtitleTypes.includes(app.mimeType(subtitlesFileDialog.file))) { 0259 mpv.command(["sub-add", subtitlesFileDialog.file.toString(), "select"]) 0260 } 0261 } 0262 onRejected: mpv.focus = true 0263 } 0264 0265 InputPopup { 0266 id: openUrlPopup 0267 0268 x: 10 0269 y: 10 0270 lastUrl: GeneralSettings.lastUrl 0271 buttonText: i18nc("@action:button", "Open") 0272 0273 onUrlOpened: function(url) { 0274 window.openFile(url, true) 0275 GeneralSettings.lastUrl = url 0276 GeneralSettings.save() 0277 } 0278 } 0279 0280 // This timer allows to batch update the window size change to reduce 0281 // the io load and also work around the fact that x/y/width/height are 0282 // changed when loading the page and overwrite the saved geometry from 0283 // the previous session. 0284 Timer { 0285 id: saveWindowGeometryTimer 0286 0287 interval: 1000 0288 onTriggered: app.saveWindowGeometry(window) 0289 } 0290 0291 Component.onCompleted: { 0292 app.restoreWindowGeometry(window) 0293 app.activateColorScheme(GeneralSettings.colorScheme) 0294 } 0295 0296 function openFile(path, addToRecentFiles = false) { 0297 if (addToRecentFiles) { 0298 recentFilesModel.addUrl(path) 0299 } 0300 0301 mpv.playlistModel.addItem(path, PlaylistModel.Clear) 0302 } 0303 0304 function isFullScreen() { 0305 return window.visibility === Window.FullScreen 0306 } 0307 0308 function toggleFullScreen() { 0309 if (!isFullScreen()) { 0310 window.showFullScreen() 0311 } else { 0312 exitFullscreen() 0313 } 0314 } 0315 0316 function exitFullscreen() { 0317 if (window.previousVisibility === Window.Maximized) { 0318 window.show() 0319 window.showMaximized() 0320 } else { 0321 window.showNormal() 0322 } 0323 } 0324 0325 function resizeWindow() { 0326 if (!GeneralSettings.resizeWindowToVideo || isFullScreen()) { 0327 return 0328 } 0329 0330 window.width = mpv.videoWidth 0331 window.height = mpv.videoHeight 0332 + (footer.visible ? footer.height : 0) 0333 + (header.visible ? header.height : 0) 0334 + (menuBar.visible ? menuBar.height : 0) 0335 } 0336 }