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 The text that is shown inside the Page Header
26 \qmlproperty string text
28 property alias text: label.text
30 property bool searchEntryEnabled: false
31 property alias searchQuery: searchField.text
32 property ListModel searchHistory: SearchHistoryModel {}
35 implicitHeight: units.gu(8.5)
37 function triggerSearch() {
38 if (searchEntryEnabled) searchField.forceActiveFocus()
41 function resetSearch() {
42 if (!searchHistory) return;
44 searchHistory.addQuery(searchField.text);
45 searchField.text = "";
46 searchField.focus = false;
51 onShownChanged: if (shown) resetSearch()
64 contentHeight: headerContainer.height
67 contentY: searchField.activeFocus || searchField.text != "" ? searchContainer.y : headerContainer.y
69 Behavior on contentY { NumberAnimation { duration: 200; easing.type: Easing.OutQuad } }
71 // FIXME this could potentially be simplified to avoid all the containers
76 height: childrenRect.height
88 leftMargin: units.gu(2)
90 verticalCenter: parent.verticalCenter
96 font.weight: Font.Light
98 elide: Text.ElideRight
106 objectName: "searchContainer"
108 visible: searchEntryEnabled
110 property bool narrowMode: parent.width < label.contentWidth + units.gu(50)
112 property bool active: searchField.text != "" || searchField.activeFocus
113 property var popover: null
115 anchors.right: textContainer.right
116 height: header.height
119 if (active && narrowMode) "narrowActive"
120 else if (!active && narrowMode) "narrowInactive"
121 else if (active && !narrowMode) "active"
122 else if (!active && !narrowMode) "inactive"
124 function openPopover() {
125 if (searchHistory.count > 0) {
126 searchContainer.popover = PopupUtils.open(popoverComponent, searchField,
128 "pointerTarget": pointerPositioner,
129 "contentWidth": searchField.width,
130 "edgeMargins": units.gu(1)
136 function closePopover() {
137 if (searchContainer.popover) PopupUtils.close(searchContainer.popover)
140 onActiveFocusChanged: if (!activeFocus) { searchHistory.addQuery(searchField.text) }
146 anchors.margins: units.gu(1)
148 hasClearButton: false
150 primaryItem: Button {
151 enabled: searchField.text != ""
152 ItemStyle.class: "transparent-button"
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
275 ItemStyle.class: "transparent-button"
283 onClicked: searchContainer.closePopover()
286 anchors.centerIn: parent
289 source: "../Dash/graphics/icon_listview_clear.png"
300 ListItem.Standard { enabled: false; text: i18n.tr("Recent searches") }
306 delegate: ListItem.Standard {
307 showDivider: index < recentSearches.count - 1
310 searchHistory.addQuery(text)
311 searchField.text = text
320 enabled: searchField.activeFocus
328 height: searchContainer.popover ? parent.height + searchContainer.popover.contentHeight + units.gu(2) : parent.height
330 onPressed: searchField.focus = false
342 bottom: parent.bottom
345 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