summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2017-04-16 17:47:48 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2017-04-16 17:47:48 +0200
commitef8a9f2f1d9f91358541b83fab63603aa3001bff (patch)
tree205a945c83a5029c7f700c0cb9c682a99fba30b2
parent899ca952964a09bf2c2304b42d2ce0d859c99c39 (diff)
downloadkube-ef8a9f2f1d9f91358541b83fab63603aa3001bff.tar.gz
kube-ef8a9f2f1d9f91358541b83fab63603aa3001bff.zip
Don't thread drafts and sent
To do this we: * Expose from the model wether or not the model is threaded * Set the relevant properties from the model on the controller (so we can switch between aggregate and non-aggregate versions) * Keep the controller in the view it belongs to. While this works it highlights a couple of issues: * Controllers are view specific and should be kept within the view. * The actions we execute in the controller are closely related to the model. The model is essentially what the user sees, and therefore what he operatees on. * Sink should perhaps expose aggregates better. We have to pass around the values from the model because the model dispatches between aggregate and non-aggregate property depending on the threaded state. Similary the controller operates on the thread or not depending on the threaded state. Perhaps it would be more useful if sink actually returned the aggregate somehow, with the regular properties. That way the controller could use the regular properties from the entity it gets (which would simply either be the aggregate or non-aggregate depending on the executed query). If the aggregate already contains all matched ids, then we would also not have to execute an additional query to get the thread again, the modification would simply be applied to all ids originally returned.
-rw-r--r--components/kube/contents/ui/Kube.qml22
-rw-r--r--framework/qml/ConversationView.qml1
-rw-r--r--framework/qml/MailListView.qml35
-rw-r--r--framework/src/domain/mailcontroller.cpp32
-rw-r--r--framework/src/domain/mailcontroller.h8
-rw-r--r--framework/src/domain/maillistmodel.cpp47
-rw-r--r--framework/src/domain/maillistmodel.h7
7 files changed, 109 insertions, 43 deletions
diff --git a/components/kube/contents/ui/Kube.qml b/components/kube/contents/ui/Kube.qml
index 41e970c6..979f7bd5 100644
--- a/components/kube/contents/ui/Kube.qml
+++ b/components/kube/contents/ui/Kube.qml
@@ -89,15 +89,6 @@ Controls2.ApplicationWindow {
89 //END ActionHandler 89 //END ActionHandler
90 90
91 //Controller 91 //Controller
92 Kube.MailController {
93 id: mailController
94 Binding on threadLeader {
95 //!! checks for the availability of the type
96 when: !!mailListView.currentMail
97 value: mailListView.currentMail
98 }
99 }
100
101 Kube.FolderController { 92 Kube.FolderController {
102 id: folderController 93 id: folderController
103 Binding on folder { 94 Binding on folder {
@@ -119,19 +110,6 @@ Controls2.ApplicationWindow {
119 onActivated: folderController.synchronizeAction.execute() 110 onActivated: folderController.synchronizeAction.execute()
120 enabled: folderController.synchronizeAction.enabled 111 enabled: folderController.synchronizeAction.enabled
121 } 112 }
122 Shortcut {
123 sequence: StandardKey.Delete
124 onActivated: mailController.moveToTrashAction.execute()
125 enabled: mailController.moveToTrashAction.enabled
126 }
127 Shortcut {
128 sequence: StandardKey.MoveToNextLine
129 onActivated: mailListView.currentIndex++
130 }
131 Shortcut {
132 sequence: StandardKey.MoveToPreviousLine
133 onActivated: mailListView.currentIndex--
134 }
135 //END Shortcuts 113 //END Shortcuts
136 114
137 //BEGIN background 115 //BEGIN background
diff --git a/framework/qml/ConversationView.qml b/framework/qml/ConversationView.qml
index 8c6e2d38..83771925 100644
--- a/framework/qml/ConversationView.qml
+++ b/framework/qml/ConversationView.qml
@@ -149,6 +149,7 @@ Rectangle {
149 when: !!root.currentMail 149 when: !!root.currentMail
150 value: root.currentMail 150 value: root.currentMail
151 } 151 }
152 operateOnThreads: false
152 } 153 }
153 154
154 Timer { 155 Timer {
diff --git a/framework/qml/MailListView.qml b/framework/qml/MailListView.qml
index 1e0123cc..27fae7c2 100644
--- a/framework/qml/MailListView.qml
+++ b/framework/qml/MailListView.qml
@@ -28,6 +28,9 @@ Item {
28 property variant parentFolder 28 property variant parentFolder
29 property variant currentMail: null 29 property variant currentMail: null
30 property bool isDraft : false 30 property bool isDraft : false
31 property bool isImportant : false
32 property bool isTrash : false
33 property bool isUnread : false
31 property int currentIndex 34 property int currentIndex
32 property string filterString: searchBar.text; 35 property string filterString: searchBar.text;
33 36
@@ -35,6 +38,34 @@ Item {
35 currentMail = null 38 currentMail = null
36 } 39 }
37 40
41 Kube.MailController {
42 id: mailController
43 Binding on mail {
44 //!! checks for the availability of the type
45 when: !!root.currentMail
46 value: root.currentMail
47 }
48 unread: root.isUnread
49 trash: root.isUnread
50 important: root.isUnread
51 draft: root.isUnread
52 operateOnThreads: mailListModel.isThreaded
53 }
54
55 Shortcut {
56 sequence: StandardKey.Delete
57 onActivated: mailController.moveToTrashAction.execute()
58 enabled: mailController.moveToTrashAction.enabled
59 }
60 Shortcut {
61 sequence: StandardKey.MoveToNextLine
62 onActivated: root.currentIndex++
63 }
64 Shortcut {
65 sequence: StandardKey.MoveToPreviousLine
66 onActivated: root.currentIndex--
67 }
68
38 ToolBar { 69 ToolBar {
39 id: toolbar 70 id: toolbar
40 71
@@ -142,9 +173,13 @@ Item {
142 onCurrentItemChanged: { 173 onCurrentItemChanged: {
143 root.currentMail = currentItem.currentData.domainObject; 174 root.currentMail = currentItem.currentData.domainObject;
144 root.isDraft = currentItem.currentData.draft; 175 root.isDraft = currentItem.currentData.draft;
176 root.isTrash = currentItem.currentData.trash;
177 root.isImportant = currentItem.currentData.important;
178 root.isUnread = currentItem.currentData.unread;
145 } 179 }
146 180
147 model: Kube.MailListModel { 181 model: Kube.MailListModel {
182 id: mailListModel
148 parentFolder: root.parentFolder 183 parentFolder: root.parentFolder
149 filter: root.filterString 184 filter: root.filterString
150 } 185 }
diff --git a/framework/src/domain/mailcontroller.cpp b/framework/src/domain/mailcontroller.cpp
index fe02afc3..a6c5c555 100644
--- a/framework/src/domain/mailcontroller.cpp
+++ b/framework/src/domain/mailcontroller.cpp
@@ -39,7 +39,10 @@ MailController::MailController()
39 action_moveToFolder{new Kube::ControllerAction{this, &MailController::moveToFolder}} 39 action_moveToFolder{new Kube::ControllerAction{this, &MailController::moveToFolder}}
40{ 40{
41 QObject::connect(this, &MailController::mailChanged, &MailController::updateActions); 41 QObject::connect(this, &MailController::mailChanged, &MailController::updateActions);
42 QObject::connect(this, &MailController::threadLeaderChanged, &MailController::updateActions); 42 QObject::connect(this, &MailController::importantChanged, &MailController::updateActions);
43 QObject::connect(this, &MailController::draftChanged, &MailController::updateActions);
44 QObject::connect(this, &MailController::trashChanged, &MailController::updateActions);
45 QObject::connect(this, &MailController::unreadChanged, &MailController::updateActions);
43 updateActions(); 46 updateActions();
44} 47}
45 48
@@ -47,24 +50,21 @@ void MailController::runModification(const std::function<void(ApplicationDomain:
47{ 50{
48 if (auto mail = getMail()) { 51 if (auto mail = getMail()) {
49 f(*mail); 52 f(*mail);
50 run(Store::modify(*mail)); 53 if (getOperateOnThreads()) {
51 } else if (auto mail = getThreadLeader()) { 54 run(Store::modify(Sink::StandardQueries::completeThread(*mail), *mail));
52 f(*mail); 55 } else {
53 run(Store::modify(Sink::StandardQueries::completeThread(*mail), *mail)); 56 run(Store::modify(*mail));
57 }
54 } 58 }
55} 59}
56 60
57void MailController::updateActions() 61void MailController::updateActions()
58{ 62{
59 auto mail = getMail(); 63 if (auto mail = getMail()) {
60 if (!mail) { 64 action_moveToTrash->setEnabled(!getTrash());
61 mail= getThreadLeader(); 65 action_restoreFromTrash->setEnabled(getTrash());
62 } 66 action_markAsRead->setEnabled(getUnread());
63 if (mail) { 67 action_markAsUnread->setEnabled(getUnread());
64 action_moveToTrash->setEnabled(!mail->getTrash());
65 action_restoreFromTrash->setEnabled(mail->getTrash());
66 action_markAsRead->setEnabled(mail->getUnread());
67 action_markAsUnread->setEnabled(!mail->getUnread());
68 } else { 68 } else {
69 action_moveToTrash->setEnabled(false); 69 action_moveToTrash->setEnabled(false);
70 action_restoreFromTrash->setEnabled(false); 70 action_restoreFromTrash->setEnabled(false);
@@ -99,8 +99,8 @@ void MailController::markAsImportant()
99 99
100void MailController::toggleImportant() 100void MailController::toggleImportant()
101{ 101{
102 runModification([] (ApplicationDomain::Mail &mail) { 102 runModification([this] (ApplicationDomain::Mail &mail) {
103 mail.setImportant(!mail.getImportant()); 103 mail.setImportant(!getImportant());
104 SinkLog() << "Toggle important " << mail.identifier() << mail.getImportant(); 104 SinkLog() << "Toggle important " << mail.identifier() << mail.getImportant();
105 }); 105 });
106} 106}
diff --git a/framework/src/domain/mailcontroller.h b/framework/src/domain/mailcontroller.h
index f6613558..0bc000f1 100644
--- a/framework/src/domain/mailcontroller.h
+++ b/framework/src/domain/mailcontroller.h
@@ -25,9 +25,15 @@
25class MailController : public Kube::Controller 25class MailController : public Kube::Controller
26{ 26{
27 Q_OBJECT 27 Q_OBJECT
28 //Use this instead of mail property to get overall status of thread.
29 KUBE_CONTROLLER_PROPERTY(bool, Unread, unread)
30 KUBE_CONTROLLER_PROPERTY(bool, Important, important)
31 KUBE_CONTROLLER_PROPERTY(bool, Trash, trash)
32 KUBE_CONTROLLER_PROPERTY(bool, Draft, draft)
33
28 KUBE_CONTROLLER_PROPERTY(Sink::ApplicationDomain::Mail::Ptr, Mail, mail) 34 KUBE_CONTROLLER_PROPERTY(Sink::ApplicationDomain::Mail::Ptr, Mail, mail)
29 KUBE_CONTROLLER_PROPERTY(Sink::ApplicationDomain::Mail::Ptr, ThreadLeader, threadLeader)
30 KUBE_CONTROLLER_PROPERTY(Sink::ApplicationDomain::Folder::Ptr, TargetFolder, targetFolder) 35 KUBE_CONTROLLER_PROPERTY(Sink::ApplicationDomain::Folder::Ptr, TargetFolder, targetFolder)
36 KUBE_CONTROLLER_PROPERTY(bool, OperateOnThreads, operateOnThreads)
31 KUBE_CONTROLLER_ACTION(markAsRead) 37 KUBE_CONTROLLER_ACTION(markAsRead)
32 KUBE_CONTROLLER_ACTION(markAsUnread) 38 KUBE_CONTROLLER_ACTION(markAsUnread)
33 KUBE_CONTROLLER_ACTION(markAsImportant) 39 KUBE_CONTROLLER_ACTION(markAsImportant)
diff --git a/framework/src/domain/maillistmodel.cpp b/framework/src/domain/maillistmodel.cpp
index 83340f69..0f477624 100644
--- a/framework/src/domain/maillistmodel.cpp
+++ b/framework/src/domain/maillistmodel.cpp
@@ -114,9 +114,17 @@ QVariant MailListModel::data(const QModelIndex &idx, int role) const
114 case Date: 114 case Date:
115 return mail->getDate(); 115 return mail->getDate();
116 case Unread: 116 case Unread:
117 return mail->getProperty("unreadCollected").toList().contains(true); 117 if (mIsThreaded) {
118 return mail->getProperty("unreadCollected").toList().contains(true);
119 } else {
120 return mail->getUnread();
121 }
118 case Important: 122 case Important:
119 return mail->getProperty("importantCollected").toList().contains(true); 123 if (mIsThreaded) {
124 return mail->getProperty("importantCollected").toList().contains(true);
125 } else {
126 return mail->getImportant();
127 }
120 case Draft: 128 case Draft:
121 return mail->getDraft(); 129 return mail->getDraft();
122 case Sent: 130 case Sent:
@@ -133,7 +141,11 @@ QVariant MailListModel::data(const QModelIndex &idx, int role) const
133 } 141 }
134 return mail->getMimeMessage(); 142 return mail->getMimeMessage();
135 case ThreadSize: 143 case ThreadSize:
136 return mail->getProperty("count").toInt(); 144 if (mIsThreaded) {
145 return mail->getProperty("count").toInt();
146 } else {
147 return 1;
148 }
137 case Mail: 149 case Mail:
138 return QVariant::fromValue(mail); 150 return QVariant::fromValue(mail);
139 case Incomplete: 151 case Incomplete:
@@ -176,6 +188,11 @@ void MailListModel::runQuery(const Sink::Query &query)
176 setSourceModel(m_model.data()); 188 setSourceModel(m_model.data());
177} 189}
178 190
191bool MailListModel::isThreaded() const
192{
193 return mIsThreaded;
194}
195
179void MailListModel::setParentFolder(const QVariant &parentFolder) 196void MailListModel::setParentFolder(const QVariant &parentFolder)
180{ 197{
181 using namespace Sink::ApplicationDomain; 198 using namespace Sink::ApplicationDomain;
@@ -189,11 +206,33 @@ void MailListModel::setParentFolder(const QVariant &parentFolder)
189 return; 206 return;
190 } 207 }
191 mCurrentQueryItem = folder->identifier(); 208 mCurrentQueryItem = folder->identifier();
192 Sink::Query query = Sink::StandardQueries::threadLeaders(*folder); 209 if (folder->getSpecialPurpose().contains(Sink::ApplicationDomain::SpecialPurpose::Mail::drafts) ||
210 folder->getSpecialPurpose().contains(Sink::ApplicationDomain::SpecialPurpose::Mail::sent)) {
211 mIsThreaded = false;
212 } else {
213 mIsThreaded = true;
214 }
215 emit isThreadedChanged();
216
217 Sink::Query query = [&] {
218 if (mIsThreaded) {
219 return Sink::StandardQueries::threadLeaders(*folder);
220 } else {
221 Sink::Query query;
222 query.setId("threadleaders-unthreaded");
223 if (!folder->resourceInstanceIdentifier().isEmpty()) {
224 query.resourceFilter(folder->resourceInstanceIdentifier());
225 }
226 query.filter<Sink::ApplicationDomain::Mail::Folder>(*folder);
227 query.sort<Sink::ApplicationDomain::Mail::Date>();
228 return query;
229 }
230 }();
193 if (!folder->getSpecialPurpose().contains(Sink::ApplicationDomain::SpecialPurpose::Mail::trash)) { 231 if (!folder->getSpecialPurpose().contains(Sink::ApplicationDomain::SpecialPurpose::Mail::trash)) {
194 //Filter trash if this is not a trash folder 232 //Filter trash if this is not a trash folder
195 query.filter<Sink::ApplicationDomain::Mail::Trash>(false); 233 query.filter<Sink::ApplicationDomain::Mail::Trash>(false);
196 } 234 }
235
197 query.setFlags(Sink::Query::LiveQuery); 236 query.setFlags(Sink::Query::LiveQuery);
198 query.limit(100); 237 query.limit(100);
199 query.request<Mail::Subject>(); 238 query.request<Mail::Subject>();
diff --git a/framework/src/domain/maillistmodel.h b/framework/src/domain/maillistmodel.h
index 44347661..5ed081f4 100644
--- a/framework/src/domain/maillistmodel.h
+++ b/framework/src/domain/maillistmodel.h
@@ -32,6 +32,7 @@ class MailListModel : public QSortFilterProxyModel
32 Q_PROPERTY (QVariant parentFolder READ parentFolder WRITE setParentFolder) 32 Q_PROPERTY (QVariant parentFolder READ parentFolder WRITE setParentFolder)
33 Q_PROPERTY (QVariant mail READ mail WRITE setMail) 33 Q_PROPERTY (QVariant mail READ mail WRITE setMail)
34 Q_PROPERTY (QString filter READ filter WRITE setFilter) 34 Q_PROPERTY (QString filter READ filter WRITE setFilter)
35 Q_PROPERTY (bool isThreaded READ isThreaded NOTIFY isThreadedChanged)
35 36
36public: 37public:
37 enum Status { 38 enum Status {
@@ -49,6 +50,8 @@ public:
49 bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE; 50 bool lessThan(const QModelIndex &left, const QModelIndex &right) const Q_DECL_OVERRIDE;
50 bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE; 51 bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_OVERRIDE;
51 52
53 bool isThreaded() const;
54
52 enum Roles { 55 enum Roles {
53 Subject = Qt::UserRole + 1, 56 Subject = Qt::UserRole + 1,
54 Sender, 57 Sender,
@@ -84,6 +87,9 @@ public:
84 void setFilter(const QString &mail); 87 void setFilter(const QString &mail);
85 QString filter() const; 88 QString filter() const;
86 89
90signals:
91 void isThreadedChanged();
92
87private: 93private:
88 void fetchMail(Sink::ApplicationDomain::Mail::Ptr mail); 94 void fetchMail(Sink::ApplicationDomain::Mail::Ptr mail);
89 95
@@ -91,4 +97,5 @@ private:
91 bool mFetchMails = false; 97 bool mFetchMails = false;
92 QSet<QByteArray> mFetchedMails; 98 QSet<QByteArray> mFetchedMails;
93 QByteArray mCurrentQueryItem; 99 QByteArray mCurrentQueryItem;
100 bool mIsThreaded = true;
94}; 101};