Guest User

Untitled

a guest
Nov 3rd, 2017
140
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
QML 20.48 KB | None | 0 0
  1. /****************************************************************************
  2. **
  3. ** Copyright (C) 2013 Jolla Ltd.
  4. ** Contact: Vesa Halttunen <vesa.halttunen@jollamobile.com>
  5. **
  6. ****************************************************************************/
  7.  
  8. import QtQuick 2.0
  9. import org.nemomobile.lipstick 0.1
  10. import Sailfish.Silica 1.0
  11. import org.nemomobile.systemsettings 1.0
  12. import org.nemomobile.configuration 1.0
  13. import org.nemomobile.mpris 1.0
  14. import QtFeedback 5.0
  15. import "../systemwindow"
  16. import "../compositor"
  17.  
  18. SystemWindow {
  19.     id: volumeBar
  20.  
  21.     MprisManager { id: mprisManager }
  22.    
  23.     property bool volumeIncreasing
  24.     property bool lateScreenshotCapture
  25.     property var screenshot
  26.     property bool controllingMedia: forceMediaVolume.value ||
  27.                                     volumeControl.mediaState === VolumeControl.MediaStateActive ||
  28.                                     volumeControl.mediaState === VolumeControl.MediaStateForeground ||
  29.                                     volumeControl.mediaState === VolumeControl.MediaStateBackground ||
  30.                                     volumeControl.callActive || showContinuousVolume
  31.     property real statusBarPushDownY: volumeArea.y + volumeArea.height
  32.     property bool showContinuousVolume: false
  33.     property int maximumVolume: controllingMedia ? volumeControl.maximumVolume : 100
  34.     property real initialChange: 0
  35.     property bool disableSmoothChange: true
  36.     property real baseVolume
  37.     property real continuousVolume: {
  38.         // The maximum continuous volume that should be allowed. Plus one so that the warning is triggered.
  39.         var max = (controllingMedia && volumeControl.restrictedVolume !== volumeControl.maximumVolume)
  40.                     ? (volumeControl.restrictedVolume+1) : maximumVolume
  41.  
  42.         // delta ranges from -1 to 1 (ratio of window dimension plus direction)
  43.         // Triple rate of volume change as in practice will not reach these limits.
  44.         var d = Lipstick.compositor.volumeGestureFilterItem.delta
  45.         return Math.min(Math.max(baseVolume + 3*d*maximumVolume, 0), max)
  46.     }
  47.     onContinuousVolumeChanged: {
  48.         if (!Lipstick.compositor.volumeGestureFilterItem.active)
  49.             return
  50.  
  51.         // Gesture only controls media volume
  52.         if (Lipstick.compositor.volumeGestureFilterItem.deltaIncreasing) {
  53.             if (Math.floor(continuousVolume) === 0)
  54.                 volumeControl.volume = Math.ceil(continuousVolume)
  55.             else
  56.                 volumeControl.volume = Math.floor(continuousVolume)
  57.         } else {
  58.             volumeControl.volume = Math.ceil(continuousVolume)
  59.         }
  60.     }
  61.  
  62.     property color _foregroundColor: controllingMedia && (volumeControl.volume > volumeControl.safeVolume)
  63.                                     ? Theme.highlightDimmerColor
  64.                                     : Theme.primaryColor
  65.     property color _backgroundColor: controllingMedia && (volumeControl.volume > volumeControl.safeVolume)
  66.                                         ? Theme.primaryColor
  67.                                         : Theme.secondaryHighlightColor
  68.  
  69.     Behavior on _foregroundColor { ColorAnimation { } }
  70.     Behavior on _backgroundColor { ColorAnimation { } }
  71.  
  72.     // Place below other notifications
  73.     z: -1
  74.  
  75.     onControllingMediaChanged: {
  76.         keyRepeatDelay.stop
  77.         keyRepeat.stop()
  78.     }
  79.  
  80.     ProfileControl {
  81.         id: profileControl
  82.  
  83.         property bool modifying
  84.  
  85.         signal externalProfileChanged()
  86.  
  87.         function adjustRingtoneVolume(amount) {
  88.             modifying = true
  89.  
  90.             var effectiveVolume = (profile == "silent") ? 0 : ringerVolume
  91.             var newVolume = Math.max(Math.min(effectiveVolume + amount, 100), 0)
  92.             var newProfile = newVolume > 0 ? "general" : "silent"
  93.  
  94.             // in silent mode, avoid changing general profile level if decrease is requested
  95.             if (profile !== "silent" || newProfile !== "silent") {
  96.                 ringerVolume = newVolume
  97.             }
  98.  
  99.             if (newProfile != profile) {
  100.                 profile = newProfile
  101.                 if (newProfile === "silent") {
  102.                     silenceVibra.start()
  103.                 }
  104.             }
  105.  
  106.             modifying = false
  107.         }
  108.  
  109.         onProfileChanged: {
  110.             if (!modifying) {
  111.                 externalProfileChanged()
  112.             }
  113.         }
  114.     }
  115.  
  116.     ConfigurationValue {
  117.         id: forceMediaVolume
  118.         key: "/jolla/sound/force_mediavolume"
  119.         defaultValue: false
  120.     }
  121.  
  122.     HapticsEffect {
  123.         id: silenceVibra
  124.         intensity: 0.2
  125.         duration: 85
  126.     }
  127.  
  128.     Item {
  129.         id: volumeArea
  130.  
  131.         width: parent.width
  132.         height: Theme.iconSizeSmall + Theme.paddingMedium
  133.         y: -height
  134.  
  135.         Rectangle {
  136.             anchors.fill: parent
  137.             color: Theme.overlayBackgroundColor
  138.             opacity: 0.8
  139.         }
  140.  
  141.         Rectangle {
  142.             id: volumeRect
  143.  
  144.             objectName: "volumeRect"
  145.  
  146.             // On large screens display continuous volume changes
  147.             property real displayVolume: {
  148.                 if (!controllingMedia && profileControl.profile == "silent") {
  149.                     return 0
  150.                 }
  151.                 if (controllingMedia && volumeControl.callActive) {
  152.                     if (showContinuousVolume)
  153.                         return (continuousVolume+1) / (maximumVolume+1)
  154.                     else
  155.                         return (volumeControl.volume+1) / (volumeControl.maximumVolume+1)
  156.                 } else {
  157.                     if (showContinuousVolume)
  158.                         return continuousVolume / maximumVolume
  159.                     else if (controllingMedia)
  160.                         return volumeControl.volume / volumeControl.maximumVolume
  161.                     else
  162.                         return profileControl.ringerVolume / 100
  163.                 }
  164.             }
  165.  
  166.             property real widthFraction: displayVolume
  167.  
  168.             anchors {
  169.                 top: parent.top
  170.                 topMargin: Theme.paddingSmall/2
  171.                 bottom: parent.bottom
  172.                 bottomMargin: Theme.paddingSmall/2
  173.                 left: parent.left
  174.             }
  175.  
  176.             width: volumeArea.width * widthFraction
  177.  
  178.             Behavior on widthFraction {
  179.                 enabled: !showContinuousVolume && !disableSmoothChange
  180.                 NumberAnimation { easing.type: Easing.OutSine }
  181.             }
  182.  
  183.             color: _backgroundColor
  184.         }
  185.  
  186.         Item {
  187.             objectName: "volumeAnnotation"
  188.  
  189.             anchors.fill: parent
  190.  
  191.             property bool mute: controllingMedia
  192.                                 ? (!volumeControl.callActive && volumeControl.volume === 0)
  193.                                 : (profileControl.profile === "silent" || profileControl.ringerVolume === 0)
  194.             property real muteOpacity: mute ? 1 : 0
  195.             Behavior on muteOpacity {
  196.                 enabled: volumeBar.state != "" && volumeBar.state != "showBarExternal"
  197.                 FadeAnimation { property: "muteOpacity" }
  198.             }
  199.  
  200.             Image {
  201.                 id: muteIcon
  202.  
  203.                 anchors.verticalCenter: parent.verticalCenter
  204.                 x: Theme.horizontalPageMargin
  205.                 opacity: parent.muteOpacity
  206.  
  207.                 property string baseSource: controllingMedia ? "image://theme/icon-system-volume-mute" : "image://theme/icon-system-ringtone-mute"
  208.                 source: baseSource + "?" + _foregroundColor
  209.             }
  210.  
  211.             Image {
  212.                 id: volumeIcon
  213.  
  214.                 anchors.verticalCenter: parent.verticalCenter
  215.                 x: Theme.horizontalPageMargin
  216.                 opacity: 1 - parent.muteOpacity
  217.  
  218.                 property string baseSource: controllingMedia ? "image://theme/icon-system-volume" : "image://theme/icon-system-ringtone"
  219.                 source: baseSource + "?" + _foregroundColor
  220.             }
  221.  
  222.             Label {
  223.                 anchors {
  224.                     verticalCenter: parent.verticalCenter
  225.                     left: muteIcon.right
  226.                     leftMargin: Theme.paddingMedium
  227.                 }
  228.  
  229.                 font.pixelSize: Theme.fontSizeExtraSmall
  230.                 opacity: parent.muteOpacity
  231.                 color: _foregroundColor
  232.  
  233.                 //% "Muted"
  234.                 text: qsTrId("lipstick-jolla-home-la-muted")
  235.             }
  236.  
  237.             Label {
  238.                 anchors {
  239.                     verticalCenter: parent.verticalCenter
  240.                     left: volumeIcon.right
  241.                     leftMargin: Theme.paddingMedium
  242.                 }
  243.  
  244.                 font.pixelSize: Theme.fontSizeExtraSmall
  245.                 opacity: 1 - parent.muteOpacity
  246.                 color: _foregroundColor
  247.  
  248.                 text: {
  249.                     if (controllingMedia) {
  250.                         if (volumeControl.volume > volumeControl.safeVolume) {
  251.                             //% "High volume"
  252.                             return qsTrId("lipstick-jolla-home-la-high-volume")
  253.                         } else if (volumeControl.callActive && volumeControl.volume === 0) {
  254.                             //: Label used when minimum (unmuted) volume is set
  255.                             //% "Minimum"
  256.                             return qsTrId("lipstick-jolla-home-la-minimum-volume")
  257.                         } else {
  258.                             //% "Volume"
  259.                             return qsTrId("lipstick-jolla-home-la-volume")
  260.                         }
  261.                     } else {
  262.                         //% "Ringtone volume"
  263.                         return qsTrId("lipstick-jolla-home-la-ringtone_volume")
  264.                     }
  265.                 }
  266.             }
  267.         }
  268.     }
  269.  
  270.     states: [
  271.         State {
  272.             name: "showBar"
  273.             PropertyChanges {
  274.                 target: volumeArea
  275.                 y: 0
  276.             }
  277.         },
  278.         State {
  279.             name: "showBarKey"
  280.             extend: "showBar"
  281.             PropertyChanges {
  282.                 target: volumeBar
  283.                 disableSmoothChange: false
  284.             }
  285.             PropertyChanges {
  286.                 target: volumeRect
  287.                 widthFraction: volumeRect.displayVolume
  288.             }
  289.         },
  290.         State {
  291.             name: "showBarGesture"
  292.             extend: "showBar"
  293.             PropertyChanges {
  294.                 target: volumeBar
  295.                 showContinuousVolume: Screen.sizeCategory >= Screen.Large
  296.             }
  297.         },
  298.         State {
  299.             name: "showBarExternal"
  300.             extend: "showBar"
  301.             PropertyChanges {
  302.                 target: volumeBar
  303.                 controllingMedia: false
  304.                 showContinuousVolume: false
  305.             }
  306.         }
  307.     ]
  308.  
  309.     transitions: [
  310.         Transition {
  311.             from: ""
  312.             to: "showBarKey"
  313.             SequentialAnimation {
  314.                 ScriptAction {
  315.                     script: {
  316.                         volumeRect.widthFraction = volumeRect.displayVolume + initialChange
  317.                     }
  318.                 }
  319.                 NumberAnimation {
  320.                     target: volumeArea
  321.                     property: "y"
  322.                     duration: 200
  323.                     easing.type: Easing.OutQuad
  324.                 }
  325.                 NumberAnimation {
  326.                     target: volumeRect
  327.                     property: "widthFraction"
  328.                     easing.type: Easing.OutSine
  329.                 }
  330.                 PropertyAction {
  331.                     target: volumeBar
  332.                     property: "disableSmoothChange"
  333.                 }
  334.                 ScriptAction { script: hideTimer.restart() }
  335.             }
  336.         },
  337.         Transition {
  338.             from: ""
  339.             to: "showBarGesture"
  340.             SequentialAnimation {
  341.                 PropertyAction {
  342.                     target: volumeBar
  343.                     property: "showContinuousVolume"
  344.                 }
  345.                 NumberAnimation {
  346.                     target: volumeArea
  347.                     property: "y"
  348.                     duration: 200
  349.                     easing.type: Easing.OutQuad
  350.                 }
  351.                 ScriptAction { script: hideTimer.restart() }
  352.             }
  353.         },
  354.         Transition {
  355.             from: ""
  356.             to: "showBarExternal"
  357.             SequentialAnimation {
  358.                 PauseAnimation {
  359.                     duration: 150
  360.                 }
  361.                 NumberAnimation {
  362.                     target: volumeArea
  363.                     property: "y"
  364.                     duration: 300
  365.                     easing.type: Easing.InOutQuad
  366.                 }
  367.                 ScriptAction { script: hideTimer.restart() }
  368.             }
  369.         },
  370.         Transition {
  371.             to: ""
  372.             SequentialAnimation {
  373.                 NumberAnimation {
  374.                     target: volumeArea
  375.                     property: "y"
  376.                     duration: 200
  377.                     easing.type: Easing.OutQuad
  378.                 }
  379.                 PropertyAction {
  380.                     target: volumeBar
  381.                     properties: "disableSmoothChange, showContinuousVolume"
  382.                 }
  383.                 PropertyAction {
  384.                     target: volumeRect
  385.                     property: "widthFraction"
  386.                 }
  387.                 ScriptAction {
  388.                     script: {
  389.                         volumeControl.windowVisible = false
  390.                         if (lateScreenshotCapture) {
  391.                             if (!screenshot) {
  392.                                 var component = Qt.createComponent(Qt.resolvedUrl("Screenshot.qml"))
  393.                                 if (component.status == Component.Ready) {
  394.                                     screenshot = component.createObject(volumeBar)
  395.                                 } else {
  396.                                     console.warn("Screenshot object instantiation failed:", component.errorString())
  397.                                 }
  398.                             }
  399.                             if (screenshot) {
  400.                                 screenshot.capture()
  401.                             }
  402.                         }
  403.                         lateScreenshotCapture = false
  404.                     }
  405.                 }
  406.             }
  407.         }
  408.     ]
  409.  
  410.     Loader {
  411.         id: loader
  412.  
  413.         function showWarning(initial) {
  414.             loader.source = "WarningNote.qml"
  415.             loader.item.initial = initial
  416.             loader.item.opacity = 1.0
  417.             hideTimer.stop()
  418.         }
  419.  
  420.         anchors {
  421.             top: volumeArea.bottom
  422.             bottom: parent.bottom
  423.             left: parent.left
  424.             right: parent.right
  425.         }
  426.  
  427.         Connections {
  428.             target: loader.item
  429.             onOpacityChanged: {
  430.                 if (loader.item.opacity <= 0.0) {
  431.                     loader.source = ""
  432.                     hideTimer.restart()
  433.                 }
  434.             }
  435.         }
  436.     }
  437.  
  438.     Timer {
  439.         id: hideTimer
  440.         interval: 1500
  441.         onTriggered: {
  442.             if (!Lipstick.compositor.volumeGestureFilterItem.active)
  443.                 volumeBar.state = ""
  444.         }
  445.     }
  446.  
  447.     Timer {
  448.         id: keyRepeatDelay
  449.         interval: 600
  450.         onTriggered: keyRepeat.start()
  451.     }
  452.  
  453.     Timer {
  454.         id: keyRepeat
  455.         interval: volumeBar.controllingMedia ? 75 : 300
  456.         repeat: true
  457.         onTriggered: {
  458.             if (volumeBar.controllingMedia) {
  459.                 if (volumeIncreasing)
  460.                     mprisManager.previous()
  461.                 else
  462.                     mprisManager.next()
  463.                 keyRepeat.stop()
  464.                 keyRepeatDelay.stop()
  465.                 initialChange = 0
  466.             } else {
  467.                 profileControl.adjustRingtoneVolume(volumeBar.volumeIncreasing ? 20 : -20)
  468.             }
  469.  
  470.             restartHideTimerIfWindowVisibleAndWarningNotVisible()
  471.         }
  472.     }
  473.  
  474.     Connections {
  475.         target: volumeControl
  476.         onWindowVisibleChanged: {
  477.             if (volumeControl.windowVisible) {
  478.                 if (volumeBar.state == "") {
  479.                     if (Lipstick.compositor.volumeGestureFilterItem.active) {
  480.                         volumeBar.state = "showBarGesture"
  481.                     } else {
  482.                         volumeBar.state = "showBarKey"
  483.                         hideTimer.restart()
  484.                     }
  485.                 }
  486.             }
  487.         }
  488.         onVolumeChanged: restartHideTimerIfWindowVisibleAndWarningNotVisible()
  489.         onVolumeKeyPressed: {
  490.             if (keyRepeat.running || keyRepeatDelay.running) {
  491.                 if (Lipstick.compositor.visible) {
  492.                     screenshotTimer.restart()
  493.                 }
  494.                 return
  495.             }
  496.  
  497.             volumeBar.volumeIncreasing = (key == Qt.Key_VolumeUp)
  498.  
  499.             if (volumeBar.controllingMedia) {
  500.                 initialChange = 0
  501.                 baseVolume = volumeControl.volume
  502.                 keyRepeat.stop()
  503.                 keyRepeatDelay.restart()
  504.             } else {
  505.                 if (volumeControl.windowVisible) {
  506.                     if (volumeIncreasing)
  507.                         initialChange = profileControl.ringerVolume === 100 ? 0 : -0.2
  508.                     else
  509.                         initialChange = profileControl.ringerVolume === 0 ? 0 : 0.2
  510.  
  511.                     profileControl.adjustRingtoneVolume(volumeBar.volumeIncreasing ? 20 : -20)
  512.                 } else {
  513.                     initialChange = 0
  514.                 }
  515.  
  516.                 keyRepeat.restart() // no initial delay
  517.             }
  518.  
  519.             volumeBar.state = "showBarKey"
  520.             volumeControl.windowVisible = true
  521.             restartHideTimerIfWindowVisibleAndWarningNotVisible()
  522.         }
  523.         onVolumeKeyReleased: {
  524.             initialChange = 0
  525.             if (volumeBar.controllingMedia)
  526.                 keyRepeat.stop()
  527.                 keyRepeatDelay.stop()
  528.                 if (volumeIncreasing)
  529.                     initialChange = volumeControl.volume === volumeControl.maximumVolume ? 0 : -1 / (volumeControl.maximumVolume+1)
  530.                 else
  531.                     initialChange = volumeControl.volume === 0 ? 0 : 1 / (volumeControl.maximumVolume+1)
  532.                 volumeControl.volume = volumeControl.volume + (volumeBar.volumeIncreasing ? 1 : -1)
  533.                
  534.             if (volumeBar.volumeIncreasing == (key == Qt.Key_VolumeUp)) {
  535.                 // Handle pressing both buttons and releasing the first, though
  536.                 // in that case keyRepeat is probably already stopped by screenshotTimer
  537.                 keyRepeat.stop()
  538.                 keyRepeatDelay.stop()
  539.             }
  540.             screenshotTimer.stop()
  541.             lateScreenshotCapture = false
  542.         }
  543.         onShowAudioWarning: loader.showWarning(initial)
  544.     }
  545.  
  546.     Connections {
  547.         target: Lipstick.compositor.volumeGestureFilterItem
  548.         onActiveChanged: {
  549.             if (Lipstick.compositor.volumeGestureFilterItem.active) {
  550.                 if (!volumeControl.windowVisible)
  551.                     baseVolume = continuousVolume
  552.                 volumeBar.state = "showBarGesture"
  553.                 volumeControl.windowVisible = true
  554.                 hideTimer.stop()
  555.             } else {
  556.                 baseVolume = continuousVolume
  557.                 restartHideTimerIfWindowVisibleAndWarningNotVisible()
  558.             }
  559.         }
  560.     }
  561.  
  562.     Connections {
  563.         target: profileControl
  564.         onExternalProfileChanged: {
  565.             if (profileControl.profile != "silent" && recentSoundOnFromPulldown.active) {
  566.                 volumeBar.state = "showBarExternal"
  567.                 volumeControl.windowVisible = true
  568.                 restartHideTimerIfWindowVisibleAndWarningNotVisible()
  569.             }
  570.         }
  571.     }
  572.  
  573.     Timer {
  574.         id: screenshotTimer
  575.         interval: 200
  576.         onTriggered: {
  577.             lateScreenshotCapture = true
  578.             keyRepeat.stop()
  579.             keyRepeatDelay.stop()
  580.             initialChange = 0
  581.             if (volumeBar.controllingMedia)
  582.                 baseVolume = volumeControl.volume
  583.             volumeBar.volumeIncreasing = false
  584.             volumeBar.state = ""
  585.         }
  586.     }
  587.  
  588.     function restartHideTimerIfWindowVisibleAndWarningNotVisible() {
  589.         if (volumeControl.windowVisible && loader.source == "" && !Lipstick.compositor.volumeGestureFilterItem.active) {
  590.             hideTimer.restart()
  591.         }
  592.     }
  593. }
Add Comment
Please, Sign In to add comment