~sil2100/unity-2d/precise-security

« back to all changes in this revision

Viewing changes to launcher/Application.qml

  • Committer: Aurelien Gateau
  • Date: 2010-11-10 08:57:29 UTC
  • mto: This revision was merged to the branch mainline in revision 284.
  • Revision ID: aurelien.gateau@canonical.com-20101110085729-fl1ye7impkqhm0w6
Added a section about const correct-ness

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * This file is part of unity-2d
3
 
 *
4
 
 * Copyright 2010-2011 Canonical Ltd.
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or modify
7
 
 * it under the terms of the GNU General Public License as published by
8
 
 * the Free Software Foundation; version 3.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 
 */
18
 
 
19
 
import QtQuick 1.1
20
 
import Unity2d 1.0
21
 
 
22
 
/* This component represents a single "tile" in the launcher and the surrounding
23
 
   indicator icons.
24
 
 
25
 
   The tile is square in size, with a side determined by the 'tileSize' property,
26
 
   and rounded borders.
27
 
   It is composed by a colored background layer, an icon (with 'icon' as source),
28
 
   and a layer on top that provides a "shine" effect.
29
 
   The main color of the background layer may be calculated based on the icon color
30
 
   or may be fixed (depending on the 'backgroundFromIcon' property).
31
 
 
32
 
   There's also an additional layer which contains only the outline of the tile
33
 
   that is only appearing during the launching animation (when the 'launching' property is
34
 
   true). During this animation the background fades out and the outline fades in,
35
 
   giving a "pulsing" appearance to the tile.
36
 
 
37
 
   Around the tile we may have on the left a number of "pips" between zero and three.
38
 
   Pips are small icons used to indicate how many windows we have open for the current tile
39
 
   (based on the 'windowCount' property).
40
 
   The rule is: if there's only one window, we just display an arrow. If there are
41
 
   two we display 2 pips, if there are 3 or more display 3 pips.
42
 
 
43
 
   On the right of the tile there's an arrow that appears if the tile is currently 'active'.
44
 
 
45
 
   Additionally, when the tile is marked as 'urgent' it will start an animation where the
46
 
   rotation is changed so that it appears to be "shaking".
 
1
import Qt 4.7
 
2
 
 
3
/* Item displaying an application.
 
4
 
 
5
   It contains:
 
6
    - a generic bordered background image
 
7
    - an icon representing the application
 
8
    - a text describing the application
 
9
 
 
10
   When an application is launched, the border changes appearance.
 
11
   It supports mouse hover by changing the appearance of the background image.
 
12
 
 
13
   The 'icon' property holds the source of the image to load as an icon.
 
14
   The 'label' property holds the text to display.
 
15
   The 'running' property is a boolean indicating whether or not the
 
16
   application is launched.
 
17
 
 
18
   The 'clicked' signal is emitted upon clicking on the item.
47
19
*/
48
 
