diff options
author | Christian Mollekopf <chrigi_1@fastmail.fm> | 2018-07-06 22:47:19 +0200 |
---|---|---|
committer | Christian Mollekopf <chrigi_1@fastmail.fm> | 2018-07-12 16:08:21 +0200 |
commit | 727e3f05df471548e590958168c52c474ab44e06 (patch) | |
tree | de80b6c523956795f3678aa474c67f6236aa541a /framework/qml | |
parent | 395f85b92f461923619fcf713f8029311630a8f2 (diff) | |
download | kube-727e3f05df471548e590958168c52c474ab44e06.tar.gz kube-727e3f05df471548e590958168c52c474ab44e06.zip |
A view search overlay
Diffstat (limited to 'framework/qml')
-rw-r--r-- | framework/qml/MailListView.qml | 51 | ||||
-rw-r--r-- | framework/qml/SearchPopup.qml | 184 | ||||
-rw-r--r-- | framework/qml/View.qml | 25 |
3 files changed, 210 insertions, 50 deletions
diff --git a/framework/qml/MailListView.qml b/framework/qml/MailListView.qml index 7e6f584d..998d9729 100644 --- a/framework/qml/MailListView.qml +++ b/framework/qml/MailListView.qml | |||
@@ -31,19 +31,10 @@ FocusScope { | |||
31 | property bool isTrash : false | 31 | property bool isTrash : false |
32 | property bool isUnread : false | 32 | property bool isUnread : false |
33 | property variant currentMail: null | 33 | property variant currentMail: null |
34 | property bool showFilter: false | 34 | property alias filter: mailListModel.filter |
35 | property string filter: null | ||
36 | |||
37 | onFilterChanged: { | ||
38 | Kube.Fabric.postMessage(Kube.Messages.searchString, {"searchString": filter}) | ||
39 | } | ||
40 | 35 | ||
41 | onParentFolderChanged: { | 36 | onParentFolderChanged: { |
42 | currentMail = null | 37 | currentMail = null |
43 | filterField.clearSearch() | ||
44 | } | ||
45 | onShowFilterChanged: { | ||
46 | find.forceActiveFocus() | ||
47 | } | 38 | } |
48 | 39 | ||
49 | Kube.Listener { | 40 | Kube.Listener { |
@@ -74,45 +65,6 @@ FocusScope { | |||
74 | 65 | ||
75 | spacing: 0 | 66 | spacing: 0 |
76 | 67 | ||
77 | Rectangle { | ||
78 | id: filterField | ||
79 | Layout.fillWidth: true | ||
80 | height: Kube.Units.gridUnit * 2 | ||
81 | color: Kube.Colors.buttonColor | ||
82 | visible: root.showFilter | ||
83 | |||
84 | function clearSearch() { | ||
85 | root.showFilter = false | ||
86 | find.text = "" | ||
87 | root.filter = "" | ||
88 | } | ||
89 | |||
90 | RowLayout { | ||
91 | anchors { | ||
92 | verticalCenter: parent.verticalCenter | ||
93 | } | ||
94 | |||
95 | width: parent.width - Kube.Units.smallSpacing | ||
96 | spacing: 0 | ||
97 | |||
98 | Kube.IconButton { | ||
99 | iconName: Kube.Icons.remove | ||
100 | activeFocusOnTab: visible | ||
101 | onClicked: filterField.clearSearch() | ||
102 | } | ||
103 | |||
104 | Kube.TextField { | ||
105 | id: find | ||
106 | Layout.fillWidth: true | ||
107 | placeholderText: qsTr("Filter...") | ||
108 | onTextChanged: root.filter = text | ||
109 | activeFocusOnTab: visible | ||
110 | focus: visible | ||
111 | Keys.onEscapePressed: filterField.clearSearch() | ||
112 | } | ||
113 | } | ||
114 | } | ||
115 | |||
116 | Kube.ListView { | 68 | Kube.ListView { |
117 | id: listView | 69 | id: listView |
118 | objectName: "listView" | 70 | objectName: "listView" |
@@ -156,7 +108,6 @@ FocusScope { | |||
156 | model: Kube.MailListModel { | 108 | model: Kube.MailListModel { |
157 | id: mailListModel | 109 | id: mailListModel |
158 | parentFolder: root.parentFolder | 110 | parentFolder: root.parentFolder |
159 | filter: root.filter | ||
160 | } | 111 | } |
161 | 112 | ||
162 | delegate: Kube.ListDelegate { | 113 | delegate: Kube.ListDelegate { |
diff --git a/framework/qml/SearchPopup.qml b/framework/qml/SearchPopup.qml new file mode 100644 index 00000000..b1787e1b --- /dev/null +++ b/framework/qml/SearchPopup.qml | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Michael Bohlender, <michael.bohlender@kdemail.net> | ||
3 | * Copyright (C) 2017 Christian Mollekopf, <mollekopf@kolabsys.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along | ||
16 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
18 | */ | ||
19 | |||
20 | |||
21 | import QtQuick 2.9 | ||
22 | import QtQuick.Controls 2 | ||
23 | import QtQuick.Layouts 1.1 | ||
24 | |||
25 | import org.kube.framework 1.0 as Kube | ||
26 | |||
27 | Item { | ||
28 | id: root | ||
29 | |||
30 | property rect searchArea | ||
31 | property string backgroundColor: Kube.Colors.darkCharcoalGrey | ||
32 | property real backgroundOpacity: 0 | ||
33 | property real searchAreaOpacity: backgroundOpacity / 4 | ||
34 | |||
35 | NumberAnimation on backgroundOpacity { | ||
36 | id: fadeIn | ||
37 | from: 0 | ||
38 | to: 0.8 | ||
39 | duration: 100 | ||
40 | } | ||
41 | |||
42 | Component.onCompleted: fadeIn.start() | ||
43 | |||
44 | NumberAnimation on backgroundOpacity { | ||
45 | id: fadeOut | ||
46 | running: false | ||
47 | to: 0 | ||
48 | duration: 100 | ||
49 | onRunningChanged: { | ||
50 | if (!running) { | ||
51 | root.destroy() | ||
52 | } | ||
53 | } | ||
54 | } | ||
55 | |||
56 | function close() { | ||
57 | fadeOut.start() | ||
58 | } | ||
59 | |||
60 | property string filter: "" | ||
61 | |||
62 | parent: ApplicationWindow.overlay | ||
63 | anchors.fill: parent | ||
64 | enabled: false | ||
65 | |||
66 | //left | ||
67 | Rectangle { | ||
68 | x: 0 | ||
69 | y: 0 | ||
70 | width: searchArea.x | ||
71 | height: parent.height | ||
72 | color: parent.backgroundColor | ||
73 | opacity: parent.backgroundOpacity | ||
74 | } | ||
75 | //bottom | ||
76 | Rectangle { | ||
77 | x: searchArea.x | ||
78 | y: searchArea.y + searchArea.height | ||
79 | width: searchArea.width | ||
80 | height: parent.height - y | ||
81 | color: parent.backgroundColor | ||
82 | opacity: parent.backgroundOpacity | ||
83 | } | ||
84 | //right | ||
85 | Rectangle { | ||
86 | x: searchArea.x + searchArea.width | ||
87 | y: 0 | ||
88 | width: parent.width - x | ||
89 | height: parent.height | ||
90 | color: parent.backgroundColor | ||
91 | opacity: parent.backgroundOpacity | ||
92 | } | ||
93 | //bottom | ||
94 | Rectangle { | ||
95 | x: searchArea.x | ||
96 | y: 0 | ||
97 | width: searchArea.width | ||
98 | height: searchArea.y | ||
99 | color: parent.backgroundColor | ||
100 | opacity: parent.backgroundOpacity | ||
101 | } | ||
102 | //outline | ||
103 | Rectangle { | ||
104 | x: searchArea.x | ||
105 | y: searchArea.y | ||
106 | width: searchArea.width | ||
107 | height: searchArea.height | ||
108 | color: "transparent" | ||
109 | border { | ||
110 | width: 3 | ||
111 | color: Kube.Colors.highlightColor | ||
112 | } | ||
113 | Rectangle { | ||
114 | anchors.fill: parent | ||
115 | color: parent.parent.backgroundColor | ||
116 | opacity: parent.parent.searchAreaOpacity | ||
117 | } | ||
118 | } | ||
119 | |||
120 | |||
121 | Rectangle { | ||
122 | id: filterField | ||
123 | enabled: true | ||
124 | parent: ApplicationWindow.overlay | ||
125 | |||
126 | anchors { | ||
127 | horizontalCenter: parent.horizontalCenter | ||
128 | } | ||
129 | y: parent.height / 3 | ||
130 | height: Kube.Units.gridUnit * 2 | ||
131 | width: Kube.Units.gridUnit * 30 | ||
132 | radius: Kube.Units.smallSpacing | ||
133 | |||
134 | color: Kube.Colors.darkBackgroundColor | ||
135 | |||
136 | states: [ | ||
137 | State { | ||
138 | name: "searchInProgress" | ||
139 | when: find.text.length != 0 | ||
140 | PropertyChanges {target: filterField; y: Kube.Units.gridUnit} | ||
141 | PropertyChanges {target: root; searchAreaOpacity: 0} | ||
142 | } | ||
143 | ] | ||
144 | |||
145 | transitions: Transition { | ||
146 | NumberAnimation { properties: "y"; easing.type: Easing.InOutQuad } | ||
147 | } | ||
148 | |||
149 | function clearSearch() { | ||
150 | find.text = "" | ||
151 | root.close() | ||
152 | } | ||
153 | |||
154 | Shortcut { | ||
155 | sequences: [StandardKey.Cancel] | ||
156 | onActivated: filterField.clearSearch() | ||
157 | } | ||
158 | |||
159 | RowLayout { | ||
160 | anchors { | ||
161 | verticalCenter: parent.verticalCenter | ||
162 | } | ||
163 | |||
164 | width: parent.width - Kube.Units.smallSpacing | ||
165 | spacing: 0 | ||
166 | |||
167 | Kube.IconButton { | ||
168 | iconName: Kube.Icons.remove | ||
169 | activeFocusOnTab: visible | ||
170 | onClicked: filterField.clearSearch() | ||
171 | } | ||
172 | |||
173 | Kube.TextField { | ||
174 | id: find | ||
175 | Layout.fillWidth: true | ||
176 | placeholderText: qsTr("Filter...") | ||
177 | onTextChanged: root.filter = text | ||
178 | activeFocusOnTab: visible | ||
179 | focus: visible | ||
180 | Keys.onEscapePressed: filterField.clearSearch() | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | } | ||
diff --git a/framework/qml/View.qml b/framework/qml/View.qml index 9daa76a8..88cc3f10 100644 --- a/framework/qml/View.qml +++ b/framework/qml/View.qml | |||
@@ -31,6 +31,19 @@ FocusScope { | |||
31 | property int count: contentItems.length | 31 | property int count: contentItems.length |
32 | default property alias contentItems: content.data | 32 | default property alias contentItems: content.data |
33 | 33 | ||
34 | property rect searchArea: null | ||
35 | property string filter: "" | ||
36 | property var searchObject: null | ||
37 | function triggerSearch() { | ||
38 | root.searchObject = searchComponent.createObject(root) | ||
39 | } | ||
40 | function clearSearch() { | ||
41 | if (root.searchObject) { | ||
42 | root.searchObject.close() | ||
43 | root.searchObject = null | ||
44 | } | ||
45 | } | ||
46 | |||
34 | property bool __aborted: false | 47 | property bool __aborted: false |
35 | 48 | ||
36 | //This signal will be emitted once all initial properties have been set and the view is ready to load | 49 | //This signal will be emitted once all initial properties have been set and the view is ready to load |
@@ -104,4 +117,16 @@ FocusScope { | |||
104 | id: content | 117 | id: content |
105 | anchors.fill: parent | 118 | anchors.fill: parent |
106 | } | 119 | } |
120 | |||
121 | Component { | ||
122 | id: searchComponent | ||
123 | Kube.SearchPopup { | ||
124 | searchArea: root.searchArea | ||
125 | onFilterChanged: { | ||
126 | root.filter = filter | ||
127 | } | ||
128 | } | ||
129 | |||
130 | } | ||
131 | |||
107 | } | 132 | } |