From 727e3f05df471548e590958168c52c474ab44e06 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Fri, 6 Jul 2018 22:47:19 +0200 Subject: A view search overlay --- framework/qml/MailListView.qml | 51 +---------- framework/qml/SearchPopup.qml | 184 ++++++++++++++++++++++++++++++++++++++++ framework/qml/View.qml | 25 ++++++ framework/qmldir | 1 + views/conversation/qml/View.qml | 23 +++-- 5 files changed, 227 insertions(+), 57 deletions(-) create mode 100644 framework/qml/SearchPopup.qml 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 { property bool isTrash : false property bool isUnread : false property variant currentMail: null - property bool showFilter: false - property string filter: null - - onFilterChanged: { - Kube.Fabric.postMessage(Kube.Messages.searchString, {"searchString": filter}) - } + property alias filter: mailListModel.filter onParentFolderChanged: { currentMail = null - filterField.clearSearch() - } - onShowFilterChanged: { - find.forceActiveFocus() } Kube.Listener { @@ -74,45 +65,6 @@ FocusScope { spacing: 0 - Rectangle { - id: filterField - Layout.fillWidth: true - height: Kube.Units.gridUnit * 2 - color: Kube.Colors.buttonColor - visible: root.showFilter - - function clearSearch() { - root.showFilter = false - find.text = "" - root.filter = "" - } - - RowLayout { - anchors { - verticalCenter: parent.verticalCenter - } - - width: parent.width - Kube.Units.smallSpacing - spacing: 0 - - Kube.IconButton { - iconName: Kube.Icons.remove - activeFocusOnTab: visible - onClicked: filterField.clearSearch() - } - - Kube.TextField { - id: find - Layout.fillWidth: true - placeholderText: qsTr("Filter...") - onTextChanged: root.filter = text - activeFocusOnTab: visible - focus: visible - Keys.onEscapePressed: filterField.clearSearch() - } - } - } - Kube.ListView { id: listView objectName: "listView" @@ -156,7 +108,6 @@ FocusScope { model: Kube.MailListModel { id: mailListModel parentFolder: root.parentFolder - filter: root.filter } 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 @@ +/* + * Copyright (C) 2017 Michael Bohlender, + * Copyright (C) 2017 Christian Mollekopf, + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +import QtQuick 2.9 +import QtQuick.Controls 2 +import QtQuick.Layouts 1.1 + +import org.kube.framework 1.0 as Kube + +Item { + id: root + + property rect searchArea + property string backgroundColor: Kube.Colors.darkCharcoalGrey + property real backgroundOpacity: 0 + property real searchAreaOpacity: backgroundOpacity / 4 + + NumberAnimation on backgroundOpacity { + id: fadeIn + from: 0 + to: 0.8 + duration: 100 + } + + Component.onCompleted: fadeIn.start() + + NumberAnimation on backgroundOpacity { + id: fadeOut + running: false + to: 0 + duration: 100 + onRunningChanged: { + if (!running) { + root.destroy() + } + } + } + + function close() { + fadeOut.start() + } + + property string filter: "" + + parent: ApplicationWindow.overlay + anchors.fill: parent + enabled: false + + //left + Rectangle { + x: 0 + y: 0 + width: searchArea.x + height: parent.height + color: parent.backgroundColor + opacity: parent.backgroundOpacity + } + //bottom + Rectangle { + x: searchArea.x + y: searchArea.y + searchArea.height + width: searchArea.width + height: parent.height - y + color: parent.backgroundColor + opacity: parent.backgroundOpacity + } + //right + Rectangle { + x: searchArea.x + searchArea.width + y: 0 + width: parent.width - x + height: parent.height + color: parent.backgroundColor + opacity: parent.backgroundOpacity + } + //bottom + Rectangle { + x: searchArea.x + y: 0 + width: searchArea.width + height: searchArea.y + color: parent.backgroundColor + opacity: parent.backgroundOpacity + } + //outline + Rectangle { + x: searchArea.x + y: searchArea.y + width: searchArea.width + height: searchArea.height + color: "transparent" + border { + width: 3 + color: Kube.Colors.highlightColor + } + Rectangle { + anchors.fill: parent + color: parent.parent.backgroundColor + opacity: parent.parent.searchAreaOpacity + } + } + + + Rectangle { + id: filterField + enabled: true + parent: ApplicationWindow.overlay + + anchors { + horizontalCenter: parent.horizontalCenter + } + y: parent.height / 3 + height: Kube.Units.gridUnit * 2 + width: Kube.Units.gridUnit * 30 + radius: Kube.Units.smallSpacing + + color: Kube.Colors.darkBackgroundColor + + states: [ + State { + name: "searchInProgress" + when: find.text.length != 0 + PropertyChanges {target: filterField; y: Kube.Units.gridUnit} + PropertyChanges {target: root; searchAreaOpacity: 0} + } + ] + + transitions: Transition { + NumberAnimation { properties: "y"; easing.type: Easing.InOutQuad } + } + + function clearSearch() { + find.text = "" + root.close() + } + + Shortcut { + sequences: [StandardKey.Cancel] + onActivated: filterField.clearSearch() + } + + RowLayout { + anchors { + verticalCenter: parent.verticalCenter + } + + width: parent.width - Kube.Units.smallSpacing + spacing: 0 + + Kube.IconButton { + iconName: Kube.Icons.remove + activeFocusOnTab: visible + onClicked: filterField.clearSearch() + } + + Kube.TextField { + id: find + Layout.fillWidth: true + placeholderText: qsTr("Filter...") + onTextChanged: root.filter = text + activeFocusOnTab: visible + focus: visible + Keys.onEscapePressed: filterField.clearSearch() + } + } + } +} 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 { property int count: contentItems.length default property alias contentItems: content.data + property rect searchArea: null + property string filter: "" + property var searchObject: null + function triggerSearch() { + root.searchObject = searchComponent.createObject(root) + } + function clearSearch() { + if (root.searchObject) { + root.searchObject.close() + root.searchObject = null + } + } + property bool __aborted: false //This signal will be emitted once all initial properties have been set and the view is ready to load @@ -104,4 +117,16 @@ FocusScope { id: content anchors.fill: parent } + + Component { + id: searchComponent + Kube.SearchPopup { + searchArea: root.searchArea + onFilterChanged: { + root.filter = filter + } + } + + } + } diff --git a/framework/qmldir b/framework/qmldir index 808563c9..b4d4fc8e 100644 --- a/framework/qmldir +++ b/framework/qmldir @@ -11,6 +11,7 @@ EditAccount 1.0 EditAccount.qml LoginAccount 1.0 LoginAccount.qml Outbox 1.0 Outbox.qml HelpPopup 1.0 HelpPopup.qml +SearchPopup 1.0 SearchPopup.qml NotificationPopup 1.0 NotificationPopup.qml Icon 1.0 Icon.qml IconButton 1.0 IconButton.qml diff --git a/views/conversation/qml/View.qml b/views/conversation/qml/View.qml index 89e6379c..2a5e3d0c 100644 --- a/views/conversation/qml/View.qml +++ b/views/conversation/qml/View.qml @@ -29,6 +29,18 @@ Kube.View { id: root property alias currentAccount: accountFolderview.currentAccount + //We have to hardcode because all the mapToItem/mapFromItem functions are garbage + searchArea: Qt.rect(ApplicationWindow.window.sidebarWidth + mailListView.parent.x, 0, (mailView.x + mailView.width) - mailListView.parent.x, (mailView.y + mailView.height) - mailListView.y) + onFilterChanged: { + mailListView.filter = filter + Kube.Fabric.postMessage(Kube.Messages.searchString, {"searchString": filter}) + } + + Kube.Listener { + filter: Kube.Messages.search + onMessageReceived: root.triggerSearch() + } + Shortcut { sequences: ['j'] onActivated: Kube.Fabric.postMessage(Kube.Messages.selectNextConversation, {}) @@ -156,12 +168,10 @@ Kube.View { Layout.minimumWidth: Kube.Units.gridUnit * 10 Kube.Listener { filter: Kube.Messages.folderSelection - onMessageReceived: mailListView.parentFolder = message.folder - } - - Kube.Listener { - filter: Kube.Messages.search - onMessageReceived: mailListView.showFilter = true + onMessageReceived: { + root.clearSearch() + mailListView.parentFolder = message.folder + } } onCurrentMailChanged: { Kube.Fabric.postMessage(Kube.Messages.mailSelection, {"mail": currentMail}) @@ -210,5 +220,4 @@ Kube.View { } } } - } -- cgit v1.2.3