This file is indexed.

/usr/lib/x86_64-linux-gnu/qt5/qml/Ubuntu/Components/1.3/Panel.qml is in qml-module-ubuntu-components 1.3.1918+16.04.20160404-0ubuntu1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
/*
 * Copyright (C) 2015 Canonical Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; version 3.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

import QtQuick 2.4
import Ubuntu.Components 1.3 as Toolkit

/*!
    \qmltype Panel
    \inqmlmodule Ubuntu.Components 1.1
    \ingroup ubuntu
    \brief A panel that can be swiped in and out from an edge of the window by the user.
    For most applications, it is highly recommended to use the \l MainView instead which includes
    a toolbar at its bottom that can be swiped in or out.

    Unless your application has very specific needs for a Panel, use a \l MainView with the
    default toolbar.

    When using a Panel, do not theme it directly, but theme its contents, because
    the Panel itself should not have visible elements, since it is
    in the view (to detect mouse events) even when its contents should be invisible.

    Set the anchors and/or width/height of the Panel to specify the area that the Panel covers when
    opened.

    A black panel that can be swiped in from the lower-right of the window can be created like this:
    \qml
        import QtQuick 2.4
        import Ubuntu.Components 1.3

        Item {
            width: units.gu(80)
            height: units.gu(80)

            Panel {
                id: panel
                anchors {
                    right: parent.right
                    bottom: parent.bottom
                }
                width: parent.width / 2
                height: units.gu(8)

                Rectangle {
                    anchors.fill: parent
                    color: theme.palette.normal.overlay

                    Button {
                        anchors.centerIn: parent
                        text: "Click"
                    }
                }
            }
        }
    \endqml

    A panel that looks like the standard (bottom-aligned) toolbar, but with custom contents, can be created like this:
    \qml
        import QtQuick 2.4
        import Ubuntu.Components 1.3

        Item {
            width: units.gu(80)
            height: units.gu(80)

            Panel {
                id: panel
                anchors {
                    left: parent.left
                    right: parent.right
                    bottom: parent.bottom
                }
                height: units.gu(8)

                Item {
                    anchors.fill: parent

                    // two properties used by the toolbar delegate:
                    property bool opened: panel.opened
                    property bool animating: panel.animating

                    Button {
                        anchors.centerIn: parent
                        text: "Click"
                    }
                }
            }
        }
    \endqml

    Any Items can be placed inside the Panel, but MouseAreas can block mouse events from reaching
    the panel and thus obstruct the swiping behavior for hiding the panel. As a result, the user cannot
    start swiping on the buttons in the examples above in order to hide the panel. To remedy this, clicked()
    signals are forwarded from the panel by calling the child's trigger() function. Example:
    \qml
        import QtQuick 2.4
        import Ubuntu.Components 1.3

        Rectangle {
            color: theme.palette.normal.background
            width: units.gu(40)
            height: units.gu(40)

            Panel {
                id: panel
                anchors {
                    left: parent.left
                    right: parent.right
                    bottom: parent.bottom
                }
                height: units.gu(8)

                Rectangle {
                    color: theme.palette.normal.overlay
                    anchors.fill: parent
                    Rectangle {
                        width: units.gu(8)
                        height: units.gu(4)
                        anchors.centerIn: parent
                        color: "red"
                        function trigger() {
                            print("The red rectangle was clicked");
                        }
                    }
                }
            }
            Component.onCompleted: panel.open();
        }
    \endqml
    Like this, the red rectangle accepts click events, but the user can still swipe down on top
    of the rectangle in order to hide the panel.
*/
Item {
    id: panel

    /*!
      Default property, holds the content which will be swiped in and out.
      \qmlproperty list<Object> contents
     */
    default property alias contents: bar.data

    /*!
      The property defines the alignment of the panel.
      The implementation supports the following values:
        \list
        \li Qt.AlignBottom to swipe in the panel from the bottom (default)
        \li Qt.AlignTop to swipe in the panel from the top
        \li Qt.AlignLeft to swipe in the panel from the left
        \li Qt.AlignRight to swipe in the panel from the right
        \li Qt.AlignLeading left when layout mirrorring is disabled, right otherwise
        \li Qt.AlignTrailing right when layout mirroring is disabled, left otherwise
        \endlist
        The default value is \b Qt.AlignBottom, and it is not recommended to change the
        default value because the left, right and top edge are already used for system
        functions, while the bottom edge is reserved for app-specific functionality
        such as a default toolbar. The use of Qt.AlignLeading and Qt.AlignTrailing is
        preferred over Qt.AlignLeft and Qt.AlignRight in order to more easily support
        right-to-left user interfaces that use LayoutMirroring.
      */
    property int align: Qt.AlignBottom

    /*!
      When opened, the panel is visible, otherwise it is hidden.
      Use edge swipes to open/close the panel.
      The opened property is not updated until the swipe gesture is completed.
     */
    // opened is true if state is spread, or if state is moving/hint and the previous state was spread.
    property bool opened: (panel.state === "spread") ||
                          (panel.state === "moving" && internal.previousState === "spread")
    /*! \internal */
    // FIXME: When opened is made read-only, onOpenedChanged can be removed entirely.
    onOpenedChanged: {
        if (internal.openedChangedWarning) {
            console.log("DEPRECATED use of Panel.opened property. This property will be made read-only,
                please use the opened property of the Page tools or use Panel.open() and Panel.close().");

            if (opened) {
                panel.open();
            } else {
                panel.close();
            }

            // re-establish the previous binding for opened.
            panel.opened = Qt.binding(function() {
                return (panel.state === "spread") ||
                        (panel.state === "moving" && internal.previousState === "spread");
            })
        }

        internal.openedChangedWarning = true;
    }

    /*!
      Open the panel
     */
    function open() {
        // FIXME: When opened is made readonly, openedChangedWarning must be removed
        internal.openedChangedWarning = false;
        panel.state = "spread";
        hideTimer.conditionalRestart();
    }

    /*!
      Close the panel
     */
    function close() {
        // FIXME: When opened is made readonly, openedChangedWarning must be removed.
        internal.openedChangedWarning = false;
        panel.state = "";
        hideTimer.stop();
    }

    /*!
      The time in milliseconds before the panel automatically hides after inactivity
      when it is not locked. Interacting with the panel resets the timer.
      Note that adding contents to the panel that accepts mouse events will prevent
      the panel from detecting interaction and the timer will not be reset.
      Setting a negative value will disable automatic hiding.
      Default value: -1 (automatic hiding is disabled).
      \qmlproperty int hideTimeout
     */
    property alias hideTimeout: hideTimer.interval

    /*!
      Disable edge swipe to open/close the panel. False by default.
     */
    property bool locked: false
    /*! \internal */
    onLockedChanged: {
        if (state == "hint" || state == "moving") {
            draggingArea.finishMoving();
        }
        if (!hideTimer.conditionalRestart()) {
            hideTimer.stop();
        }
    }

    Timer {
        id: hideTimer
        interval: -1
        running: panel.opened && !panel.locked && interval >= 0

        function conditionalRestart() {
            if (hideTimer.interval >= 0) {
                if (!panel.locked && panel.opened) {
                    hideTimer.restart();
                    return true;
                }
            }
            return false;
        }
        onIntervalChanged: {
            if (!conditionalRestart()) {
                hideTimer.stop();
            }
        }
        onTriggered: {
            if (!panel.locked) {
                panel.close();
            }
        }
    }
    // disable the timer when the application is not active to avoid closing
    //  the panel immediately after the application becomes active again
    Connections {
        target: Qt.application
        onActiveChanged: {
            if (Qt.application.active) {
                hideTimer.conditionalRestart();
            } else {
                hideTimer.stop();
            }
        }
    }

    /*!
      How much of the panel to show when the user touches the panel's edge.
      This gives the user a hint that there is a panel hiding at that edge and
      invites him/her to swipe to show the panel completely. Default value: units.gu(2).
     */
    property real hintSize: units.gu(2)

    /*!
      The size (height for top or bottom-aligned panels, width for left or right-aligned
      panels) of the mouse area used to detect edge swipes to open the panel, when
      the panel is not opened. Default value: units.gu(2).
     */
    property real triggerSize: units.gu(2)

    /*!
      \qmlproperty real position
      The current position of the edge of the panel. The value is 0 when the panel is
      opened, and has its maximum value when the panel is closed. The maximum value is the
      width of the Panel for a left or right-aligned panel, and the height of the panel for
      top or bottom-aligned panels. When the user drags the Panel from the edge to open it,
      the position will change from the maximum size (closed) to 0 (fully expanded).
     */
    readonly property alias position: bar.position

    states: [
        State {
            name: "hint"
            PropertyChanges {
                target: bar
                position: bar.size - panel.hintSize
            }
        },
        State {
            name: "moving"
            PropertyChanges {
                target: bar
                position: Toolkit.MathUtils.clamp(draggingArea.mousePosition - internal.movingDelta, 0, bar.size)
            }
        },
        State {
            name: "spread"
            PropertyChanges {
                target: bar
                position: 0
            }
        },
        State {
            name: ""
            PropertyChanges {
                target: bar
                position: bar.size
                explicit: true
            }
        }
    ]

    /*!
      Animate transitions between the different panel states.
     */
    property bool animate: true

    /*!
      The toolbar is currently not in a stable hidden or visible state.
     */
    readonly property bool animating: draggingArea.pressed || transitionToAll.running
                                                           || transitionToHint.running
                                                           || transitionToSpread.running

    transitions: [
        Transition {
            id: transitionToAll
            to: ""
            UbuntuNumberAnimation {
                target: bar
                properties: "position"
                duration: internal.transitionDuration
            }
        },
        Transition {
            id: transitionToHint
            to: "hint"
            UbuntuNumberAnimation {
                target: bar
                properties: "position"
                duration: internal.transitionDuration
            }
        },
        Transition {
            id: transitionToSpread
            to: "spread"
            UbuntuNumberAnimation {
                target: bar
                properties: "position"
                duration: internal.transitionDuration
            }
        },
        Transition {
            id: transitionToMoving
            to: "moving"
            UbuntuNumberAnimation {
                target: bar
                properties: "position"
                duration: panel.animate ? Toolkit.UbuntuAnimation.SnapDuration : 0
            }
        }
    ]

    QtObject {
        id: internal

        // FIXME: Remove when opened property is made readonly
        property bool openedChangedWarning: true

        /*!
          The duration in milliseconds of sliding in or out transitions when opening, closing, and showing the hint.
          Default value: 250
         */
        property real transitionDuration: panel.animate ? Toolkit.UbuntuAnimation.FastDuration : 0

        property string previousState: ""
        property int movingDelta

        // Convert from Qt.AlignLeading to Qt.AlignTrailing to Qt.AlignLeft and Qt.AlignRight
        property int align: {
            if (panel.align === Qt.AlignLeading) {
                if (panel.LayoutMirroring.enabled) {
                    return Qt.AlignRight;
                } else {
                    return Qt.AlignLeft;
                }
            } else if (panel.align === Qt.AlignTrailing) {
                if (panel.LayoutMirroring.enabled) {
                    return Qt.AlignLeft;
                } else {
                    return Qt.AlignRight;
                }
            } else {
                return panel.align;
            }
        }

        readonly property int orientation: (panel.align === Qt.AlignTop || panel.align === Qt.AlignBottom)
                                           ? Qt.Horizontal : Qt.Vertical
    }

    /*! \internal */
    onStateChanged: {
        if (state == "hint") {
            internal.movingDelta = panel.hintSize + draggingArea.initialPosition - bar.size;
        } else if (state == "moving" && internal.previousState == "spread") {
            internal.movingDelta = draggingArea.initialPosition;
        }
    }

    /*!
      \internal
      \deprecated
      Enable the InverseMouseArea that closes the panel when the user clicks outside of the panel.
      This functionality moved to the MainView to deal with Toolbar hiding, but this InverseMouseArea
      is still in the Panel for backwards compatibility in apps that use it directly.
      Default value is false.

      FIXME: Remove __closeOnContentsClicks and the IMA below when all apps use Toolbar instead of Panel.
     */
    property bool __closeOnContentsClicks: false
    Toolkit.InverseMouseArea {
        anchors.fill: draggingArea
        onPressed: {
            mouse.accepted = false;
            // the mouse click may cause an update
            //  of locked by the clicked Item behind
            if (!panel.locked) panel.close();
        }
        propagateComposedEvents: true
        visible: panel.__closeOnContentsClicks && panel.locked == false && panel.state == "spread"
    }

    /*!
      \internal
      \deprecated
      Enable automatic reveal of panel on mouse hover over hint area, and hide when leaving
      the panel area. This is disabled by default, because Panel may be used to implement
      bottom edge behaviors that are completely different from the toolbar, but the property
      is enabled in Toolbar to make more usable on desktop.
     */
    property bool __openOnHover: false

    /*!
      The user presses on the opened toolbar, or when the toolbar is closed but
      not locked, the user presses in the toolbar trigger area.
      \qmlproperty bool pressed
     */
    // This is a simple alias to draggingArea.pressed, but the documentation is accurate
    // because of the visible definition of draggingArea. Pressed is false when draggingArea
    // is not visible.
    property alias pressed: draggingArea.pressed

    DraggingArea {
        id: draggingArea
        orientation: internal.orientation === Qt.Horizontal ? Qt.Vertical : Qt.Horizontal
        zeroVelocityCounts: true
        anchors {
            top: panel.align === Qt.AlignBottom ? undefined : parent.top
            bottom: panel.align === Qt.AlignTop ? undefined : parent.bottom
            left: panel.align === Qt.AlignRight || panel.align === Qt.AlignTrailing ? undefined : parent.left
            right: panel.align === Qt.AlignLeft || panel.align === Qt.AlignLeading ? undefined : parent.right
        }
        height: internal.orientation === Qt.Horizontal ? panel.opened ? bar.size + units.gu(1) : panel.triggerSize : undefined
        width: internal.orientation === Qt.Vertical ? panel.opened ? bar.size + units.gu(1) : panel.triggerSize : undefined
        visible: !panel.locked || panel.opened
        hoverEnabled: panel.__openOnHover

        property int mousePosition: getMousePosition()
        function getMousePosition() {
            switch (internal.align) {
            case Qt.AlignLeft:
                return -mouseX;
            case Qt.AlignRight:
                return mouseX;
            case Qt.AlignBottom:
                return mouseY;
            case Qt.AlignTop:
                return -mouseY;
            }
        }

        // set in onPressed, reset when entering "moving" state
        property Item pressedItem: null

        // find the first child with a triggered property:
        function getTriggerableItem(mouse) {
            var item = bar; // contains the children
            while (item && !item.hasOwnProperty("trigger")) {
                var coords = mapToItem(item, mouse.x, mouse.y);
                // FIXME: When using a ListView the highlight may be
                //  returned instead of the Item that you are looking for
                item = item.childAt(coords.x, coords.y);
            }
            return item; // will be null if no item has trigger() function.
        }

        // forward trigger() events to any child Item with trigger() function.
        // This must also happen when the panel is locked, so the DraggingArea is
        // never disabled, and other signal handlers will return when panel.locked is true.
        onClicked: {
            if (pressedItem && pressedItem === getTriggerableItem(mouse)) {
                // Click event positioned at the Item where the user first pressed
                pressedItem.trigger();
            }
        }

        property int initialPosition
        onPressed: {
            hideTimer.stop();
            pressedItem = getTriggerableItem(mouse);
            if (panel.locked) return;
            initialPosition = getMousePosition();
            if (panel.state == "") panel.state = "hint";
        }

        /*!
          The minimum amount of movement while pressed before switching to "moving" state.
          This threshold is needed to avoid detecting unintentional small movements while
          "clicking" as a drag.
          */
        property real dragThreshold: units.gu(1)

        onPositionChanged: {
            if (!pressed) return;
            if (panel.locked) return;
            if (panel.state == "hint" && mousePosition < initialPosition - dragThreshold) {
                internal.previousState = "hint";
                panel.state = "moving";
                pressedItem = null;
            } else if (panel.state == "spread" && mousePosition > initialPosition + dragThreshold) {
                internal.previousState = "spread";
                panel.state = "moving";
                pressedItem = null;
            }
        }

        onReleased: {
            if (panel.state == "moving" || panel.state == "hint") {
                finishMoving();
            } else {
                hideTimer.conditionalRestart();
            }
        }
        // Mouse cursor moving out of the window while pressed on desktop
        onCanceled: {
            if (panel.state == "moving" || panel.state == "hint") {
                finishMoving();
            } else {
                hideTimer.conditionalRestart();
            }
        }

        onEntered: {
            if (panel.__openOnHover) {
                panel.open();
            }
            hideTimer.stop();
        }

        onExited: {
            // panel.__openOnHover
            // Ensure the panel is not still opening. The draggingArea will
            // change after the panel finishes the opening animation.
            if (!animating) {
                hideTimer.conditionalRestart();
            }
        }

        // FIXME: Make all parameters below themable and resolution-independent.
        //  The value of 44 was copied from the Launcher.
        function finishMoving() {
            if (draggingArea.dragVelocity < -44) {
                if (internal.align === Qt.AlignBottom || internal.align === Qt.AlignRight) {
                    panel.open();
                } else {
                    panel.close();
                }
            } else if (draggingArea.dragVelocity > 44) {
                if (internal.align === Qt.AlignBottom || internal.align === Qt.AlignRight) {
                    panel.close();
                } else {
                    panel.open();
                }
            } else {
                if (bar.position < bar.size / 2) {
                    panel.open();
                } else {
                    panel.close();
                }
            }
        }
    }

    Item {
        id: bar
        objectName: "bar_item"
        height: parent.height
        width: parent.width
        anchors {
            left: internal.orientation === Qt.Horizontal ? parent.left : undefined
            right: internal.orientation === Qt.Horizontal ? parent.right : undefined
            top: internal.orientation === Qt.Vertical ? parent.top : undefined
            bottom: internal.orientation === Qt.Vertical ? parent.bottom : undefined
        }

        property real size: internal.orientation === Qt.Horizontal ? height : width
        //position will always be in the range 0..size, where position==0 means spread, position==size means hidden.
        property real position: panel.opened ? 0 : size
        onSizeChanged: position = panel.opened ? 0 : size

        y: internal.align === Qt.AlignTop ? -position : internal.align === Qt.AlignBottom ? position : 0
        x: internal.align === Qt.AlignLeft ? -position : internal.align === Qt.AlignRight ? position : 0
    }
}