Warning, /plasma/kdeplasma-addons/applets/mediaframe/package/contents/ui/main.qml is written in an unsupported language. File is not indexed.

0001 /*
0002  *  SPDX-FileCopyrightText: 2015 Lars Pontoppidan <dev.larpon@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 import QtQuick
0008 import QtQuick.Layouts
0009 import QtQuick.Dialogs
0010 
0011 import org.kde.draganddrop 2.0 as DragDrop
0012 
0013 import org.kde.plasma.plasmoid 2.0
0014 import org.kde.plasma.core as PlasmaCore
0015 import org.kde.kirigami 2.20 as Kirigami
0016 import org.kde.plasma.components 3.0 as PlasmaComponents3
0017 import org.kde.kquickcontrolsaddons 2.0
0018 
0019 import org.kde.plasma.private.mediaframe 2.0
0020 
0021 PlasmoidItem {
0022     id: main
0023 
0024     MediaFrame {
0025         id: items
0026         random: plasmoid.configuration.randomize
0027     }
0028 
0029     preferredRepresentation: fullRepresentation
0030 
0031     switchWidth: Kirigami.Units.gridUnit * 5
0032     switchHeight: Kirigami.Units.gridUnit * 5
0033 
0034     Plasmoid.backgroundHints: PlasmaCore.Types.DefaultBackground | PlasmaCore.Types.ConfigurableBackground
0035 
0036     width: Kirigami.Units.gridUnit * 20
0037     height: Kirigami.Units.gridUnit * 13
0038 
0039     property string activeSource: ""
0040     property string transitionSource: ""
0041 
0042     readonly property bool pause: overlayMouseArea.containsMouse
0043 
0044     readonly property int itemCount: (items.count + items.futureLength)
0045     readonly property bool hasItems: ((itemCount > 0) || (items.futureLength > 0))
0046     readonly property bool isTransitioning: faderAnimation.running
0047 
0048     onActiveSourceChanged: {
0049         items.watch(activeSource)
0050     }
0051 
0052     onHasItemsChanged: {
0053         if(hasItems) {
0054             if(activeSource == "")
0055                 nextItem()
0056         }
0057     }
0058 
0059     onExternalData: (mimetype, data) => {
0060         var type = items.isDir(data) ? "folder" : "file";
0061         var item = {
0062             "path": data,
0063             "type": type
0064         };
0065 
0066         addItem(item);
0067     }
0068 
0069     function loadPathList() {
0070         var list = plasmoid.configuration.pathList
0071         items.clear()
0072         for(var i in list) {
0073             var item = JSON.parse(list[i])
0074             items.add(item.path,true)
0075         }
0076     }
0077 
0078     Component.onCompleted: {
0079         loadPathList()
0080 
0081         if (items.random)
0082             nextItem()
0083     }
0084 
0085     Connections {
0086         target: plasmoid.configuration
0087         function onPathListChanged() {
0088             loadPathList()
0089         }
0090     }
0091 
0092     function addItem(item) {
0093 
0094         if(items.isAdded(item.path)) {
0095             console.info(item.path,"already exists. Skippingā€¦")
0096             return
0097         }
0098         // work-around for QTBUG-67773:
0099         // C++ object property of type QVariant(QStringList) is not updated on changes from QML
0100         // so explicitly create a deep JSValue copy, modify that and then set it back to overwrite the old
0101         var updatedList = plasmoid.configuration.pathList.slice();
0102         updatedList.push(JSON.stringify(item));
0103         plasmoid.configuration.pathList = updatedList;
0104     }
0105 
0106     function nextItem() {
0107 
0108         if(!hasItems) {
0109             console.warn("No items available")
0110             return
0111         }
0112 
0113         var active = activeSource
0114 
0115         // Only record history if we have more than one item
0116         if(itemCount > 1)
0117             items.pushHistory(active)
0118 
0119         if(items.futureLength > 0) {
0120             setActiveSource(items.popFuture())
0121         } else {
0122             //setLoading()
0123             items.get(function(filePath){
0124                 setActiveSource(filePath)
0125                 //unsetLoading()
0126             },function(errorMessage){
0127                 //unsetLoading()
0128                 console.error("Error while getting next image",errorMessage)
0129             })
0130         }
0131     }
0132 
0133     function previousItem() {
0134         var active = activeSource
0135         items.pushFuture(active)
0136         var filePath = items.popHistory()
0137         setActiveSource(filePath)
0138     }
0139 
0140     Connections {
0141         target: items
0142 
0143         function onItemChanged(path) {
0144             console.log("item",path,"changed")
0145             activeSource = ""
0146             setActiveSource(path)
0147         }
0148 
0149     }
0150 
0151     Timer {
0152         id: nextTimer
0153         interval: (plasmoid.configuration.interval*1000)
0154         repeat: true
0155         running: hasItems && !pause
0156         onTriggered: nextItem()
0157     }
0158 
0159     Item {
0160         id: itemView
0161         anchors.fill: parent
0162 
0163         /*
0164         Video {
0165             id: video
0166             width : 800
0167             height : 600
0168             source: ""
0169 
0170             onStatusChanged: {
0171                 if(status == Video.Loaded)
0172                     video.play()
0173             }
0174         }
0175         */
0176 
0177         Item {
0178             id: imageView
0179             visible: hasItems
0180             anchors.fill: parent
0181 
0182             // This timer prevents reloading the image too often when resizing,
0183             // to minimize excessively re-reading the file on disk
0184             Timer {
0185                 id: imageReloadTimer
0186                 interval: 250
0187                 running: false
0188                 onTriggered: {
0189                     frontImage.sourceSize.width = width
0190                     frontImage.sourceSize.height = height
0191                 }
0192             }
0193 
0194             Image {
0195                 id: bufferImage
0196 
0197 
0198                 anchors.fill: parent
0199                 fillMode: plasmoid.configuration.fillMode
0200 
0201                 opacity: 0
0202 
0203                 cache: false
0204                 source: transitionSource
0205 
0206                 asynchronous: true
0207                 autoTransform: true
0208             }
0209 
0210             Image {
0211                 id: frontImage
0212 
0213                 anchors.fill: parent
0214                 fillMode: plasmoid.configuration.fillMode
0215 
0216                 cache: false
0217                 source: activeSource
0218 
0219                 asynchronous: true
0220                 autoTransform: true
0221 
0222                 onWidthChanged: imageReloadTimer.restart()
0223                 onHeightChanged: imageReloadTimer.restart()
0224 
0225                 sourceSize.width: width
0226                 sourceSize.height: height
0227 
0228                 HoverHandler {
0229                     enabled: Plasmoid.configuration.leftClickOpenImage
0230                     cursorShape: Qt.PointingHandCursor
0231                 }
0232 
0233                 TapHandler {
0234                     acceptedButtons: Qt.LeftButton
0235                     enabled: Plasmoid.configuration.leftClickOpenImage
0236                     onTapped: Qt.openUrlExternally(activeSource)
0237                 }
0238             }
0239         }
0240 
0241         // BUG TODO fix the rendering of the drop shadow
0242         /*
0243         DropShadow {
0244             id: itemViewDropShadow
0245             anchors.fill: parent
0246             visible: imageView.visible && !plasmoid.configuration.useBackground
0247 
0248             radius: 8.0
0249             samples: 16
0250             color: "#80000000"
0251             source: frontImage
0252         }
0253         */
0254 
0255     }
0256 
0257     function setActiveSource(source) {
0258         if(itemCount > 1) { // Only do transition if we have more that one item
0259             transitionSource = source
0260             faderAnimation.restart()
0261         } else {
0262             transitionSource = source
0263             activeSource = source
0264         }
0265     }
0266 
0267     SequentialAnimation {
0268         id: faderAnimation
0269 
0270         ParallelAnimation {
0271             OpacityAnimator { target: frontImage; from: 1; to: 0; duration: Kirigami.Units.veryLongDuration }
0272             OpacityAnimator { target: bufferImage; from: 0; to: 1; duration: Kirigami.Units.veryLongDuration }
0273         }
0274         ScriptAction {
0275             script: {
0276                 // Copy the transitionSource
0277                 var ts = transitionSource
0278                 activeSource = ts
0279                 frontImage.opacity = 1
0280                 transitionSource = ""
0281                 bufferImage.opacity = 0
0282             }
0283         }
0284     }
0285 
0286     DragDrop.DropArea {
0287         id: dropArea
0288         anchors.fill: parent
0289 
0290         onDrop: {
0291             var mimeData = event.mimeData
0292             if (mimeData.hasUrls) {
0293                 var urls = mimeData.urls
0294                 for (var i = 0, j = urls.length; i < j; ++i) {
0295                     var url = urls[i]
0296                     var type = items.isDir(url) ? "folder" : "file"
0297                     var item = { "path":url, "type":type }
0298                     addItem(item)
0299                 }
0300             }
0301             event.accept(Qt.CopyAction)
0302         }
0303     }
0304 
0305     Item {
0306         id: overlay
0307 
0308         anchors.fill: parent
0309 
0310         visible: hasItems
0311         opacity: overlayMouseArea.containsMouse ? 1 : 0
0312 
0313         Behavior on opacity {
0314             NumberAnimation {}
0315         }
0316 
0317         PlasmaComponents3.Button {
0318             anchors.left: parent.left
0319             anchors.verticalCenter: parent.verticalCenter
0320             enabled: (items.historyLength > 0) && !isTransitioning
0321             visible: main.itemCount > 1
0322             icon.name: "arrow-left"
0323             onClicked: {
0324                 nextTimer.stop()
0325                 previousItem()
0326             }
0327         }
0328 
0329         PlasmaComponents3.Button {
0330             anchors.right: parent.right
0331             anchors.verticalCenter: parent.verticalCenter
0332             enabled: hasItems && !isTransitioning
0333             visible: main.itemCount > 1
0334             icon.name: "arrow-right"
0335             onClicked: {
0336                 nextTimer.stop()
0337                 nextItem()
0338             }
0339         }
0340 
0341         Row {
0342             anchors.bottom: parent.bottom
0343             anchors.horizontalCenter: parent.horizontalCenter
0344             anchors.bottomMargin: Kirigami.Units.smallSpacing
0345 
0346             /*
0347             PlasmaComponents3.Button {
0348                 icon.name: "documentinfo"
0349                 onClicked: {  }
0350             }
0351             */
0352             PlasmaComponents3.Button {
0353 
0354                 //text: activeSource.split("/").pop().slice(-25)
0355                 icon.name: "document-preview"
0356                 onClicked: Qt.openUrlExternally(main.activeSource)
0357 
0358                 // PlasmaComponents3.ToolTip {
0359                 //     text: activeSource
0360                 // }
0361             }
0362             /*
0363             PlasmaComponents3.Button {
0364                 icon.name: "trash-empty"
0365                 onClicked: {  }
0366             }
0367 
0368             PlasmaComponents3.Button {
0369                 icon.name: "flag-black"
0370                 onClicked: {  }
0371             }
0372             */
0373         }
0374 
0375         // BUG TODO Fix overlay so _all_ mouse events reach lower components
0376         MouseArea {
0377             id: overlayMouseArea
0378 
0379             anchors.fill: parent
0380             hoverEnabled: true
0381 
0382             propagateComposedEvents: true
0383 
0384             //onClicked: mouse.accepted = false;
0385             onPressed: mouse.accepted = false;
0386             //onReleased: mouse.accepted = false;
0387             onDoubleClicked: mouse.accepted = false;
0388             //onPositionChanged: mouse.accepted = false;
0389             //onPressAndHold: mouse.accepted = false;
0390 
0391         }
0392 
0393     }
0394 
0395     // Visualization of the count down
0396     // TODO Makes plasmashell suck CPU until the universe or the computer collapse in on itself
0397     /*
0398     Rectangle {
0399         id: progress
0400 
0401         visible: plasmoid.configuration.showCountdown && hasItems && itemCount > 1
0402 
0403         color: "transparent"
0404 
0405         implicitWidth: Kirigami.Units.gridUnit
0406         implicitHeight: implicitWidth
0407 
0408         Rectangle {
0409             anchors.fill: parent
0410 
0411             opacity:  pause ? 0.1 : 0.5
0412 
0413             radius: width / 2
0414             color: "gray"
0415 
0416             Rectangle {
0417                 id: innerRing
0418                 anchors.fill: parent
0419 
0420                 scale: 0
0421 
0422                 radius: width / 2
0423 
0424                 color: "lightblue"
0425 
0426                 ScaleAnimator on scale {
0427                     running: nextTimer.running
0428                     loops: Animation.Infinite
0429                     from: 0;
0430                     to: 1;
0431                     duration: nextTimer.interval
0432                 }
0433 
0434             }
0435         }
0436 
0437         Kirigami.Icon {
0438             id: pauseIcon
0439             visible: pause
0440             anchors.fill: parent
0441             source: "media-playback-pause"
0442         }
0443     }
0444     */
0445 
0446     PlasmaComponents3.Button {
0447 
0448         anchors.centerIn: parent
0449 
0450         visible: !hasItems
0451         icon.name: "configure"
0452         text: i18nc("@action:button", "Configureā€¦")
0453         onClicked: {
0454             Plasmoid.internalAction("configure").trigger();
0455         }
0456     }
0457 }