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
21import SessionManager 0.1
26 The text that is shown inside the Page Header
27 \qmlproperty string text
29 property alias text: label.text
31 property bool searchEntryEnabled: false
32 property alias searchQuery: searchField.text
33 property ListModel searchHistory: SearchHistoryModel {}
36 implicitHeight: units.gu(8.5)
38 function triggerSearch() {
39 if (searchEntryEnabled) searchField.forceActiveFocus()
42 function resetSearch() {
43 if (!searchHistory) return;
45 searchHistory.addQuery(searchField.text);
46 searchField.text = "";
47 searchField.focus = false;
51 target: SessionManager
52 onActiveChanged: if (!SessionManager.active) 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
89 leftMargin: units.gu(2)
91 verticalCenter: parent.verticalCenter
94 color: Theme.palette.selected.backgroundText
97 font.weight: Font.Light
99 elide: Text.ElideRight
107 objectName: "searchContainer"
109 visible: searchEntryEnabled
111 property bool narrowMode: parent.width < label.contentWidth + units.gu(50)
113 property bool active: searchField.text != "" || searchField.activeFocus
114 property var popover: null
116 anchors.right: textContainer.right
117 height: header.height
120 if (active && narrowMode) "narrowActive"
121 else if (!active && narrowMode) "narrowInactive"
122 else if (active && !narrowMode) "active"
123 else if (!active && !narrowMode) "inactive"
125 function openPopover() {
126 if (searchHistory.count > 0) {
127 searchContainer.popover = PopupUtils.open(popoverComponent, searchField,
129 "pointerTarget": pointerPositioner,
130 "contentWidth": searchField.width,
131 "edgeMargins": units.gu(1)
137 function closePopover() {
138 if (searchContainer.popover) PopupUtils.close(searchContainer.popover)
141 onActiveFocusChanged: if (!activeFocus) { searchHistory.addQuery(searchField.text) }
147 anchors.margins: units.gu(1)
149 hasClearButton: false
151 primaryItem: AbstractButton {
152 enabled: searchField.text != ""
154 if (searchField.text != "") {
155 searchHistory.addQuery(searchField.text)
156 searchField.text = ""
159 height: parent.height
165 verticalCenter: parent.verticalCenter
167 leftMargin: units.gu(0.5)
174 id: pointerPositioner
175 anchors.left: parent.right
176 anchors.leftMargin: units.gu(0.5)
177 anchors.top: parent.bottom
182 if (text != "") searchContainer.closePopover()
183 else if (text == "" && activeFocus) searchContainer.openPopover()
186 onActiveFocusChanged: {
187 if (!activeFocus) searchContainer.closePopover()
194 AnchorChanges { target: textContainer; anchors.top: headerContainer.top }
195 AnchorChanges { target: searchContainer; anchors.left: undefined; anchors.top: textContainer.top }
199 PropertyChanges { target: searchField; highlighted: true }
200 AnchorChanges { target: textContainer; anchors.top: searchContainer.bottom }
201 AnchorChanges { target: searchContainer; anchors.left: headerContainer.left; anchors.top: headerContainer.top }
206 PropertyChanges { target: searchContainer; width: units.gu(40) }
207 PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
208 PropertyChanges { target: searchField; highlighted: true }
213 PropertyChanges { target: searchContainer; width: units.gu(25) }
214 PropertyChanges { target: primaryImage; source: "../Dash/graphics/icon_search_inactive.png" }
215 PropertyChanges { target: searchField; highlighted: false }
220 PropertyChanges { target: header; contentY: 0 }
221 PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
224 name: "narrowInactive"
226 PropertyChanges { target: header; contentY: header.height }
227 PropertyChanges { target: primaryImage; source: searchField.text ? "../Dash/graphics/icon_clear.png" : "../Dash/graphics/icon_search_active.png" }
234 SequentialAnimation {
236 NumberAnimation { targets: [searchContainer, searchField]; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
237 PropertyAction { target: primaryImage; property: "source" }
238 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
240 ScriptAction { script: searchContainer.openPopover() }
245 ScriptAction { script: searchContainer.closePopover() }
246 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.InOutQuad }
247 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
251 SequentialAnimation {
253 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
254 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
256 ScriptAction { script: searchContainer.openPopover() }
261 ScriptAction { script: searchContainer.closePopover() }
262 NumberAnimation { targets: [searchContainer, searchField] ; property: "width"; duration: 200; easing.type: Easing.OutQuad }
263 AnchorAnimation { targets: [searchContainer, textContainer]; duration: 200; easing.type: Easing.InOutQuad }
272 // FIXME: this should go into the first item below, but enable: false
273 // prevents mouse events propagation
282 onClicked: searchContainer.closePopover()
285 anchors.centerIn: parent
288 source: "../Dash/graphics/icon_listview_clear.png"
299 ListItem.Standard { enabled: false; text: i18n.tr("Recent searches") }
305 delegate: ListItem.Standard {
306 showDivider: index < recentSearches.count - 1
309 searchHistory.addQuery(text)
310 searchField.text = text
319 enabled: searchField.activeFocus
327 height: searchContainer.popover ? parent.height + searchContainer.popover.contentHeight + units.gu(2) : parent.height
329 onPressed: searchField.focus = false
341 bottom: parent.bottom
344 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