@@ -14,387 +14,243 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17−import QtQuick 2.0
17+import QtQuick 2.2
18+import Ubuntu.Components 1.1
18−import Ubuntu.Components 0.1
19+import Ubuntu.Components.Themes.Ambiance 1.1
19−import Ubuntu.Components.Popups 0.1
20+import Ubuntu.Components.Popups 1.0
20−import Ubuntu.Components.ListItems 0.1 as ListItem
21+import Ubuntu.Components.ListItems 1.0
25+ implicitHeight: headerContainer.height + units.gu(2) + bottomContainer.height
26+ height: implicitHeight
28+ property bool showBackButton: false
29+ property string title
30+ property var scope: null
25 property bool searchEntryEnabled: false
32 property bool searchEntryEnabled: false
26− property alias searchQuery: searchField.text
27 property ListModel searchHistory
33 property ListModel searchHistory
28− property var scope: null
34+ property alias searchQuery: searchTextField.text
29− property alias childItem: itemContainer.children
30− property alias bottomItem: bottomContainer.children
31− property alias showBackButton: backButton.visible
33− signal backClicked
36+ property alias bottomItem: bottomContainer.children
35− height: header.height + units.gu(2) + bottomContainer.height
38+ signal backClicked()
36− implicitHeight: header.height + units.gu(2) + bottomContainer.height
38 function triggerSearch() {
40 function triggerSearch() {
39− if (searchEntryEnabled) searchField.forceActiveFocus()
41+ if (searchEntryEnabled) searchTextField.forceActiveFocus()
42− function resetSearch() {
44+ function resetSearch(unfocusField) {
43− if (!searchHistory) return;
45+ if (unfocusField == undefined) {
45− searchHistory.addQuery(searchField.text);
50+ searchHistory.addQuery(searchTextField.text);
46− unfocus();
53+ unfocus();
47− searchField.text = "";
54+ }
55+ searchTextField.text = "";
50 function unfocus() {
58 function unfocus() {
59+ print("unfocusing field")
51− searchField.focus = false;
60+ searchTextField.focus = false;
54− Connections {
63+ function openSearchHistory() {
55− target: greeter
64+ print("should open search history")
56− onShownChanged: if (shown) resetSearch()
65+ if (openSearchAnimation.running) {
66+ print("huh! animation is running")
67+ openSearchAnimation.openSearchHistory = true
68+ } else if (root.searchHistory.count > 0) {
69+ PopupUtils.open(popoverComponent, searchTextField,
71+ "contentWidth": searchTextField.width,
72+ "edgeMargins": units.gu(1)
59 Flickable {
78 Flickable {
60− id: header
79+ id: headerContainer
61− anchors {
80+ clip: true
62− left: parent.left
81+ anchors { left: parent.left; top: parent.top; right: parent.right }
66 height: units.gu(6.5)
82 height: units.gu(6.5)
67−
83+ contentHeight: headersColumn.height
68 interactive: false
84 interactive: false
69− contentHeight: headerContainer.height
85+ contentY: showSearch ? 0 : height
72− contentY: searchField.activeFocus || searchField.text != "" ? searchContainer.y : headerContainer.y
87+ property bool showSearch: false
74− Behavior on contentY { NumberAnimation { duration: 200; easing.type: Easing.OutQuad } }
78− objectName: root.objectName + "_backButton"
80− height: header.height
84− leftMargin: visible ? units.gu(2) : 0
86− width: visible ? image.width + units.gu(2) : 0
87− onClicked: root.backClicked();
90− anchors.centerIn: parent
91− source: "graphics/headerback.png"
95− // FIXME this could potentially be simplified to avoid all the containers
89+ Behavior on contentY {
96− Item {
90+ UbuntuNumberAnimation {
97− id: headerContainer
91+ id: openSearchAnimation
92+ property bool openSearchHistory: false
99− anchors {
94+ onRunningChanged: {
100− left: backButton.right
95+ if (!running && openSearchAnimation.openSearchHistory) {
101− right: parent.right
96+ openSearchAnimation.openSearchHistory = false;
102− }
97+ root.openSearchHistory()
103− height: childrenRect.height
108− width: searchContainer.narrowMode ? header.width : header.width - searchContainer.width
109− height: header.height
114− objectName: "searchContainer"
116− visible: searchEntryEnabled
117− property bool popoverShouldOpen: false
118− property bool popoverShouldClose: false
120− property bool narrowMode: parent.width < units.gu(80)
122− property bool active: searchField.text != "" || searchField.activeFocus
123− property var popover: null
125− anchors.right: headerContainer.right
126− height: header.height
129− if (active && narrowMode) "narrowActive"
130− else if (!active && narrowMode) "narrowInactive"
131− else if (active && !narrowMode) "active"
132− else if (!active && !narrowMode) "inactive"
135− if (state == "active" || state == "narrowActive") {
136− popoverShouldOpen = true;
137− popoverShouldClose = false;
139− popoverShouldOpen = false;
140− popoverShouldClose = true;
144− function openPopover() {
103+ Column {
145− if (searchHistory.count > 0) {
104+ id: headersColumn
146− searchContainer.popover = PopupUtils.open(popoverComponent, pointerPositioner,
105+ anchors.fill: parent
147− {
106+ height: searchHeader.height + header.height
148− "contentWidth": searchField.width,
107+
149− "edgeMargins": units.gu(1)
108+ PageHeadStyle {
150− }
109+ id: searchHeader
151− )
110+ anchors { left: parent.left; right: parent.right }
152− }
111+ height: headerContainer.height
153− popoverShouldOpen = false;
112+ contentHeight: height
154− popoverShouldClose = false;
113+ separatorSource: ""
155− }
114+ property var styledItem: searchHeader
156−
115+ property string title: "searchHeader"
157− function closePopover() {
116+ property var config: PageHeadConfiguration {
158− if (searchContainer.popover) {
117+ backAction: Action {
159− PopupUtils.close(searchContainer.popover);
118+ iconName: "back"
160− searchContainer.popover = null;
119+ onTriggered: {
120+ root.resetSearch(true)
121+ headerContainer.showSearch = false
162− popoverShouldOpen = false;
163− popoverShouldClose = false;
166− onActiveFocusChanged: if (!activeFocus) { searchHistory.addQuery(searchField.text) }
168− TextField {
125+ property var contents: TextField {
169− id: searchField
126+ id: searchTextField
171− anchors.fill: parent
172− anchors.margins: units.gu(1)
174− inputMethodHints: Qt.ImhNoPredictiveText
175 hasClearButton: false
127 hasClearButton: false
130+ leftMargin: units.gu(1)
131+ topMargin: units.gu(1)
132+ bottomMargin: units.gu(1)
133+ rightMargin: root.width > units.gu(60) ? root.width - units.gu(40) : units.gu(1)
177− primaryItem: AbstractButton {
136+ secondaryItem: AbstractButton {
178− enabled: searchField.text != "" && !searchIndicator.running
180− if (searchField.text != "") {
181− searchHistory.addQuery(searchField.text)
182− searchField.text = ""
185− height: parent.height
137+ height: searchTextField.height
186 width: height
138 width: height
188− ActivityIndicator {
140+ Image {
189− id: searchIndicator
141+ anchors.fill: parent
190− objectName: "searchIndicator"
192− anchors {
142+ anchors.margins: units.gu(.75)
193− verticalCenter: parent.verticalCenter
143+ source: "image://theme/clear"
194− left: parent.left
144+ opacity: searchTextField.text.length > 0 && !searchActivityIndicator.running
195− leftMargin: units.gu(0.5)
198− running: opacity > 0
201− Image {
147+ ActivityIndicator {
202− id: primaryImage
148+ id: searchActivityIndicator
203− objectName: "primaryImage"
204− anchors {
149+ anchors.fill: parent
205− verticalCenter: parent.verticalCenter
150+ anchors.margins: units.gu(.75)
206− left: parent.left
151+ running: root.scope && root.scope.searchInProgress
207− leftMargin: units.gu(0.5)
152+ opacity: running ? 1 : 0
153+ Behavior on opacity {
154+ UbuntuNumberAnimation { duration: UbuntuAnimation.FastDuration }
211− visible: opacity > 0
214− Item {
158+ onClicked: {
215− id: pointerPositioner
159+ root.resetSearch(false)
216− anchors.left: parent.right
160+ root.openSearchHistory()
217− anchors.leftMargin: units.gu(0.5)
218− anchors.top: parent.bottom
223− if (text != "") searchContainer.closePopover()
224− else if (text == "" && activeFocus) searchContainer.openPopover()
227 onActiveFocusChanged: {
164 onActiveFocusChanged: {
228− if (!activeFocus) searchContainer.closePopover()
165+ if (activeFocus) {
166+ root.openSearchHistory()
231− states: [
172+ PageHeadStyle {
232− State {
173+ id: header
233− name: "searching"
174+ anchors { left: parent.left; right: parent.right }
234− when: scope && scope.searchInProgress
175+ height: headerContainer.height
235− PropertyChanges { target: searchIndicator; running: true; opacity: 1 }
176+ contentHeight: height
236− PropertyChanges { target: primaryImage; opacity: 0 }
177+ separatorSource: ""
237− },
178+ textColor: "grey"
238− State {
179+ property var styledItem: header
239− name: "idle"
180+ property string title: root.title
240− when: !scope || !scope.searchInProgress
181+ property var config: PageHeadConfiguration {
241− PropertyChanges { target: searchIndicator; opacity: 0 }
182+ backAction: Action {
242− PropertyChanges { target: primaryImage; opacity: 1 }
183+ iconName: "back"
184+ visible: root.showBackButton
186+ print("Back clicked")
246− transitions: [
191+ actions: [
247− Transition {
192+ Action {
248− to: "searching"
193+ iconName: "search"
249− reversible: true
194+ visible: root.searchEntryEnabled
250− SequentialAnimation {
195+ onTriggered: {
251− NumberAnimation { target: primaryImage; property: "opacity"; duration: UbuntuAnimation.FastDuration; easing.type: Easing.Linear }
196+ headerContainer.showSearch = true
252− NumberAnimation { target: searchIndicator; property: "opacity"; duration: UbuntuAnimation.FastDuration; easing.type: Easing.Linear }
197+ searchTextField.forceActiveFocus()
261− AnchorChanges { target: itemContainer; anchors.top: headerContainer.top }
262− AnchorChanges { target: searchContainer; anchors.left: undefined; anchors.top: itemContainer.top }
266− PropertyChanges { target: searchField; highlighted: true }
267− AnchorChanges { target: itemContainer; anchors.top: searchContainer.bottom }
268− AnchorChanges { target: searchContainer; anchors.left: headerContainer.left; anchors.top: headerContainer.top }
273− PropertyChanges { target: searchContainer; width: units.gu(40) }
274− PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
275− PropertyChanges { target: searchField; highlighted: true }
280− PropertyChanges { target: searchContainer; width: units.gu(25) }
281− PropertyChanges { target: primaryImage; source: "../Dash/graphics/icon_search_inactive.png" }
282− PropertyChanges { target: searchField; highlighted: false }
285− name: "narrowActive"
287− PropertyChanges { target: header; contentY: 0 }
288− PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
291− name: "narrowInactive"
293− PropertyChanges { target: header; contentY: header.height }
294− PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
301− SequentialAnimation {
303− NumberAnimation { targets: [searchContainer, searchField]; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
304− PropertyAction { target: primaryImage; property: "source" }
305− AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
307− ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
312− ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
313− NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
314− AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
318− SequentialAnimation {
320− NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
321− AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
323− ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
327− to: "narrowInactive"
328− ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
329− NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
330− AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
334− Component {
206+ Component {
335− id: popoverComponent
207+ id: popoverComponent
336− Popover {
208+ Popover {
337− id: popover
209+ id: popover
339− // FIXME: this should go into the first item below, but enable: false
211+ // FIXME: this should go into the first item below, but enable: false
340− // prevents mouse events propagation
212+ // prevents mouse events propagation
341− AbstractButton {
213+ AbstractButton {
342− anchors {
214+ anchors {
343− top: parent.top
215+ top: parent.top
344− right: parent.right
216+ right: parent.right
346− height: units.gu(6)
218+ height: units.gu(6)
347− width: height
219+ width: height
349− onClicked: searchContainer.closePopover()
221+ onClicked: PopupUtils.close(popover)
352− anchors.centerIn: parent
224+ anchors.centerIn: parent
353− width: units.gu(2)
225+ width: units.gu(2)
354− height: units.gu(2)
226+ height: units.gu(2)
355− source: "../Dash/graphics/icon_listview_clear.png"
227+ source: "../Dash/graphics/icon_listview_clear.png"
359− Column {
231+ Column {
360− anchors {
232+ anchors {
361− top: parent.top
233+ top: parent.top
362− left: parent.left
234+ left: parent.left
363− right: parent.right
235+ right: parent.right
366− ListItem.Standard { enabled: false; text: i18n.tr("Recent searches") }
238+ Standard { enabled: false; text: i18n.tr("Recent searches") }
368− Repeater {
240+ Repeater {
369− id: recentSearches
241+ id: recentSearches
370− model: searchHistory
242+ model: searchHistory
372− delegate: ListItem.Standard {
244+ delegate: Standard {
373− showDivider: index < recentSearches.count - 1
245+ showDivider: index < recentSearches.count - 1
374− text: query
246+ text: query
375− onClicked: {
247+ onClicked: {
376− searchHistory.addQuery(text)
248+ searchHistory.addQuery(text)
377− searchField.text = text
249+ searchTextField.text = text
378− }
250+ PopupUtils.close(popover)
386− enabled: searchField.activeFocus
394− height: searchContainer.popover ? parent.height + searchContainer.popover.contentHeight + units.gu(2) : parent.height
396− onPressed: searchField.focus = false
@@ -402,7 +258,7 @@ Item {
402 BorderImage {
258 BorderImage {
403 id: bottomBorder
259 id: bottomBorder
404 anchors {
260 anchors {
405− top: header.bottom
261+ top: headerContainer.bottom
406 left: parent.left
262 left: parent.left
407 right: parent.right
263 right: parent.right
408 bottom: bottomContainer.top
264 bottom: bottomContainer.top