Messagelib

sortorder.cpp
1 /******************************************************************************
2  *
3  * SPDX-FileCopyrightText: 2009 Thomas McGuire <[email protected]>
4  *
5  * SPDX-License-Identifier: GPL-2.0-or-later
6  *
7  *******************************************************************************/
8 #include "core/sortorder.h"
9 
10 #include "messagelistutil.h"
11 #include "messagelistutil_p.h"
12 
13 #include <KLocalizedString>
14 
15 #include <QMetaEnum>
16 
17 using namespace MessageList::Core;
18 
19 SortOrder::SortOrder()
20  : mMessageSorting(SortMessagesByDateTime)
21  , mMessageSortDirection(Descending)
22  , mGroupSorting(NoGroupSorting)
23  , mGroupSortDirection(Ascending)
24 {
25 }
26 
27 SortOrder::GroupSorting SortOrder::groupSorting() const
28 {
29  return mGroupSorting;
30 }
31 
32 void SortOrder::setGroupSorting(SortOrder::GroupSorting gs)
33 {
34  mGroupSorting = gs;
35 }
36 
37 SortOrder::SortDirection SortOrder::groupSortDirection() const
38 {
39  return mGroupSortDirection;
40 }
41 
42 void SortOrder::setGroupSortDirection(SortOrder::SortDirection groupSortDirection)
43 {
44  mGroupSortDirection = groupSortDirection;
45 }
46 
47 SortOrder::MessageSorting SortOrder::messageSorting() const
48 {
49  return mMessageSorting;
50 }
51 
52 void SortOrder::setMessageSorting(SortOrder::MessageSorting ms)
53 {
54  mMessageSorting = ms;
55 }
56 
57 SortOrder::SortDirection SortOrder::messageSortDirection() const
58 {
59  return mMessageSortDirection;
60 }
61 
62 void SortOrder::setMessageSortDirection(SortOrder::SortDirection messageSortDirection)
63 {
64  mMessageSortDirection = messageSortDirection;
65 }
66 
67 QVector<QPair<QString, int> > SortOrder::enumerateMessageSortingOptions(Aggregation::Threading t)
68 {
70  ret.append({ i18n("None (Storage Order)"), SortOrder::NoMessageSorting });
71  ret.append({ i18n("By Date/Time"), SortOrder::SortMessagesByDateTime });
72  if (t != Aggregation::NoThreading) {
73  ret.append({ i18n("By Date/Time of Most Recent in Subtree"), SortOrder::SortMessagesByDateTimeOfMostRecent });
74  }
75  ret.append({ i18n("By Sender"), SortOrder::SortMessagesBySender });
76  ret.append({ i18n("By Receiver"), SortOrder::SortMessagesByReceiver });
77  ret.append({ i18n("By Smart Sender/Receiver"), SortOrder::SortMessagesBySenderOrReceiver });
78  ret.append({ i18n("By Subject"), SortOrder::SortMessagesBySubject });
79  ret.append({ i18n("By Size"), SortOrder::SortMessagesBySize });
80  ret.append({ i18n("By Action Item Status"), SortOrder::SortMessagesByActionItemStatus });
81  ret.append({ i18n("By Unread Status"), SortOrder::SortMessagesByUnreadStatus });
82  ret.append({ i18n("By Important Status"), SortOrder::SortMessagesByImportantStatus });
83  ret.append({ i18n("By Attachment Status"), SortOrder::SortMessagesByAttachmentStatus });
84  return ret;
85 }
86 
87 QVector<QPair<QString, int> > SortOrder::enumerateMessageSortDirectionOptions(MessageSorting ms)
88 {
90  if (ms == SortOrder::NoMessageSorting) {
91  return ret;
92  }
93 
94  if (
95  (ms == SortOrder::SortMessagesByDateTime)
96  || (ms == SortOrder::SortMessagesByDateTimeOfMostRecent)
97  ) {
98  ret.append({ i18n("Least Recent on Top"), SortOrder::Ascending });
99  ret.append({ i18n("Most Recent on Top"), SortOrder::Descending });
100  return ret;
101  }
102 
103  ret.append({ i18nc("Sort order for messages", "Ascending"), SortOrder::Ascending });
104  ret.append({ i18nc("Sort order for messages", "Descending"), SortOrder::Descending });
105  return ret;
106 }
107 
108 QVector<QPair<QString, int> > SortOrder::enumerateGroupSortingOptions(Aggregation::Grouping g)
109 {
111  if (g == Aggregation::NoGrouping) {
112  return ret;
113  }
114  if ((g == Aggregation::GroupByDate) || (g == Aggregation::GroupByDateRange)) {
115  ret.append({ i18n("by Date/Time"), SortOrder::SortGroupsByDateTime });
116  } else {
117  ret.append({ i18n("None (Storage Order)"), SortOrder::NoGroupSorting });
118  ret.append({ i18n("by Date/Time of Most Recent Message in Group"), SortOrder::SortGroupsByDateTimeOfMostRecent });
119  }
120 
121  if (g == Aggregation::GroupBySenderOrReceiver) {
122  ret.append({ i18n("by Sender/Receiver"), SortOrder::SortGroupsBySenderOrReceiver });
123  } else if (g == Aggregation::GroupBySender) {
124  ret.append({ i18n("by Sender"), SortOrder::SortGroupsBySender });
125  } else if (g == Aggregation::GroupByReceiver) {
126  ret.append({ i18n("by Receiver"), SortOrder::SortGroupsByReceiver });
127  }
128 
129  return ret;
130 }
131 
132 QVector<QPair<QString, int> > SortOrder::enumerateGroupSortDirectionOptions(Aggregation::Grouping g, GroupSorting gs)
133 {
135  if (g == Aggregation::NoGrouping || gs == SortOrder::NoGroupSorting) {
136  return ret;
137  }
138 
139  if (gs == SortOrder::SortGroupsByDateTimeOfMostRecent) {
140  ret.append({ i18n("Least Recent on Top"), SortOrder::Ascending });
141  ret.append({ i18n("Most Recent on Top"), SortOrder::Descending });
142  return ret;
143  }
144  ret.append({ i18nc("Sort order for mail groups", "Ascending"), SortOrder::Ascending });
145  ret.append({ i18nc("Sort order for mail groups", "Descending"), SortOrder::Descending });
146  return ret;
147 }
148 
150 static bool optionListHasOption(const OptionList &optionList, int optionValue, int defaultOptionValue)
151 {
152  for (const auto &pair : optionList) {
153  if (pair.second == optionValue) {
154  return true;
155  }
156  }
157  if (optionValue != defaultOptionValue) {
158  return false;
159  } else {
160  return true;
161  }
162 }
163 
164 bool SortOrder::validForAggregation(const Aggregation *aggregation) const
165 {
166  OptionList messageSortings = enumerateMessageSortingOptions(aggregation->threading());
167  OptionList messageSortDirections = enumerateMessageSortDirectionOptions(mMessageSorting);
168  OptionList groupSortings = enumerateGroupSortingOptions(aggregation->grouping());
169  OptionList groupSortDirections = enumerateGroupSortDirectionOptions(aggregation->grouping(),
170  mGroupSorting);
171  SortOrder defaultSortOrder = defaultForAggregation(aggregation, SortOrder());
172  bool messageSortingOk = optionListHasOption(messageSortings,
173  mMessageSorting, defaultSortOrder.messageSorting());
174  bool messageSortDirectionOk = optionListHasOption(messageSortDirections, mMessageSortDirection,
175  defaultSortOrder.messageSortDirection());
176 
177  bool groupSortingOk = optionListHasOption(groupSortings, mGroupSorting,
178  defaultSortOrder.groupSorting());
179  bool groupSortDirectionOk = optionListHasOption(groupSortDirections, mGroupSortDirection,
180  defaultSortOrder.groupSortDirection());
181  return messageSortingOk && messageSortDirectionOk
182  && groupSortingOk && groupSortDirectionOk;
183 }
184 
185 SortOrder SortOrder::defaultForAggregation(const Aggregation *aggregation, SortOrder oldSortOrder)
186 {
187  SortOrder newSortOrder;
188 
189  //
190  // First check if we can adopt the message sorting and the message sort direction from
191  // the old sort order. This is mostly true, except, for example, when the old message sorting
192  // was "by most recent in subtree", and the aggregation doesn't use threading.
193  //
194  OptionList messageSortings = enumerateMessageSortingOptions(aggregation->threading());
195  bool messageSortingOk = optionListHasOption(messageSortings,
196  oldSortOrder.messageSorting(),
198  bool messageSortDirectionOk = false;
199  if (messageSortingOk) {
200  OptionList messageSortDirections = enumerateMessageSortDirectionOptions(
201  oldSortOrder.messageSorting());
202  messageSortDirectionOk = optionListHasOption(messageSortDirections, oldSortOrder.messageSortDirection(),
204  }
205 
206  //
207  // Ok, if we can partly adopt the old sort order, set the values now.
208  //
209  if (messageSortingOk) {
210  newSortOrder.setMessageSorting(oldSortOrder.messageSorting());
211  } else {
212  newSortOrder.setMessageSorting(SortMessagesByDateTime);
213  }
214  if (messageSortDirectionOk) {
215  newSortOrder.setMessageSortDirection(oldSortOrder.messageSortDirection());
216  } else {
217  newSortOrder.setMessageSortDirection(Descending);
218  }
219 
220  //
221  // Now set the group sorting and group sort direction, depending on the aggregation.
222  //
223  Aggregation::Grouping grouping = aggregation->grouping();
224  if (grouping == Aggregation::GroupByDate
225  || grouping == Aggregation::GroupByDateRange) {
226  newSortOrder.setGroupSortDirection(Descending);
227  newSortOrder.setGroupSorting(SortGroupsByDateTime);
228  } else if (grouping == Aggregation::GroupByReceiver || grouping == Aggregation::GroupBySender
229  || grouping == Aggregation::GroupBySenderOrReceiver) {
230  newSortOrder.setGroupSortDirection(Descending);
231  switch (grouping) {
232  case Aggregation::GroupByReceiver:
233  newSortOrder.setGroupSorting(SortGroupsByReceiver);
234  break;
235  case Aggregation::GroupBySender:
236  newSortOrder.setGroupSorting(SortGroupsBySender);
237  break;
238  case Aggregation::GroupBySenderOrReceiver:
239  newSortOrder.setGroupSorting(SortGroupsBySenderOrReceiver);
240  break;
241  default:
242  break;
243  }
244  }
245 
246  return newSortOrder;
247 }
248 
249 bool SortOrder::readConfigHelper(KConfigGroup &conf, const QString &id)
250 {
251  if (!conf.hasKey(id + MessageList::Util::messageSortingConfigName())) {
252  return false;
253  }
254  mMessageSorting = messageSortingForName(
255  conf.readEntry(id + MessageList::Util::messageSortingConfigName()));
256  mMessageSortDirection = sortDirectionForName(
257  conf.readEntry(id + MessageList::Util::messageSortDirectionConfigName()));
258  mGroupSorting = groupSortingForName(
259  conf.readEntry(id + MessageList::Util::groupSortingConfigName()));
260  mGroupSortDirection = sortDirectionForName(
261  conf.readEntry(id + MessageList::Util::groupSortDirectionConfigName()));
262  return true;
263 }
264 
265 void SortOrder::readConfig(KConfigGroup &conf, const QString &storageId, bool *storageUsesPrivateSortOrder)
266 {
267  SortOrder privateSortOrder, globalSortOrder;
268  globalSortOrder.readConfigHelper(conf, QStringLiteral("GlobalSortOrder"));
269  *storageUsesPrivateSortOrder = privateSortOrder.readConfigHelper(conf, storageId);
270  if (*storageUsesPrivateSortOrder) {
271  *this = privateSortOrder;
272  } else {
273  *this = globalSortOrder;
274  }
275 }
276 
277 void SortOrder::writeConfig(KConfigGroup &conf, const QString &storageId, bool storageUsesPrivateSortOrder) const
278 {
279  QString id = storageId;
280  if (!storageUsesPrivateSortOrder) {
281  id = QStringLiteral("GlobalSortOrder");
282  conf.deleteEntry(storageId + MessageList::Util::messageSortingConfigName());
283  conf.deleteEntry(storageId + MessageList::Util::messageSortDirectionConfigName());
284  conf.deleteEntry(storageId + MessageList::Util::groupSortingConfigName());
285  conf.deleteEntry(storageId + MessageList::Util::groupSortDirectionConfigName());
286  }
287 
288  conf.writeEntry(id + MessageList::Util::messageSortingConfigName(),
289  nameForMessageSorting(mMessageSorting));
290  conf.writeEntry(id + MessageList::Util::messageSortDirectionConfigName(),
291  nameForSortDirection(mMessageSortDirection));
292  conf.writeEntry(id + MessageList::Util::groupSortingConfigName(),
293  nameForGroupSorting(mGroupSorting));
294  conf.writeEntry(id + MessageList::Util::groupSortDirectionConfigName(),
295  nameForSortDirection(mGroupSortDirection));
296 }
297 
298 bool SortOrder::isValidMessageSorting(SortOrder::MessageSorting ms)
299 {
300  switch (ms) {
301  case SortOrder::NoMessageSorting:
302  case SortOrder::SortMessagesByDateTime:
303  case SortOrder::SortMessagesByDateTimeOfMostRecent:
304  case SortOrder::SortMessagesBySenderOrReceiver:
305  case SortOrder::SortMessagesBySender:
306  case SortOrder::SortMessagesByReceiver:
307  case SortOrder::SortMessagesBySubject:
308  case SortOrder::SortMessagesBySize:
309  case SortOrder::SortMessagesByActionItemStatus:
310  case SortOrder::SortMessagesByUnreadStatus:
311  case SortOrder::SortMessagesByImportantStatus:
312  case SortOrder::SortMessagesByAttachmentStatus:
313  // ok
314  break;
315  default:
316  // b0rken
317  return false;
318  }
319 
320  return true;
321 }
322 
323 const QString SortOrder::nameForSortDirection(SortDirection sortDirection)
324 {
325  int index = staticMetaObject.indexOfEnumerator("SortDirection");
326  return QLatin1String(staticMetaObject.enumerator(index).valueToKey(sortDirection));
327 }
328 
329 const QString SortOrder::nameForMessageSorting(MessageSorting messageSorting)
330 {
331  int index = staticMetaObject.indexOfEnumerator("MessageSorting");
332  return QLatin1String(staticMetaObject.enumerator(index).valueToKey(messageSorting));
333 }
334 
335 const QString SortOrder::nameForGroupSorting(GroupSorting groupSorting)
336 {
337  int index = staticMetaObject.indexOfEnumerator("GroupSorting");
338  return QLatin1String(staticMetaObject.enumerator(index).valueToKey(groupSorting));
339 }
340 
341 SortOrder::SortDirection SortOrder::sortDirectionForName(const QString &name)
342 {
343  int index = staticMetaObject.indexOfEnumerator("SortDirection");
344  return static_cast<SortDirection>(staticMetaObject.enumerator(index).keyToValue(
345  name.toLatin1().constData()));
346 }
347 
348 SortOrder::MessageSorting SortOrder::messageSortingForName(const QString &name)
349 {
350  int index = staticMetaObject.indexOfEnumerator("MessageSorting");
351  return static_cast<MessageSorting>(staticMetaObject.enumerator(index).keyToValue(
352  name.toLatin1().constData()));
353 }
354 
355 SortOrder::GroupSorting SortOrder::groupSortingForName(const QString &name)
356 {
357  int index = staticMetaObject.indexOfEnumerator("GroupSorting");
358  return static_cast<GroupSorting>(staticMetaObject.enumerator(index).keyToValue(
359  name.toLatin1().constData()));
360 }
361 
362 #include "moc_sortorder.cpp"
A class which holds information about sorting, e.g.
Definition: sortorder.h:21
A set of aggregation options that can be applied to the MessageList::Model in a single shot...
Definition: aggregation.h:27
SortDirection messageSortDirection() const
Returns the current message SortDirection.
Definition: sortorder.cpp:57
void append(const T &value)
MessageSorting messageSorting() const
Returns the current message sorting option.
Definition: sortorder.cpp:47
Threading
The available threading methods.
Definition: aggregation.h:65
Threading threading() const
Returns the current threading method.
Definition: aggregation.h:177
void writeEntry(const QString &key, const QVariant &value, WriteConfigFlags pFlags=Normal)
Grouping grouping() const
Returns the currently set Grouping option.
Definition: aggregation.cpp:31
The implementation independent part of the MessageList library.
Definition: aggregation.h:21
SortDirection
The "generic" sort direction: used for groups and for messages If you add values here please look at ...
Definition: sortorder.h:50
void deleteEntry(const QString &pKey, WriteConfigFlags pFlags=Normal)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
void setGroupSorting(GroupSorting gs)
Sets the GroupSorting option.
Definition: sortorder.cpp:32
MessageSorting
The available message sorting options.
Definition: sortorder.h:60
void setMessageSortDirection(SortDirection messageSortDirection)
Sets the SortDirection for the message.
Definition: sortorder.cpp:62
const char * constData() const const
void setMessageSorting(MessageSorting ms)
Sets the current message sorting option.
Definition: sortorder.cpp:52
bool hasKey(const QString &key) const
QString i18n(const char *text, const TYPE &arg...)
Grouping
Message grouping.
Definition: aggregation.h:36
GroupSorting
How to sort the groups If you add values here please look at the implementations of the enumerate* fu...
Definition: sortorder.h:35
QByteArray toLatin1() const const
void setGroupSortDirection(SortDirection groupSortDirection)
Sets the SortDirection for the groups.
Definition: sortorder.cpp:42
T readEntry(const QString &key, const T &aDefault) const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Jul 2 2020 23:11:14 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.