DropItem {
49
 
    id: item
50
 
 
51
 
    Accessible.role: Accessible.PushButton
52
 
 
53
 
    anchors.horizontalCenter: parent.horizontalCenter
54
 
 
55
 
    height: selectionOutlineSize
56
 
 
57
 
    property bool isBfb: false
58
 
    property int tileSize
59
 
    property int selectionOutlineSize
60
 
    property alias name: looseItem.objectName
61
 
    property string desktopFile: ""
 
20
Item {
62
21
    property alias icon: icon.source
63
 
    property alias urgentAnimation: urgentAnimation
 
22
    property alias label: label.text
64
23
    property bool running: false
65
24
    property bool active: false
66
25
    property bool urgent: false
 
26
    property bool sticky: false
67
27
    property bool launching: false
68
 
    property alias interactive: mouse.enabled
69
 
 
70
 
    property int counter: 0
71
 
    property bool counterVisible: false
72
 
    property real progress: 0.0
73
 
    property bool progressBarVisible: false
74
 
    property alias emblem: emblemIcon.source
75
 
    property bool emblemVisible: false
76
 
 
77
 
    property bool backgroundFromIcon
78
 
    property color defaultBackgroundColor: "#333333"
79
 
    property color selectedBackgroundColor: "#dddddd"
80
 
 
81
 
    property alias shortcutVisible: shortcut.visible
82
 
    property alias shortcutText: shortcutText.text
83
 
 
84
 
    property bool isBeingDragged: false
85
 
    property int dragPosition
86
 
 
87
 
    property int pips: 0
88
 
    property string pipSource: "launcher/artwork/launcher_" +
89
 
                               ((pips <= 1) ? "arrow" : "pip") + "_ltr.png"
90
 
    function getPipOffset(index) {
91
 
        /* Pips need to always be centered, regardless if they are an even or odd
92
 
           number. The following simple conditional code works and is less
93
 
           convoluted than a generic formula. It's ok since we always work with at
94
 
           most three pips anyway. */
95
 
        if (pips == 1) return 0
96
 
        if (pips == 2) return (index == 0) ? -2 : +2
97
 
        else return (index == 0) ? 0 : (index == 1) ? -4 : +4
98
 
    }
99
 
 
100
 
    function isRightToLeft() {
101
 
        return Qt.application.layoutDirection == Qt.RightToLeft
102
 
    }
103
28
 
104
29
    signal clicked(variant mouse)
105
 
    signal pressed(variant mouse)
106
30
    signal entered
107
31
    signal exited
108
32
 
 
33
    MouseArea {
 
34
        id: mouse
 
35
 
 
36
        acceptedButtons: Qt.LeftButton | Qt.RightButton
 
37
        hoverEnabled: true
 
38
        anchors.fill: parent
 
39
        onClicked: parent.clicked(mouse)
 
40
        onEntered: parent.entered()
 
41
        onExited: parent.exited()
 
42
    }
 
43
 
 
44
    Keys.onPressed: {
 
45
        if (event.key == Qt.Key_Return) {
 
46
            clicked()
 
47
            event.accepted = true;
 
48
        }
 
49
    }
 
50
 
 
51
    Image {
 
52
        id: shadow
 
53
 
 
54
        source: "artwork/shadow.png"
 
55
        asynchronous: true
 
56
    }
 
57
 
 
58
    Image {
 
59
        id: glow
 
60
 
 
61
        anchors.horizontalCenter: parent.horizontalCenter
 
62
        anchors.verticalCenter: parent.verticalCenter
 
63
 
 
64
        source: "artwork/glow.png"
 
65
        asynchronous: true
 
66
        opacity: 0.0
 
67
 
 
68
        SequentialAnimation on opacity {
 
69
            loops: Animation.Infinite
 
70
            alwaysRunToEnd: true
 
71
            running: launching
 
72
            NumberAnimation { to: 1.0; duration: 1000; easing.type: Easing.InOutQuad }
 
73
            NumberAnimation { to: 0.0; duration: 1000; easing.type: Easing.InOutQuad }
 
74
        }
 
75
    }
 
76
 
109
77
    Item {
110
 
        /* The actual item, reparented so its y coordinate can be animated. */
111
 
        id: looseItem
112
 
        LayoutMirroring.enabled: isRightToLeft()
113
 
        LayoutMirroring.childrenInherit: true
114
 
        parent: list
115
 
        width: item.width
116
 
        height: item.height
117
 
        x: item.x
118
 
        y: -item.ListView.view.contentY + item.y
119
 
        /* The item is above the list's contentItem.
120
 
           Top and bottom gradients, ListViewDragAndDrop and autoscroll areas
121
 
           are above the item */
122
 
        z: list.contentItem.z + 1
123
 
 
124
 
        /* Bind to the scale of the delegate so that it is animated upon insertion/removal */
125
 
        scale: item.scale
126
 
 
127
 
        /* The y coordinate is initially not animated, as it would result in an
128
 
           unwanted effect of every single item popping out from the top of the
129
 
           launcher (even when they are supposed to be coming from the bottom).
130
 
           This property is later set to true once the item has taken its
131
 
           initial position. */
132
 
        property bool animateY: false
133
 
 
134
 
        /* This is the arrow shown at the right of the tile when the application is
135
 
           the active one */
136
 
        Image {
137
 
            objectName: "active"
138
 
            anchors.right: parent.right
139
 
            y: item.height - item.selectionOutlineSize / 2 - height / 2
140
 
            mirror: isRightToLeft()
141
 
 
142
 
            source: "image://blended/%1color=%2alpha=%3"
143
 
                  .arg("launcher/artwork/launcher_arrow_rtl.png")
144
 
                  .arg("lightgrey")
145
 
                  .arg(1.0)
146
 
 
147
 
            visible: active && (looseItem.state != "beingDragged")
148
 
        }
149
 
 
150
 
        /* This is the area on the left of the tile where the pips/arrow end up.
151
 
 
152
 
           I'd rather use a Column here, but the pip images have an halo
153
 
           around them, so they are pretty tall and would mess up the column.
154
 
           As a workaround I center all of them, then shift up or down
155
 
           depending on the index. */
156
 
        Repeater {
157
 
            model: item.pips
158
 
            delegate: Image {
159
 
                objectName: "pips-" + index
160
 
                /* FIXME: It seems that when the image is created (or re-used) by the Repeater
161
 
                   for a moment it doesn't have any parent, and therefore warnings are
162
 
                   printed for the following two anchor assignements. This fixes the
163
 
                   problem, but I'm not sure if it should happen in the first place. */
164
 
                anchors.left: (parent) ? parent.left : undefined
165
 
                y: item.height - item.selectionOutlineSize / 2 - height / 2 + getPipOffset(index)
166
 
                mirror: isRightToLeft()
167
 
 
168
 
                source: "image://blended/%1color=%2alpha=%3"
169
 
                        .arg(pipSource).arg("lightgrey").arg(1.0)
170
 
 
171
 
                visible: looseItem.state != "beingDragged"
172
 
            }
173
 
        }
174
 
 
175
 
        MouseArea {
176
 
            id: mouse
177
 
            anchors.fill: parent
178
 
            hoverEnabled: true
179
 
            acceptedButtons: Qt.LeftButton | Qt.RightButton | Qt.MidButton
180
 
 
181
 
            onClicked: item.clicked(mouse)
182
 
            onEntered: item.entered()
183
 
            onExited: item.exited()
184
 
            onPressed: item.pressed(mouse)
185
 
        }
186
 
 
187
 
        /* This is the for centering the actual tile in the launcher */
188
 
        Item {
189
 
            id: tile
190
 
            width: item.tileSize
191
 
            height: item.tileSize
192
 
            anchors.centerIn: parent
193
 
 
194
 
            /* This is the image providing the background image. The
195
 
               color blended with this image is obtained from the color of the icon when it's
196
 
               loaded.
197
 
               While the application is launching, this will fade out and in. */
198
 
            Image {
199
 
                id: tileBackground
200
 
                objectName: "tileBackground"
201
 
                property color color: defaultBackgroundColor
202
 
                anchors.fill: parent
203
 
                smooth: true
204
 
                opacity: 1
205
 
 
206
 
                SequentialAnimation on opacity {
207
 
                    NumberAnimation { to: 0.0; duration: 1000; easing.type: Easing.InOutQuad }
208
 
                    NumberAnimation { to: 1.0; duration: 1000; easing.type: Easing.InOutQuad }
209
 
 
210
 
                    loops: Animation.Infinite
211
 
                    alwaysRunToEnd: true
212
 
                    running: launching
213
 
                }
214
 
 
215
 
                sourceSize.width: item.tileSize
216
 
                sourceSize.height: item.tileSize
217
 
                source: {
218
 
                    if (isBfb) {
219
 
                        if (declarativeView.focus && item.activeFocus) {
220
 
                            return "artwork/squircle_base_selected_54.png"
221
 
                        } else {
222
 
                            return "artwork/squircle_base_54.png"
223
 
                        }
224
 
                    }
225
 
 
226
 
                    var actualColor = declarativeView.focus && item.activeFocus ? selectedBackgroundColor : color
227
 
                    return "image://blended/%1color=%2alpha=%3"
228
 
                        .arg("launcher/artwork/round_corner_54x54.png")
229
 
                        .arg(actualColor.toString().replace("#", ""))
230
 
                        .arg(1.0)
231
 
                }
232
 
            }
233
 
 
234
 
            /* This image appears only while launching, and pulses in and out in counterpoint
235
 
               to the background, so that the outline of the tile is always visible. */
236
 
            Image {
237
 
                id: tileOutline
238
 
                anchors.fill: parent
239
 
                smooth: true
240
 
 
241
 
                sourceSize.width: item.tileSize
242
 
                sourceSize.height: item.tileSize
243
 
                source: "artwork/round_outline_54x54.png"
244
 
 
245
 
                opacity: 0
246
 
 
247
 
                SequentialAnimation on opacity {
248
 
                    NumberAnimation { to: 1.0; duration: 1000; easing.type: Easing.InOutQuad }
249
 
                    NumberAnimation { to: 0.0; duration: 1000; easing.type: Easing.InOutQuad }
250
 
 
251
 
                    loops: Animation.Infinite
252
 
                    alwaysRunToEnd: true
253
 
                    running: launching
254
 
                }
255
 
            }
256
 
 
257
 
            /* This is just the main icon of the tile */
258
 
            Image {
259
 
                id: icon
260
 
                objectName: "icon"
261
 
                anchors.centerIn: parent
262
 
                smooth: true
263
 
 
264
 
                sourceSize.width: 48
265
 
                sourceSize.height: 48
266
 
 
267
 
                /* Whenever one of the parameters used in calculating the background color of
268
 
                   the icon changes, recalculate its value */
269
 
                onWidthChanged: updateColors()
270
 
                onHeightChanged: updateColors()
271
 
                onSourceChanged: updateColors()
272
 
                onStatusChanged: if (status == Image.Error) source = "image://icons/unknown"
273
 
 
274
 
                function updateColors() {
275
 
                    if (!item.backgroundFromIcon) return;
276
 
 
277
 
                    var colors = iconUtilities.getColorsFromIcon(icon.source, icon.sourceSize)
278
 
                    if (colors && colors.length > 0) tileBackground.color = colors[0]
279
 
                }
280
 
            }
281
 
 
282
 
            /* This just adds some shiny effect to the tile */
283
 
            Image {
284
 
                id: tileShine
285
 
                anchors.fill: parent
286
 
                smooth: true
287
 
 
288
 
                source: isBfb ? "artwork/squircle_shine_54.png" : "artwork/round_shine_54x54.png"
289
 
                sourceSize.width: item.tileSize
290
 
                sourceSize.height: item.tileSize
291
 
            }
292
 
 
293
 
            Image {
294
 
                id: selectionOutline
295
 
                objectName: "selectionOutline"
296
 
                anchors.centerIn: parent
297
 
                smooth: true
298
 
                source: isBfb ? "artwork/squircle_glow_54.png" : "artwork/round_selected_66x66.png"
299
 
                visible: declarativeView.focus && item.activeFocus
300
 
            }
301
 
 
302
 
            Rectangle {
303
 
                id: counter
304
 
                height: 16 - border.width
305
 
                width: 32
306
 
                // Using anchors the item will be 1 pixel off with respect to Unity
307
 
                y: 1
308
 
                x: 1
309
 
                radius: height / 2 - 1
310
 
                smooth: true
311
 
                border.width: 2
312
 
                border.color: "white"
313
 
                color: "#595959"
314
 
                visible: launcherItem.counterVisible
315
 
 
316
 
                Text {
317
 
                    anchors.centerIn: parent
318
 
                    font.pixelSize: parent.height - 3
319
 
                    width: parent.width - 5
320
 
                    smooth: true
321
 
                    elide: Text.ElideRight
322
 
                    horizontalAlignment: Text.AlignHCenter
323
 
                    color: "white"
324
 
                    text: launcherItem.counter
325
 
                }
326
 
            }
327
 
 
328
 
            Image {
329
 
                id: progressBar
330
 
                objectName: "progressBar"
331
 
                source: "artwork/progress_bar_trough.png"
332
 
                anchors.verticalCenter: parent.verticalCenter
333
 
                anchors.left: parent.left
334
 
                width: tile.width
335
 
                smooth: true
336
 
                state: launcherItem.progressBarVisible ? "" : "hidden"
337
 
 
338
 
                Image {
339
 
                    id: progressFill
340
 
                    source: "artwork/progress_bar_fill.png"
341
 
                    anchors.verticalCenter: parent.verticalCenter
342
 
                    x: 6
343
 
                    width: sourceSize.width * launcherItem.progress
344
 
                    smooth: true
345
 
 
346
 
                    Behavior on width {
347
 
                       NumberAnimation { duration: 200; easing.type: Easing.InOutSine }
348
 
                    }
349
 
                }
350
 
 
351
 
                Behavior on width {
352
 
                    NumberAnimation { duration: 200; easing.type: Easing.InOutSine }
353
 
                }
354
 
 
355
 
                states: State {
356
 
                    name: "hidden"
357
 
                    PropertyChanges {
358
 
                        target: progressBar
359
 
                        width: 0
360
 
                    }
361
 
                    // This, combined with anchors.left: parent.left in the default state
362
 
                    // makes the bar seem to come in from the left and go away at the right
363
 
                    AnchorChanges {
364
 
                        target: progressBar
365
 
                        anchors.left: undefined
366
 
                        anchors.right: tile.right
367
 
                    }
368
 
                }
369
 
            }
370
 
 
371
 
            Rectangle {
372
 
                id: shortcut
373
 
                anchors.centerIn: parent
374
 
                color: "#B3000000" // 0.7 opacity on black
375
 
                radius: 2
376
 
                width: 22
377
 
                height: 22
378
 
                smooth: true
379
 
 
380
 
                Text {
381
 
                    id: shortcutText
382
 
                    anchors.centerIn: parent
383
 
                    color: "white"
384
 
                    smooth: true
385
 
                }
386
 
            }
387
 
 
388
 
            Image {
389
 
                id: emblemIcon
390
 
                anchors.left: parent.left
391
 
                anchors.top: parent.top
392
 
                visible: launcherItem.emblemVisible && !counter.visible
393
 
                smooth: true
394
 
            }
395
 
 
396
 
 
397
 
            /* The entire tile will "shake" when the window is marked as "urgent", to attract
398
 
               the user's attention */
 
78
        id: container
 
79
 
 
80
        width: 50
 
81
        height: 50
 
82
        anchors.horizontalCenter: parent.horizontalCenter
 
83
        anchors.verticalCenter: parent.verticalCenter
 
84
 
 
85
        Rectangle {
 
86
            id: background
 
87
 
 
88
            opacity: mouse.containsMouse ? 1.0 : 0.9
 
89
            anchors.fill: parent
 
90
            anchors.margins: 1
 
91
            anchors.horizontalCenter: parent.horizontalCenter
 
92
            anchors.verticalCenter: parent.verticalCenter
 
93
            smooth: true
 
94
            color: if(icon.source != "")
 
95
                       return launcherView.iconAverageColor(icon.source,
 
96
                                                            Qt.size(icon.width, icon.height))
 
97
            radius: 5
 
98
        }
 
99
 
 
100
        Image {
 
101
            id: icon
 
102
 
 
103
            width: 30
 
104
            height: 30
 
105
            anchors.horizontalCenter: parent.horizontalCenter
 
106
            anchors.verticalCenter: parent.verticalCenter
 
107
            fillMode: Image.PreserveAspectFit
 
108
            sourceSize.width: width
 
109
            sourceSize.height: height
 
110
            smooth: true
 
111
 
 
112
            asynchronous: true
 
113
            opacity: status == Image.Ready ? 1 : 0
 
114
            Behavior on opacity {NumberAnimation {duration: 200; easing.type: Easing.InOutQuad}}
 
115
        }
 
116
 
 
117
        Image {
 
118
            id: foreground
 
119
 
 
120
            anchors.fill: parent
 
121
            anchors.horizontalCenter: parent.horizontalCenter
 
122
            anchors.verticalCenter: parent.verticalCenter
 
123
            fillMode: Image.PreserveAspectFit
 
124
            sourceSize.width: width
 
125
            sourceSize.height: height
 
126
            smooth: true
 
127
 
 
128
            source: "/usr/share/unity/themes/prism_icon_foreground.png"
 
129
 
 
130
            asynchronous: true
 
131
            opacity: status == Image.Ready ? 1 : 0
 
132
            Behavior on opacity {NumberAnimation {duration: 200; easing.type: Easing.InOutQuad}}
 
133
        }
 
134
 
 
135
        SequentialAnimation {
 
136
            id: nudging
 
137
            running: urgent
399
138
            SequentialAnimation {
400
 
                id: urgentAnimation
401
 
                running: urgent
402
 
                alwaysRunToEnd: true
403
 
 
404
 
                SequentialAnimation {
405
 
                    loops: (urgent) ? 30 : 0
406
 
                    NumberAnimation { target: tile; property: "rotation"; to: 15; duration: 150 }
407
 
                    NumberAnimation { target: tile; property: "rotation"; to: -15; duration: 150 }
408
 
                }
409
 
                NumberAnimation { target: tile; property: "rotation"; to: 0; duration: 75 }
410
 
            }
411
 
        }
412
 
 
413
 
        states: State {
414
 
            name: "beingDragged"
415
 
            when: item.isBeingDragged
416
 
            PropertyChanges {
417
 
                target: looseItem
418
 
                y: item.dragPosition - tile.height / 2
419
 
                /* When dragging an item, stack it on top of all its siblings */
420
 
                z: list.contentItem.z + 2
421
 
            }
422
 
        }
423
 
        Behavior on y {
424
 
            enabled: /* do not animate during initial positioning */
425
 
                     looseItem.animateY
426
 
                     /* do not animate while dragging to re-order applications */
427
 
                     && (looseItem.state != "beingDragged")
428
 
                     /* do not animate during insertion/removal */
429
 
                     && (looseItem.scale == 1)
430
 
                     /* do not animate while flicking the list */
431
 
                     && !item.ListView.view.moving
432
 
                     && !item.ListView.view.autoScrolling
433
 
            NumberAnimation {
434
 
                duration: 250
435
 
                easing.type: Easing.OutBack
436
 
            }
437
 
        }
438
 
 
439
 
        /* Delay the animation on y to when the item has been initially positioned. */
440
 
        Timer {
441
 
            id: canAnimateY
442
 
            /* This ensures that the trigger will be executed in the next
443
 
               iteration of the event loop, at which point the item will have
444
 
               taken its initial position. */
445
 
            triggeredOnStart: true
446
 
            onTriggered: {
447
 
                stop()
448
 
                looseItem.animateY = true
449
 
            }
450
 
        }
451
 
        Component.onCompleted: canAnimateY.start()
 
139
                loops: 30
 
140
                NumberAnimation { target: container; property: "rotation"; to: 15; duration: 150 }
 
141
                NumberAnimation { target: container; property: "rotation"; to: -15; duration: 150 }
 
142
            }
 
143
            NumberAnimation { target: container; property: "rotation"; to: 0; duration: 75 }
 
144
        }
 
145
 
 
146
        NumberAnimation {
 
147
            id: end_nudging
 
148
            running: !urgent
 
149
            target: container
 
150
            property: "rotation"
 
151
            to: 0
 
152
            duration: 75
 
153
        }
 
154
 
 
155
    }
 
156
 
 
157
    Image {
 
158
        id: running_arrow
 
159
 
 
160
        z: -1
 
161
        width: sourceSize.width
 
162
        height: sourceSize.height
 
163
        anchors.rightMargin: -2
 
164
        anchors.right: container.left
 
165
        anchors.verticalCenter: container.verticalCenter
 
166
        opacity: running ? 1.0 : 0.0
 
167
        source: urgent ? "/usr/share/unity/themes/application-running-notify.png" : "/usr/share/unity/themes/application-running.png"
 
168
 
 
169
        Behavior on opacity {NumberAnimation {duration: 200; easing.type: Easing.InOutQuad}}
 
170
    }
 
171
 
 
172
    Image {
 
173
        id: active_arrow
 
174
 
 
175
        z: -1
 
176
        width: sourceSize.width
 
177
        height: sourceSize.height
 
178
        anchors.leftMargin: -2
 
179
        anchors.left: container.right
 
180
        anchors.verticalCenter: container.verticalCenter
 
181
        opacity: active ? 1.0 : 0.0
 
182
        source: "/usr/share/unity/themes/application-selected.png"
 
183
 
 
184
        Behavior on opacity {NumberAnimation {duration: 200; easing.type: Easing.InOutQuad}}
 
185
    }
 
186
 
 
187
    Text {
 
188
        id: label
 
189
 
 
190
        font.pointSize: 10
 
191
        wrapMode: Text.WordWrap
 
192
        horizontalAlignment: Text.AlignHCenter
 
193
        anchors.top: parent.bottom
 
194
        anchors.topMargin: 7
 
195
        anchors.right: parent.right
 
196
        anchors.bottom: parent.bottom
 
197
        anchors.left: parent.left
 
198
        font.underline: parent.focus
452
199
    }
453
200
}