2 * Copyright (C) 2013 Canonical, Ltd.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18import Ubuntu.Components 0.1
19import Ubuntu.Components.Popups 0.1
20import Ubuntu.Components.ListItems 0.1 as ListItem
25 property bool searchEntryEnabled: false
26 property alias searchQuery: searchField.text
27 property ListModel searchHistory
29 property alias childItem: itemContainer.children
32 implicitHeight: units.gu(8.5)
34 function triggerSearch() {
35 if (searchEntryEnabled) searchField.forceActiveFocus()
38 function resetSearch() {
39 if (!searchHistory) return;
41 searchHistory.addQuery(searchField.text);
43 searchField.text = "";
47 searchField.focus = false;
52 onShownChanged: if (shown) resetSearch()
65 contentHeight: headerContainer.height
68 contentY: searchField.activeFocus || searchField.text != "" ? searchContainer.y : headerContainer.y
70 Behavior on contentY { NumberAnimation { duration: 200; easing.type: Easing.OutQuad } }
72 // FIXME this could potentially be simplified to avoid all the containers
77 height: childrenRect.height
82 width: searchContainer.narrowMode ? header.width : header.width - searchContainer.width
88 objectName: "searchContainer"
90 visible: searchEntryEnabled
91 property bool popoverShouldOpen: false
92 property bool popoverShouldClose: false
94 property bool narrowMode: parent.width < units.gu(80)
96 property bool active: searchField.text != "" || searchField.activeFocus
97 property var popover: null
99 anchors.right: headerContainer.right
100 height: header.height
103 if (active && narrowMode) "narrowActive"
104 else if (!active && narrowMode) "narrowInactive"
105 else if (active && !narrowMode) "active"
106 else if (!active && !narrowMode) "inactive"
109 if (state == "active" || state == "narrowActive") {
110 popoverShouldOpen = true;
111 popoverShouldClose = false;
113 popoverShouldOpen = false;
114 popoverShouldClose = true;
118 function openPopover() {
119 if (searchHistory.count > 0) {
120 searchContainer.popover = PopupUtils.open(popoverComponent, pointerPositioner,
122 "contentWidth": searchField.width,
123 "edgeMargins": units.gu(1)
127 popoverShouldOpen = false;
128 popoverShouldClose = false;
131 function closePopover() {
132 if (searchContainer.popover) {
133 PopupUtils.close(searchContainer.popover);
134 searchContainer.popover = null;
136 popoverShouldOpen = false;
137 popoverShouldClose = false;
140 onActiveFocusChanged: if (!activeFocus) { searchHistory.addQuery(searchField.text) }
146 anchors.margins: units.gu(1)
148 hasClearButton: false
150 primaryItem: AbstractButton {
151 enabled: searchField.text != "" && !searchIndicator.running
153 if (searchField.text != "") {
154 searchHistory.addQuery(searchField.text)
155 searchField.text = ""
158 height: parent.height
163 objectName: "searchIndicator"
166 verticalCenter: parent.verticalCenter
168 leftMargin: units.gu(0.5)
176 objectName: "primaryImage"
178 verticalCenter: parent.verticalCenter
180 leftMargin: units.gu(0.5)
188 id: pointerPositioner
189 anchors.left: parent.right
190 anchors.leftMargin: units.gu(0.5)
191 anchors.top: parent.bottom
196 if (text != "") searchContainer.closePopover()
197 else if (text == "" && activeFocus) searchContainer.openPopover()
200 onActiveFocusChanged: {
201 if (!activeFocus) searchContainer.closePopover()
207 when: scope && scope.searchInProgress
208 PropertyChanges { target: searchIndicator; running: true; opacity: 1 }
209 PropertyChanges { target: primaryImage; opacity: 0 }
213 when: !scope || !scope.searchInProgress
214 PropertyChanges { target: searchIndicator; opacity: 0 }
215 PropertyChanges { target: primaryImage; opacity: 1 }
223 SequentialAnimation {
224 NumberAnimation { target: primaryImage; property: "opacity"; duration: UbuntuAnimation.FastDuration; easing.type: Easing.Linear }
225 NumberAnimation { target: searchIndicator; property: "opacity"; duration: UbuntuAnimation.FastDuration; easing.type: Easing.Linear }
234 AnchorChanges { target: itemContainer; anchors.top: headerContainer.top }
235 AnchorChanges { target: searchContainer; anchors.left: undefined; anchors.top: itemContainer.top }
239 PropertyChanges { target: searchField; highlighted: true }
240 AnchorChanges { target: itemContainer; anchors.top: searchContainer.bottom }
241 AnchorChanges { target: searchContainer; anchors.left: headerContainer.left; anchors.top: headerContainer.top }
246 PropertyChanges { target: searchContainer; width: units.gu(40) }
247 PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
248 PropertyChanges { target: searchField; highlighted: true }
253 PropertyChanges { target: searchContainer; width: units.gu(25) }
254 PropertyChanges { target: primaryImage; source: "../Dash/graphics/icon_search_inactive.png" }
255 PropertyChanges { target: searchField; highlighted: false }
260 PropertyChanges { target: header; contentY: 0 }
261 PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
264 name: "narrowInactive"
266 PropertyChanges { target: header; contentY: header.height }
267 PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
274 SequentialAnimation {
276 NumberAnimation { targets: [searchContainer, searchField]; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
277 PropertyAction { target: primaryImage; property: "source" }
278 AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
280 ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
285 ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
286 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
287 AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
291 SequentialAnimation {
293 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
294 AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
296 ScriptAction { script: if (searchContainer.popoverShouldOpen) { searchContainer.openPopover(); } }
301 ScriptAction { script: if (searchContainer.popoverShouldClose) { searchContainer.closePopover(); } }
302 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
303 AnchorAnimation { targets: [searchContainer, itemContainer]; duration: 200; easing.type: Easing.InOutQuad }
312 // FIXME: this should go into the first item below, but enable: false
313 // prevents mouse events propagation
322 onClicked: searchContainer.closePopover()
325 anchors.centerIn: parent
328 source: "../Dash/graphics/icon_listview_clear.png"
339 ListItem.Standard { enabled: false; text: i18n.tr("Recent searches") }
345 delegate: ListItem.Standard {
346 showDivider: index < recentSearches.count - 1
349 searchHistory.addQuery(text)
350 searchField.text = text
359 enabled: searchField.activeFocus
367 height: searchContainer.popover ? parent.height + searchContainer.popover.contentHeight + units.gu(2) : parent.height
369 onPressed: searchField.focus = false
381 bottom: parent.bottom
384 source: "graphics/PageHeaderBaseDivider.sci"
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list