improved desktop UI
[mardrone] / mardrone / imports / com / nokia / meego / EditBubble.qml
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the Qt Components project.
8 **
9 ** $QT_BEGIN_LICENSE:BSD$
10 ** You may use this file under the terms of the BSD license as follows:
11 **
12 ** "Redistribution and use in source and binary forms, with or without
13 ** modification, are permitted provided that the following conditions are
14 ** met:
15 **   * Redistributions of source code must retain the above copyright
16 **     notice, this list of conditions and the following disclaimer.
17 **   * Redistributions in binary form must reproduce the above copyright
18 **     notice, this list of conditions and the following disclaimer in
19 **     the documentation and/or other materials provided with the
20 **     distribution.
21 **   * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
22 **     the names of its contributors may be used to endorse or promote
23 **     products derived from this software without specific prior written
24 **     permission.
25 **
26 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40
41 import QtQuick 1.1
42 import "." 1.0
43 import "Utils.js" as Utils
44 import "EditBubble.js" as Private
45
46 Item {
47     id: bubble
48
49     property Item textInput: null
50     property bool valid: rect.canCut || rect.canCopy || rect.canPaste
51
52     property alias privateRect: rect
53
54     property Style platformStyle: EditBubbleStyle {}
55
56     property variant position: Qt.point(0,0)
57
58     anchors.fill: parent
59
60     Item {
61         id: rect
62         visible: false
63         width: row.width
64         height: row.height
65
66         property int arrowOffset: 0
67         property int arrowBorder: platformStyle.arrowMargin
68         property bool arrowDown: true
69         property bool changingText: false
70         property bool pastingText: false
71
72         property bool validInput: textInput != null
73         property bool canCut: rect.canCopy && !textInput.readOnly
74
75         // TextEdit will have echoMode == null
76         property bool canCopy: textSelected && (textInput.echoMode == null || textInput.echoMode == TextInput.Normal)
77         property bool canPaste: validInput && (textInput.canPaste && !textInput.readOnly)
78         property bool textSelected: validInput && (textInput.selectedText != "")
79
80         z: 1020
81
82         onWidthChanged: {
83             if (rect.visible)
84                 Private.adjustPosition(bubble);
85         }
86
87         onHeightChanged: {
88             if (rect.visible)
89                 Private.adjustPosition(bubble);
90         }
91
92         BasicRow {
93             id: row
94             Component.onCompleted: Private.updateButtons(row);
95
96             EditBubbleButton {
97                 id: buttonCut
98                 text: textTranslator.translate("qtn_comm_cut");
99                 visible: rect.canCut
100                 onClicked: {
101                     rect.changingText = true;
102                     textInput.cut();
103                     rect.changingText = false;
104                     Private.closePopup(bubble);
105                 }
106                 onVisibleChanged: Private.updateButtons(row);
107             }
108
109             EditBubbleButton {
110                 id: buttonCopy
111                 text: textTranslator.translate("qtn_comm_copy");
112                 visible: rect.canCopy
113                 onClicked: {
114                     textInput.copy();
115                     Private.closePopup(bubble);
116                 }
117                 onVisibleChanged: Private.updateButtons(row);
118             }
119
120             EditBubbleButton {
121                 id: buttonPaste
122                 text: textTranslator.translate("qtn_comm_paste");
123                 visible: rect.canPaste
124                 onClicked: {
125                     rect.changingText = true;
126                     if (textInput.inputMethodComposing) {
127                         var cursorAdjust = textInput.preedit.length - textInput.preeditCursorPosition;
128                         inputContext.reset();
129                         textInput.cursorPosition -= cursorAdjust;
130                     }
131                     rect.pastingText = true;
132                     var text = textInput.text;
133                     textInput.paste();
134                     // PastingText is set to false and clipboard is cleared if we catch onTextChanged
135                     if (rect.pastingText && text == textInput.text) {
136                         var root = Utils.findRootItemNotificationBanner(textInput);
137
138                         // create notification banner
139                         var bannerInstance = notificationBanner.createObject(root);
140                         bannerInstance.show();
141                         bannerInstance.timerEnabled = true;
142                         rect.pastingText = false;
143                     }
144                     rect.changingText = false;
145                     Private.closePopup(bubble);
146                 }
147
148                 onVisibleChanged: Private.updateButtons(row);
149             }
150
151             Component {
152                 id : notificationBanner
153                 NotificationBanner{
154                     id: errorBannerPrivate
155                     text: textTranslator.translate("qtn_comm_cantpaste");
156                     timerShowTime: 5*1000
157                     topMargin: 8
158                     leftMargin: 8
159                 }
160             }
161         }
162
163         Image {
164             source: platformStyle.bottomTailBackground
165             visible: rect.arrowDown && bubble.valid
166
167             anchors.bottom: row.bottom
168             anchors.horizontalCenter: row.horizontalCenter
169             anchors.horizontalCenterOffset: rect.arrowOffset
170         }
171
172         Image {
173             source: platformStyle.topTailBackground
174             visible: !rect.arrowDown && bubble.valid
175
176             anchors.bottom: row.top
177             anchors.bottomMargin: -platformStyle.backgroundMarginBottom - 2
178
179             anchors.horizontalCenter: row.horizontalCenter
180             anchors.horizontalCenterOffset: rect.arrowOffset
181         }
182     }
183
184     state: "closed"
185
186     states: [
187         State {
188             name: "opened"
189             ParentChange { target: rect; parent: Utils.findRootItem(textInput); }
190             PropertyChanges { target: rect; visible: true; }
191         },
192         State {
193             name: "closed"
194             ParentChange { target: rect; parent: bubble; }
195             PropertyChanges { target: rect; visible: false; }
196         }
197     ]
198
199     Connections {
200         target: Utils.findFlickable(textInput)
201         onContentYChanged: Private.adjustPosition(bubble)
202     }
203
204     Connections {
205         target: screen
206         onCurrentOrientationChanged: Private.adjustPosition(bubble)
207     }
208
209     Connections {
210         target: textInput
211         onTextChanged: {
212             if (rect.pastingText) {
213                 inputContext.clearClipboard();
214                 rect.pastingText = false;
215             }
216         }
217     }
218 }