summaryrefslogtreecommitdiffstats
path: root/framework
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2018-03-02 12:00:54 +0100
committerChristian Mollekopf <chrigi_1@fastmail.fm>2018-03-02 12:03:04 +0100
commit03e8aabf1754f5061f207d2c9c082ba6199db0e5 (patch)
tree66124163b4da541dfb17c30299b9aeb82f9fad79 /framework
parent795d551639340d81641aa8c6eabff1776e0b2ee1 (diff)
downloadkube-03e8aabf1754f5061f207d2c9c082ba6199db0e5.tar.gz
kube-03e8aabf1754f5061f207d2c9c082ba6199db0e5.zip
Visualize that a folder has new mails.
We listen for new mail notifications, and highlight the folder accordingly.
Diffstat (limited to 'framework')
-rw-r--r--framework/qml/FolderListView.qml34
-rw-r--r--framework/qml/TreeView.qml33
-rw-r--r--framework/src/domain/folderlistmodel.cpp41
-rw-r--r--framework/src/domain/folderlistmodel.h8
-rw-r--r--framework/src/sinkfabric.cpp5
5 files changed, 86 insertions, 35 deletions
diff --git a/framework/qml/FolderListView.qml b/framework/qml/FolderListView.qml
index 25c6cbe5..a24a9ff6 100644
--- a/framework/qml/FolderListView.qml
+++ b/framework/qml/FolderListView.qml
@@ -30,6 +30,33 @@ Kube.TreeView {
30 Controls1.TableViewColumn { 30 Controls1.TableViewColumn {
31 title: "Name" 31 title: "Name"
32 role: "name" 32 role: "name"
33 delegate: Item {
34 DropArea {
35 anchors.fill: parent
36 Rectangle {
37 anchors.fill: parent
38 color: Kube.Colors.viewBackgroundColor
39 opacity: 0.3
40 visible: parent.containsDrag
41 }
42 onDropped: {
43 Kube.Fabric.postMessage(Kube.Messages.moveToFolder, {"mail": drop.source.mail, "folder": model.domainObject})
44 drop.accept(Qt.MoveAction)
45 drop.source.visible = false
46 }
47 }
48
49 Kube.Label {
50 anchors {
51 verticalCenter: parent.verticalCenter
52 left: parent.left
53 right: parent.right
54 }
55 text: styleData.value
56 elide: Qt.ElideRight
57 color: model.hasNewData ? Kube.Colors.highlightColor : Kube.Colors.viewBackgroundColor
58 }
59 }
33 } 60 }
34 61
35 model: Kube.FolderListModel { 62 model: Kube.FolderListModel {
@@ -43,11 +70,4 @@ Kube.TreeView {
43 Kube.Fabric.postMessage(Kube.Messages.folderSelection, {"folder": model.data(index, Kube.FolderListModel.DomainObject), 70 Kube.Fabric.postMessage(Kube.Messages.folderSelection, {"folder": model.data(index, Kube.FolderListModel.DomainObject),
44 "trash": model.data(index, Kube.FolderListModel.Trash)}); 71 "trash": model.data(index, Kube.FolderListModel.Trash)});
45 } 72 }
46
47
48 onDropped: {
49 Kube.Fabric.postMessage(Kube.Messages.moveToFolder, {"mail": drop.source.mail, "folder": model.domainObject})
50 drop.accept(Qt.MoveAction)
51 drop.source.visible = false
52 }
53} 73}
diff --git a/framework/qml/TreeView.qml b/framework/qml/TreeView.qml
index eb140514..7b9a1103 100644
--- a/framework/qml/TreeView.qml
+++ b/framework/qml/TreeView.qml
@@ -36,12 +36,16 @@ FocusScope {
36 * FIXME: This is what QItemSelectionModel selection vs current selection are for. Try to use that instead. 36 * FIXME: This is what QItemSelectionModel selection vs current selection are for. Try to use that instead.
37 */ 37 */
38 property var activeIndex: null 38 property var activeIndex: null
39 signal dropped(var drop, var model)
40 signal activated(var index) 39 signal activated(var index)
41 onActivated: { 40 onActivated: {
42 activeIndex = index 41 activeIndex = index
43 } 42 }
44 43
44 function indexFromRow(row) {
45 //FIXME Uses internal API to get to the model index
46 return treeView.__model.mapRowToModelIndex(row)
47 }
48
45 Flickable { 49 Flickable {
46 id: flickableItem 50 id: flickableItem
47 51
@@ -115,8 +119,7 @@ FocusScope {
115 style: TreeViewStyle { 119 style: TreeViewStyle {
116 rowDelegate: Controls2.Control { 120 rowDelegate: Controls2.Control {
117 id: delegateRoot 121 id: delegateRoot
118 //FIXME Uses internal API to get to the model index 122 property bool isActive: root.activeIndex === indexFromRow(styleData.row)
119 property bool isActive: root.activeIndex === treeView.__model.mapRowToModelIndex(styleData.row)
120 height: Kube.Units.gridUnit * 1.5 123 height: Kube.Units.gridUnit * 1.5
121 //FIXME This is the only way I could find to get the correct width. parent.width is way to wide 124 //FIXME This is the only way I could find to get the correct width. parent.width is way to wide
122 width: parent.parent.parent ? parent.parent.parent.width : 0 125 width: parent.parent.parent ? parent.parent.parent.width : 0
@@ -145,30 +148,6 @@ FocusScope {
145 text: styleData.isExpanded ? "-" : "+" 148 text: styleData.isExpanded ? "-" : "+"
146 } 149 }
147 150
148 itemDelegate: Item {
149 DropArea {
150 anchors.fill: parent
151 Rectangle {
152 anchors.fill: parent
153 color: Kube.Colors.viewBackgroundColor
154 opacity: 0.3
155 visible: parent.containsDrag
156 }
157 onDropped: root.dropped(drop, model)
158 }
159
160 Kube.Label {
161 anchors {
162 verticalCenter: parent.verticalCenter
163 left: parent.left
164 right: parent.right
165 }
166 text: styleData.value
167 elide: Qt.ElideRight
168 color: Kube.Colors.viewBackgroundColor
169 }
170 }
171
172 backgroundColor: Kube.Colors.textColor 151 backgroundColor: Kube.Colors.textColor
173 highlightedTextColor: Kube.Colors.highlightedTextColor 152 highlightedTextColor: Kube.Colors.highlightedTextColor
174 } 153 }
diff --git a/framework/src/domain/folderlistmodel.cpp b/framework/src/domain/folderlistmodel.cpp
index f929b01e..6555abbf 100644
--- a/framework/src/domain/folderlistmodel.cpp
+++ b/framework/src/domain/folderlistmodel.cpp
@@ -21,6 +21,8 @@
21#include "folderlistmodel.h" 21#include "folderlistmodel.h"
22#include <sink/store.h> 22#include <sink/store.h>
23#include <sink/log.h> 23#include <sink/log.h>
24#include <sink/notifier.h>
25#include <sink/notification.h>
24#include <settings/settings.h> 26#include <settings/settings.h>
25 27
26using namespace Sink; 28using namespace Sink;
@@ -59,6 +61,7 @@ QHash< int, QByteArray > FolderListModel::roleNames() const
59 roles[DomainObject] = "domainObject"; 61 roles[DomainObject] = "domainObject";
60 roles[Status] = "status"; 62 roles[Status] = "status";
61 roles[Trash] = "trash"; 63 roles[Trash] = "trash";
64 roles[HasNewData] = "hasNewData";
62 65
63 return roles; 66 return roles;
64} 67}
@@ -92,14 +95,46 @@ QVariant FolderListModel::data(const QModelIndex &idx, int role) const
92 return folder->getSpecialPurpose().contains(Sink::ApplicationDomain::SpecialPurpose::Mail::trash); 95 return folder->getSpecialPurpose().contains(Sink::ApplicationDomain::SpecialPurpose::Mail::trash);
93 } 96 }
94 return false; 97 return false;
98 case HasNewData:
99 return mHasNewData.contains(folder->identifier());
95 } 100 }
96 return QSortFilterProxyModel::data(idx, role); 101 return QSortFilterProxyModel::data(idx, role);
97} 102}
98 103
104static QModelIndex findRecursive(QAbstractItemModel *model, const QModelIndex &parent, int role, const QVariant &value)
105{
106 for (auto row = 0; row < model->rowCount(parent); row++) {
107 const auto idx = model->index(row, 0, parent);
108 if (model->data(idx, role) == value) {
109 return idx;
110 }
111 auto result = findRecursive(model, idx, role, value);
112 if (result.isValid()) {
113 return result;
114 }
115 }
116 return {};
117}
118
99void FolderListModel::runQuery(const Query &query) 119void FolderListModel::runQuery(const Query &query)
100{ 120{
101 mModel = Store::loadModel<Folder>(query); 121 mModel = Store::loadModel<Folder>(query);
102 setSourceModel(mModel.data()); 122 setSourceModel(mModel.data());
123
124 Sink::Query resourceQuery;
125 resourceQuery.setFilter(query.getResourceFilter());
126 mNotifier.reset(new Sink::Notifier{resourceQuery});
127 mNotifier->registerHandler([&](const Sink::Notification &notification) {
128 if (notification.type == Sink::Notification::Info && notification.code == ApplicationDomain::NewContentAvailable) {
129 if (!notification.entities.isEmpty()) {
130 mHasNewData.insert(notification.entities.first());
131 auto idx = findRecursive(this, {}, Id, QVariant::fromValue(notification.entities.first()));
132 if (idx.isValid()) {
133 emit dataChanged(idx, idx);
134 }
135 }
136 }
137 });
103} 138}
104 139
105void FolderListModel::setAccountId(const QVariant &accountId) 140void FolderListModel::setAccountId(const QVariant &accountId)
@@ -164,6 +199,12 @@ bool FolderListModel::acceptRow(int sourceRow, const QModelIndex &sourceParent)
164 return enabled; 199 return enabled;
165} 200}
166 201
202void FolderListModel::fetchMore(const QModelIndex &parent)
203{
204 mHasNewData.remove(parent.data(Id).toByteArray());
205 QAbstractItemModel::fetchMore(parent);
206}
207
167void FolderListModel::setFolderId(const QVariant &folderId) 208void FolderListModel::setFolderId(const QVariant &folderId)
168{ 209{
169 const auto folder = folderId.toString().toUtf8(); 210 const auto folder = folderId.toString().toUtf8();
diff --git a/framework/src/domain/folderlistmodel.h b/framework/src/domain/folderlistmodel.h
index 738cf4a0..d3bef397 100644
--- a/framework/src/domain/folderlistmodel.h
+++ b/framework/src/domain/folderlistmodel.h
@@ -22,6 +22,8 @@
22 22
23#include <krecursivefilterproxymodel.h> 23#include <krecursivefilterproxymodel.h>
24#include <QSharedPointer> 24#include <QSharedPointer>
25#include <QSet>
26#include <sink/notifier.h>
25 27
26namespace Sink { 28namespace Sink {
27 class Query; 29 class Query;
@@ -54,7 +56,8 @@ public:
54 Id, 56 Id,
55 DomainObject, 57 DomainObject,
56 Status, 58 Status,
57 Trash 59 Trash,
60 HasNewData
58 }; 61 };
59 Q_ENUMS(Roles) 62 Q_ENUMS(Roles)
60 63
@@ -68,8 +71,11 @@ public:
68protected: 71protected:
69 bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE; 72 bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE;
70 bool acceptRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE; 73 bool acceptRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE;
74 void fetchMore(const QModelIndex &left) Q_DECL_OVERRIDE;
71 75
72private: 76private:
73 void runQuery(const Sink::Query &query); 77 void runQuery(const Sink::Query &query);
74 QSharedPointer<QAbstractItemModel> mModel; 78 QSharedPointer<QAbstractItemModel> mModel;
79 QSet<QByteArray> mHasNewData;
80 QScopedPointer<Sink::Notifier> mNotifier;
75}; 81};
diff --git a/framework/src/sinkfabric.cpp b/framework/src/sinkfabric.cpp
index 8492f272..916cc8fa 100644
--- a/framework/src/sinkfabric.cpp
+++ b/framework/src/sinkfabric.cpp
@@ -203,6 +203,11 @@ public:
203 if (notification.code == Sink::ApplicationDomain::TransmissionSuccess) { 203 if (notification.code == Sink::ApplicationDomain::TransmissionSuccess) {
204 message["type"] = "info"; 204 message["type"] = "info";
205 message["message"] = QObject::tr("A message has been sent."); 205 message["message"] = QObject::tr("A message has been sent.");
206 } else if (notification.code == Sink::ApplicationDomain::NewContentAvailable) {
207 message["type"] = "info";
208 if (!notification.entities.isEmpty()) {
209 message["folderId"] = notification.entities.first();
210 }
206 } else { 211 } else {
207 return; 212 return;
208 } 213 }