Messagelib

manager.cpp
1/******************************************************************************
2 *
3 * SPDX-FileCopyrightText: 2008 Szymon Tomasz Stefanek <pragma@kvirc.net>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 *
7 *******************************************************************************/
8
9#include "core/manager.h"
10
11#include "core/aggregation.h"
12#include "core/storagemodelbase.h"
13#include "core/theme.h"
14#include "core/view.h"
15#include "core/widgetbase.h"
16#include "messagelistsettings.h"
17
18#include <MessageCore/DateFormatter>
19#include <MessageCore/MessageCoreSettings>
20
21#include "messagelistutil_p.h"
22
23#include "messagelist_debug.h"
24#include <KConfig>
25#include <KLocalizedString>
26
27using namespace MessageList::Core;
28
29Manager *Manager::mInstance = nullptr;
30
31Manager::Manager()
32 : QObject()
33 , mDateFormatter(new MessageCore::DateFormatter())
34 , mCachedLocalizedUnknownText(i18nc("Unknown date", "Unknown"))
35{
36 mInstance = this;
37
38 loadConfiguration();
39 connect(MessageListSettings::self(), &MessageListSettings::configChanged, this, &Manager::reloadGlobalConfiguration);
40 connect(MessageCore::MessageCoreSettings::self(), &MessageCore::MessageCoreSettings::configChanged, this, &Manager::reloadGlobalConfiguration);
41}
42
43Manager::~Manager()
44{
45 disconnect(MessageListSettings::self(), &MessageListSettings::configChanged, this, &Manager::reloadGlobalConfiguration);
46 disconnect(MessageCore::MessageCoreSettings::self(), &MessageCore::MessageCoreSettings::configChanged, this, &Manager::reloadGlobalConfiguration);
47
48 saveConfiguration();
49 removeAllAggregations();
50 removeAllThemes();
51
52 delete mDateFormatter;
53
54 mInstance = nullptr;
55}
56
57void Manager::registerWidget(Widget *pWidget)
58{
59 if (!mInstance) {
60 mInstance = new Manager();
61 }
62
63 mInstance->mWidgetList.append(pWidget);
64}
65
66void Manager::unregisterWidget(Widget *pWidget)
67{
68 if (!mInstance) {
69 qCWarning(MESSAGELIST_LOG) << ("ERROR: MessageList::Manager::unregisterWidget() called when Manager::mInstance is null");
70 return;
71 }
72
73 mInstance->mWidgetList.removeAll(pWidget);
74
75 if (mInstance->mWidgetList.isEmpty()) {
76 delete mInstance;
77 mInstance = nullptr;
78 }
79}
80
81const Aggregation *Manager::aggregation(const QString &id)
82{
83 Aggregation *opt = mAggregations.value(id);
84 if (opt) {
85 return opt;
86 }
87
88 return defaultAggregation();
89}
90
91const Aggregation *Manager::defaultAggregation()
92{
93 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelAggregationsGroup());
94
95 const QString aggregationId = conf.readEntry(QStringLiteral("DefaultSet"), "");
96
97 Aggregation *opt = nullptr;
98
99 if (!aggregationId.isEmpty()) {
100 opt = mAggregations.value(aggregationId);
101 }
102
103 if (opt) {
104 return opt;
105 }
106
107 // try just the first one
109 if (it != mAggregations.constEnd()) {
110 return *it;
111 }
112
113 // aargh
114 createDefaultAggregations();
115
116 return *(mAggregations.constBegin());
117}
118
119void Manager::saveAggregationForStorageModel(const Akonadi::Collection &col, const QString &id, bool storageUsesPrivateAggregation)
120{
121 if (!col.isValid()) {
122 return;
123 }
124 saveAggregationForStorageModel(QString::number(col.id()), id, storageUsesPrivateAggregation);
125}
126
127void Manager::saveAggregationForStorageModel(const StorageModel *storageModel, const QString &id, bool storageUsesPrivateAggregation)
128{
129 saveAggregationForStorageModel(storageModel->id(), id, storageUsesPrivateAggregation);
130}
131
132void Manager::saveAggregationForStorageModel(const QString &modelId, const QString &id, bool storageUsesPrivateAggregation)
133{
134 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelAggregationsGroup());
135
136 if (storageUsesPrivateAggregation) {
137 conf.writeEntry(MessageList::Util::setForStorageModelConfigName().arg(modelId), id);
138 } else {
139 conf.deleteEntry(MessageList::Util::setForStorageModelConfigName().arg(modelId));
140 }
141
142 if (!storageUsesPrivateAggregation) {
143 conf.writeEntry(QStringLiteral("DefaultSet"), id);
144 }
145 conf.sync();
146}
147
148const Aggregation *Manager::aggregationForStorageModel(const Akonadi::Collection &col, bool *storageUsesPrivateAggregation)
149{
150 Q_ASSERT(storageUsesPrivateAggregation);
151
152 *storageUsesPrivateAggregation = false; // this is by default
153
154 if (!col.isValid()) {
155 return defaultAggregation();
156 }
157 return Manager::aggregationForStorageModel(QString::number(col.id()), storageUsesPrivateAggregation);
158}
159
160const Aggregation *Manager::aggregationForStorageModel(const StorageModel *storageModel, bool *storageUsesPrivateAggregation)
161{
162 Q_ASSERT(storageUsesPrivateAggregation);
163
164 *storageUsesPrivateAggregation = false; // this is by default
165
166 if (!storageModel) {
167 return defaultAggregation();
168 }
169 return Manager::aggregationForStorageModel(storageModel->id(), storageUsesPrivateAggregation);
170}
171
172const Aggregation *Manager::aggregationForStorageModel(const QString &storageId, bool *storageUsesPrivateAggregation)
173{
174 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelAggregationsGroup());
175
176 const QString aggregationId = conf.readEntry(MessageList::Util::setForStorageModelConfigName().arg(storageId), "");
177
178 Aggregation *opt = nullptr;
179
180 if (!aggregationId.isEmpty()) {
181 // a private aggregation was stored
182 opt = mAggregations.value(aggregationId);
183 *storageUsesPrivateAggregation = (opt != nullptr);
184 }
185
186 if (opt) {
187 return opt;
188 }
189
190 // FIXME: If the storageModel is a mailing list, maybe suggest a mailing-list like preset...
191 // We could even try to guess if the storageModel is a mailing list
192
193 return defaultAggregation();
194}
195
196void Manager::addAggregation(Aggregation *set)
197{
198 Aggregation *old = mAggregations.value(set->id());
199 delete old;
200 mAggregations.insert(set->id(), set);
201}
202
203void Manager::createDefaultAggregations()
204{
205 addAggregation(new Aggregation(i18n("Current Activity, Threaded"),
206 i18n("This view uses smart date range groups. "
207 "Messages are threaded. "
208 "So for example, in \"Today\" you will find all the messages arrived today "
209 "and all the threads that have been active today."),
216 true));
217
218 addAggregation(new Aggregation(i18n("Current Activity, Flat"),
219 i18n("This view uses smart date range groups. "
220 "Messages are not threaded. "
221 "So for example, in \"Today\" you will simply find all the messages arrived today."),
228 true));
229
230 addAggregation(new Aggregation(i18n("Activity by Date, Threaded"),
231 i18n("This view uses day-by-day groups. "
232 "Messages are threaded. "
233 "So for example, in \"Today\" you will find all the messages arrived today "
234 "and all the threads that have been active today."),
241 true));
242
243 addAggregation(new Aggregation(i18n("Activity by Date, Flat"),
244 i18n("This view uses day-by-day groups. "
245 "Messages are not threaded. "
246 "So for example, in \"Today\" you will simply find all the messages arrived today."),
253 true));
254
255 addAggregation(new Aggregation(i18n("Standard Mailing List"),
256 i18n("This is a plain and old mailing list view: no groups and heavy threading."),
263 true));
264
265 addAggregation(new Aggregation(i18n("Flat Date View"),
266 i18n("This is a plain and old list of messages sorted by date: no groups and no threading."),
273 true
274
275 ));
276
277 addAggregation(new Aggregation(i18n("Senders/Receivers, Flat"),
278 i18n("This view groups the messages by senders or receivers (depending on the folder "
279 "type). "
280 "Messages are not threaded."),
287 true));
288
289 addAggregation(new Aggregation(i18n("Thread Starters"),
290 i18n("This view groups the messages in threads and then groups the threads by the starting user."),
297 true));
298
299 /*
300 FIX THIS
301 addAggregation(
302 new Aggregation(
303 i18n( "Recent Thread Starters" ),
304 i18n( "This view groups the messages in threads and then groups the threads by the starting user. " \
305 "Groups are sorted by the date of the first thread start. "
306 ),
307 Aggregation::GroupBySenderOrReceiver,
308 Aggregation::SortGroupsByDateTimeOfMostRecent,
309 Aggregation::Descending,
310 Aggregation::PerfectReferencesAndSubject,
311 Aggregation::TopmostMessage,
312 Aggregation::SortMessagesByDateTime,
313 Aggregation::Descending
314 )
315 );
316 */
317}
318
319void Manager::removeAllAggregations()
320{
321 QMap<QString, Aggregation *>::ConstIterator end(mAggregations.constEnd());
322 for (QMap<QString, Aggregation *>::ConstIterator it = mAggregations.constBegin(); it != end; ++it) {
323 delete (*it);
324 }
325
326 mAggregations.clear();
327}
328
329void Manager::aggregationsConfigurationCompleted()
330{
331 if (mAggregations.isEmpty()) {
332 createDefaultAggregations(); // panic
333 }
334
335 saveConfiguration(); // just to be sure :)
336
337 // notify all the widgets that they should reload the option set combos
338 Q_EMIT aggregationsChanged();
339}
340
341const SortOrder Manager::sortOrderForStorageModel(const StorageModel *storageModel, bool *storageUsesPrivateSortOrder)
342{
343 Q_ASSERT(storageUsesPrivateSortOrder);
344
345 *storageUsesPrivateSortOrder = false; // this is by default
346
347 if (!storageModel) {
348 return SortOrder();
349 }
350
351 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelSortOrderGroup());
352 SortOrder ret;
353 ret.readConfig(conf, storageModel->id(), storageUsesPrivateSortOrder);
354 return ret;
355}
356
357void Manager::saveSortOrderForStorageModel(const StorageModel *storageModel, SortOrder order, bool storageUsesPrivateSortOrder)
358{
359 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelSortOrderGroup());
360 order.writeConfig(conf, storageModel->id(), storageUsesPrivateSortOrder);
361}
362
363const Theme *Manager::theme(const QString &id)
364{
365 Theme *opt = mThemes.value(id);
366 if (opt) {
367 return opt;
368 }
369
370 return defaultTheme();
371}
372
373const Theme *Manager::defaultTheme()
374{
375 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelThemesGroup());
376
377 const QString themeId = conf.readEntry(QStringLiteral("DefaultSet"), "");
378
379 Theme *opt = nullptr;
380
381 if (!themeId.isEmpty()) {
382 opt = mThemes.value(themeId);
383 }
384
385 if (opt) {
386 return opt;
387 }
388
389 // try just the first one
391 if (it != mThemes.constEnd()) {
392 return *it;
393 }
394
395 // aargh
396 createDefaultThemes();
397
398 it = mThemes.constBegin();
399
400 Q_ASSERT(it != mThemes.constEnd());
401
402 return *it;
403}
404
405void Manager::saveThemeForStorageModel(int index, const QString &id, bool storageUsesPrivateTheme)
406{
407 saveThemeForStorageModel(QString::number(index), id, storageUsesPrivateTheme);
408}
409
410void Manager::saveThemeForStorageModel(const StorageModel *storageModel, const QString &id, bool storageUsesPrivateTheme)
411{
412 saveThemeForStorageModel(storageModel->id(), id, storageUsesPrivateTheme);
413}
414
415void Manager::saveThemeForStorageModel(const QString &storageModelIndex, const QString &id, bool storageUsesPrivateTheme)
416{
417 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelThemesGroup());
418
419 if (storageUsesPrivateTheme) {
420 conf.writeEntry(MessageList::Util::setForStorageModelConfigName().arg(storageModelIndex), id);
421 } else {
422 conf.deleteEntry(MessageList::Util::setForStorageModelConfigName().arg(storageModelIndex));
423 }
424
425 if (!storageUsesPrivateTheme) {
426 conf.writeEntry(QStringLiteral("DefaultSet"), id);
427 }
428 conf.sync();
429}
430
431const Theme *Manager::themeForStorageModel(const Akonadi::Collection &col, bool *storageUsesPrivateTheme)
432{
433 Q_ASSERT(storageUsesPrivateTheme);
434
435 *storageUsesPrivateTheme = false; // this is by default
436
437 if (!col.isValid()) {
438 return defaultTheme();
439 }
440 return Manager::themeForStorageModel(QString::number(col.id()), storageUsesPrivateTheme);
441}
442
443const Theme *Manager::themeForStorageModel(const StorageModel *storageModel, bool *storageUsesPrivateTheme)
444{
445 Q_ASSERT(storageUsesPrivateTheme);
446
447 *storageUsesPrivateTheme = false; // this is by default
448
449 if (!storageModel) {
450 return defaultTheme();
451 }
452 return Manager::themeForStorageModel(storageModel->id(), storageUsesPrivateTheme);
453}
454
455const Theme *Manager::themeForStorageModel(const QString &id, bool *storageUsesPrivateTheme)
456{
457 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelThemesGroup());
458 const QString themeId = conf.readEntry(MessageList::Util::setForStorageModelConfigName().arg(id), "");
459
460 Theme *opt = nullptr;
461
462 if (!themeId.isEmpty()) {
463 // a private theme was stored
464 opt = mThemes.value(themeId);
465 *storageUsesPrivateTheme = (opt != nullptr);
466 }
467
468 if (opt) {
469 return opt;
470 }
471
472 // FIXME: If the storageModel is a mailing list, maybe suggest a mailing-list like preset...
473 // We could even try to guess if the storageModel is a mailing list
474
475 // FIXME: Prefer right-to-left themes when application layout is RTL.
476
477 return defaultTheme();
478}
479
480void Manager::addTheme(Theme *set)
481{
482 Theme *old = mThemes.value(set->id());
483 delete old;
484 mThemes.insert(set->id(), set);
485}
486
487static Theme::Column *add_theme_simple_text_column(Theme *s,
488 const QString &name,
490 bool visibleByDefault,
491 SortOrder::MessageSorting messageSorting,
492 bool alignRight,
493 bool addGroupHeaderItem)
494{
495 auto c = new Theme::Column();
496 c->setLabel(name);
497 c->setVisibleByDefault(visibleByDefault);
498 c->setMessageSorting(messageSorting);
499
500 auto r = new Theme::Row();
501
502 auto i = new Theme::ContentItem(type);
503
504 if (alignRight) {
505 r->addRightItem(i);
506 } else {
507 r->addLeftItem(i);
508 }
509
510 c->addMessageRow(r);
511
512 if (addGroupHeaderItem) {
513 auto row = new Theme::Row();
514
515 auto iRow = new Theme::ContentItem(type);
516
517 if (alignRight) {
518 row->addRightItem(iRow);
519 } else {
520 row->addLeftItem(iRow);
521 }
522
523 c->addGroupHeaderRow(row);
524 }
525
526 s->addColumn(c);
527
528 return c;
529}
530
531static Theme::Column *add_theme_simple_icon_column(Theme *s,
532 const QString &name,
533 const QString &pixmapName,
535 bool visibleByDefault,
536 SortOrder::MessageSorting messageSorting)
537{
538 auto c = new Theme::Column();
539 c->setLabel(name);
540 c->setPixmapName(pixmapName);
541 c->setVisibleByDefault(visibleByDefault);
542 c->setMessageSorting(messageSorting);
543
544 auto r = new Theme::Row();
545
546 auto i = new Theme::ContentItem(type);
547 i->setSoftenByBlendingWhenDisabled(true);
548
549 r->addLeftItem(i);
550
551 c->addMessageRow(r);
552
553 s->addColumn(c);
554
555 return c;
556}
557
558void Manager::createDefaultThemes()
559{
560 Theme *s;
561 Theme::Column *c;
562 Theme::Row *r;
564
565 // The "Classic" backward compatible theme
566
567 s = new Theme(i18nc("Default theme name", "Classic"), i18n("A simple, backward compatible, single row theme"), true /*readOnly*/
568 );
569
570 c = new Theme::Column();
571 c->setLabel(i18nc("@title:column Subject of messages", "Subject"));
573
574 r = new Theme::Row();
576 r->addLeftItem(i);
578 i->setBold(true);
579 r->addLeftItem(i);
580 c->addGroupHeaderRow(r);
581
582 r = new Theme::Row();
584 r->addLeftItem(i);
586 i->setHideWhenDisabled(true);
587 r->addLeftItem(i);
589 i->setHideWhenDisabled(true);
590 r->addLeftItem(i);
592 i->setHideWhenDisabled(true);
593 r->addLeftItem(i);
595 i->setHideWhenDisabled(true);
596 r->addLeftItem(i);
598 r->addLeftItem(i);
599 c->addMessageRow(r);
600
601 s->addColumn(c);
602
603 c = add_theme_simple_text_column(s,
604 i18n("Sender/Receiver"),
606 true,
608 false,
609 false);
610 c->setIsSenderOrReceiver(true);
611 add_theme_simple_text_column(s, i18nc("Sender of a message", "Sender"), Theme::ContentItem::Sender, false, SortOrder::SortMessagesBySender, false, false);
612 add_theme_simple_text_column(s,
613 i18nc("Receiver of a message", "Receiver"),
615 false,
617 false,
618 false);
619 add_theme_simple_text_column(s, i18nc("Date of a message", "Date"), Theme::ContentItem::Date, true, SortOrder::SortMessagesByDateTime, false, false);
620 add_theme_simple_text_column(s,
621 i18n("Most Recent Date"),
623 false,
625 false,
626 true);
627 add_theme_simple_text_column(s, i18nc("Size of a message", "Size"), Theme::ContentItem::Size, false, SortOrder::SortMessagesBySize, false, false);
628 add_theme_simple_icon_column(s,
629 i18nc("Attachment indication", "Attachment"),
630 QStringLiteral("mail-attachment"),
632 false,
634 add_theme_simple_icon_column(s,
635 i18n("Read/Unread"),
636 QStringLiteral("mail-mark-unread-new"),
638 false,
640 add_theme_simple_icon_column(s, i18n("Replied"), QStringLiteral("mail-replied"), Theme::ContentItem::RepliedStateIcon, false, SortOrder::NoMessageSorting);
641 add_theme_simple_icon_column(s,
642 i18nc("Message importance indication", "Important"),
643 QStringLiteral("mail-mark-important"),
645 false,
646 SortOrder::SortMessagesByImportantStatus);
647 add_theme_simple_icon_column(s,
648 i18n("Action Item"),
649 QStringLiteral("mail-task"),
651 false,
653 add_theme_simple_icon_column(s,
654 i18n("Spam/Ham"),
655 QStringLiteral("mail-mark-junk"),
657 false,
659 add_theme_simple_icon_column(s,
660 i18n("Watched/Ignored"),
661 QStringLiteral("mail-thread-watch"),
663 false,
665 add_theme_simple_icon_column(s,
666 i18n("Encryption"),
667 QStringLiteral("mail-encrypted-full"),
669 false,
671 add_theme_simple_icon_column(s,
672 i18n("Signature"),
673 QStringLiteral("mail-signed-verified"),
675 false,
677 add_theme_simple_icon_column(s, i18n("Tag List"), QStringLiteral("feed-subscribe"), Theme::ContentItem::TagList, false, SortOrder::NoMessageSorting);
678
679 s->resetColumnState(); // so it's initially set from defaults
680
681 addTheme(s);
682
683 // The Fancy theme
684
685 s = new Theme(i18n("Smart"), i18n("A smart multiline and multi item theme"), true /*readOnly*/
686 );
687
688 c = new Theme::Column();
689 c->setLabel(i18n("Message"));
690
691 r = new Theme::Row();
693 r->addLeftItem(i);
695 i->setBold(true);
696 r->addLeftItem(i);
697 c->addGroupHeaderRow(r);
698
699 r = new Theme::Row();
701 r->addLeftItem(i);
703 r->addRightItem(i);
705 i->setHideWhenDisabled(true);
706 r->addRightItem(i);
708 i->setHideWhenDisabled(true);
709 r->addRightItem(i);
711 i->setHideWhenDisabled(true);
712 r->addRightItem(i);
714 i->setHideWhenDisabled(true);
715 r->addRightItem(i);
717 i->setHideWhenDisabled(true);
718 r->addRightItem(i);
720 i->setHideWhenDisabled(true);
721 r->addRightItem(i);
722 c->addMessageRow(r);
723
724 Theme::Row *firstFancyRow = r; // save it so we can continue adding stuff below (after cloning the theme)
725
726 r = new Theme::Row();
728 i->setSoftenByBlending(true);
729 i->setItalic(true);
730 r->addLeftItem(i);
732 i->setSoftenByBlending(true);
733 i->setItalic(true);
734 r->addRightItem(i);
735 c->addMessageRow(r);
736
737 s->addColumn(c);
738
739 // clone the "Fancy theme" here so we'll use it as starting point for the "Fancy with clickable status"
740 auto fancyWithClickableStatus = new Theme(*s);
741 fancyWithClickableStatus->detach();
742 fancyWithClickableStatus->generateUniqueId();
743
744 // and continue the "Fancy" specific settings
745 r = firstFancyRow;
746
748 i->setHideWhenDisabled(true);
749 r->addRightItem(i);
751 i->setHideWhenDisabled(true);
752 r->addRightItem(i);
754 i->setHideWhenDisabled(true);
755 r->addRightItem(i);
757 i->setHideWhenDisabled(true);
758 r->addRightItem(i);
759
760 s->setViewHeaderPolicy(Theme::NeverShowHeader);
761
762 s->resetColumnState(); // so it's initially set from defaults
763
764 addTheme(s);
765
766 // The "Fancy with Clickable Status" theme
767
768 s = fancyWithClickableStatus;
769
770 s->setName(i18n("Smart with Clickable Status"));
771 s->setDescription(i18n("A smart multiline and multi item theme with a clickable status column"));
772 s->setReadOnly(true);
773
774 c = new Theme::Column();
775 c->setLabel(i18n("Status"));
776 c->setVisibleByDefault(true);
777
778 r = new Theme::Row();
781 r->addLeftItem(i);
784 r->addLeftItem(i);
785 c->addMessageRow(r);
786
787 r = new Theme::Row();
790 r->addLeftItem(i);
793 r->addLeftItem(i);
794 c->addMessageRow(r);
795
796 s->addColumn(c);
797
798 s->resetColumnState(); // so it's initially set from defaults
799
800 addTheme(s);
801}
802
803void Manager::removeAllThemes()
804{
805 QMap<QString, Theme *>::ConstIterator end(mThemes.constEnd());
806 for (QMap<QString, Theme *>::ConstIterator it = mThemes.constBegin(); it != end; ++it) {
807 delete (*it);
808 }
809
810 mThemes.clear();
811}
812
813void Manager::themesConfigurationCompleted()
814{
815 if (mThemes.isEmpty()) {
816 createDefaultThemes(); // panic
817 }
818
819 saveConfiguration(); // just to be sure :)
820
821 // notify all the widgets that they should reload the option set combos
822 Q_EMIT themesChanged();
823}
824
825void Manager::reloadAllWidgets()
826{
827 QList<Widget *>::ConstIterator end(mWidgetList.constEnd());
828 for (QList<Widget *>::ConstIterator it = mWidgetList.constBegin(); it != end; ++it) {
829 if ((*it)->view()) {
830 (*it)->view()->reload();
831 }
832 }
833}
834
835void Manager::reloadGlobalConfiguration()
836{
837 // This is called when configuration changes (probably edited by the options dialog)
838 const int oldDateFormat = (int)mDateFormatter->format();
839 const QString oldDateCustomFormat = mDateFormatter->customFormat();
840
841 loadGlobalConfiguration();
842
843 if ((oldDateFormat != (int)mDateFormatter->format()) || (oldDateCustomFormat != mDateFormatter->customFormat())) {
844 reloadAllWidgets();
845 }
846}
847
848void Manager::loadGlobalConfiguration()
849{
850 // Load the date format
851 const auto type = static_cast<MessageCore::DateFormatter::FormatType>(MessageCore::MessageCoreSettings::self()->dateFormat());
852 mDateFormatter->setCustomFormat(MessageCore::MessageCoreSettings::self()->customDateFormat());
853 mDateFormatter->setFormat(type);
854}
855
856void Manager::loadConfiguration()
857{
858 loadGlobalConfiguration();
859
860 {
861 // load Aggregations
862
863 KConfigGroup conf(MessageListSettings::self()->config(), QStringLiteral("MessageListView::Aggregations"));
864
865 mAggregations.clear();
866
867 const int cnt = conf.readEntry("Count", 0);
868
869 int idx = 0;
870 while (idx < cnt) {
871 const QString data = conf.readEntry(QStringLiteral("Set%1").arg(idx), QString());
872 if (!data.isEmpty()) {
873 auto set = new Aggregation();
874 if (set->loadFromString(data)) {
875 if (Aggregation *old = mAggregations.value(set->id())) {
876 delete old;
877 }
878 mAggregations.insert(set->id(), set);
879 } else {
880 delete set; // b0rken
881 }
882 }
883 idx++;
884 }
885
886 if (mAggregations.isEmpty()) {
887 // don't allow zero configuration, create some presets
888 createDefaultAggregations();
889 }
890 }
891
892 {
893 // load Themes
894
895 KConfigGroup conf(MessageListSettings::self()->config(), QStringLiteral("MessageListView::Themes"));
896
897 mThemes.clear();
898
899 const int cnt = conf.readEntry("Count", 0);
900
901 int idx = 0;
902 while (idx < cnt) {
903 const QString data = conf.readEntry(QStringLiteral("Set%1").arg(idx), QString());
904 if (!data.isEmpty()) {
905 auto set = new Theme();
906 if (set->loadFromString(data)) {
907 if (Theme *old = mThemes.value(set->id())) {
908 delete old;
909 }
910 mThemes.insert(set->id(), set);
911 } else {
912 qCWarning(MESSAGELIST_LOG) << "Saved theme loading failed";
913 delete set; // b0rken
914 }
915 }
916 ++idx;
917 }
918
919 if (mThemes.isEmpty()) {
920 // don't allow zero configuration, create some presets
921 createDefaultThemes();
922 }
923 }
924}
925
926void Manager::saveGlobalConfiguration()
927{
928 MessageListSettings::self()->save();
929}
930
931void Manager::saveConfiguration()
932{
933 saveGlobalConfiguration();
934
935 {
936 // store aggregations
937
938 KConfigGroup conf(MessageListSettings::self()->config(), QStringLiteral("MessageListView::Aggregations"));
939 // conf.clear();
940
941 conf.writeEntry("Count", mAggregations.count());
942
943 int idx = 0;
945 for (QMap<QString, Aggregation *>::ConstIterator it = mAggregations.constBegin(); it != end; ++it) {
946 conf.writeEntry(QStringLiteral("Set%1").arg(idx), (*it)->saveToString());
947 ++idx;
948 }
949 }
950
951 {
952 // store themes
953
954 KConfigGroup conf(MessageListSettings::self()->config(), QStringLiteral("MessageListView::Themes"));
955 // conf.clear();
956
957 conf.writeEntry("Count", mThemes.count());
958
959 int idx = 0;
960 QMap<QString, Theme *>::ConstIterator end(mThemes.constEnd());
961 for (QMap<QString, Theme *>::ConstIterator it = mThemes.constBegin(); it != end; ++it) {
962 conf.writeEntry(QStringLiteral("Set%1").arg(idx), (*it)->saveToString());
963 ++idx;
964 }
965 }
966
967 MessageListSettings::self()->config()->sync();
968}
969
970#include "moc_manager.cpp"
bool isValid() const
FormatType
The different types of date formats.
A set of aggregation options that can be applied to the MessageList::Model in a single shot.
Definition aggregation.h:29
@ NoGrouping
Don't group messages at all.
Definition aggregation.h:37
@ GroupByDateRange
Use smart (thread leader) date ranges ("Today","Yesterday","Last Week"...)
Definition aggregation.h:39
@ GroupBySenderOrReceiver
Group by sender (incoming) or receiver (outgoing) field.
Definition aggregation.h:40
@ GroupByDate
Group the messages by the date of the thread leader.
Definition aggregation.h:38
@ NeverExpandGroups
Never expand groups during a view fill algorithm.
Definition aggregation.h:54
@ ExpandRecentGroups
Makes sense only with GroupByDate or GroupByDateRange.
Definition aggregation.h:55
@ NoThreading
Perform no threading at all.
Definition aggregation.h:66
@ PerfectReferencesAndSubject
Thread by all of the above and try to match subjects too.
Definition aggregation.h:69
@ ExpandThreadsWithUnreadOrImportantMessages
Expand threads with "hot" messages (this includes new, unread, important, todo)
Definition aggregation.h:95
@ NeverExpandThreads
Never expand any thread, this is fast.
Definition aggregation.h:91
@ TopmostMessage
The thread grouping is computed from the topmost message (very similar to least recent,...
Definition aggregation.h:79
@ MostRecentMessage
The thread grouping is computed from the most recent message.
Definition aggregation.h:81
@ FavorSpeed
Do larger chunks of work, zero intervals between chunks.
@ FavorInteractivity
Do small chunks of work, small intervals between chunks to allow for UI event processing.
const QString & id() const
Returns the unique id of this OptionSet.
Definition optionset.h:51
void setName(const QString &name)
Sets the name of this OptionSet.
Definition optionset.h:69
void setDescription(const QString &description)
Sets the description for this option set.
Definition optionset.h:87
bool loadFromString(const QString &data)
Attempts to unpack this configuration object from a string (that is likely to come out from a config ...
Definition optionset.cpp:69
A class which holds information about sorting, e.g.
Definition sortorder.h:23
void readConfig(KConfigGroup &conf, const QString &storageId, bool *storageUsesPrivateSortOrder)
Reads the sort order from a config group.
void writeConfig(KConfigGroup &conf, const QString &storageId, bool storageUsesPrivateSortOrder) const
Writes the sort order to a config group.
MessageSorting
The available message sorting options.
Definition sortorder.h:60
@ SortMessagesBySize
Sort the messages by size.
Definition sortorder.h:68
@ SortMessagesByAttachmentStatus
Sort the messages By "Important" flags of status.
Definition sortorder.h:72
@ SortMessagesByDateTime
Sort the messages by date and time.
Definition sortorder.h:62
@ SortMessagesByActionItemStatus
Sort the messages by the "Action Item" flag of status.
Definition sortorder.h:69
@ NoMessageSorting
Don't sort the messages at all.
Definition sortorder.h:61
@ SortMessagesBySenderOrReceiver
Sort the messages by sender or receiver.
Definition sortorder.h:64
@ SortMessagesBySender
Sort the messages by sender.
Definition sortorder.h:65
@ SortMessagesByReceiver
Sort the messages by receiver.
Definition sortorder.h:66
@ SortMessagesByDateTimeOfMostRecent
Sort the messages by date and time of the most recent message in subtree.
Definition sortorder.h:63
@ SortMessagesByUnreadStatus
Sort the messages by the "Unread" flags of status.
Definition sortorder.h:70
@ SortMessagesBySubject
Sort the messages by subject.
Definition sortorder.h:67
The QAbstractItemModel based interface that you need to provide for your storage to work with Message...
virtual QString id() const =0
Returns an unique id for this Storage collection.
The Column class defines a view column available inside this theme.
Definition theme.h:501
void setMessageSorting(SortOrder::MessageSorting ms)
Sets the sort order for messages that we should switch to when clicking on this column's header (if v...
Definition theme.cpp:675
void setVisibleByDefault(bool vbd)
Sets the "visible by default" tag for this column.
Definition theme.cpp:654
void setIsSenderOrReceiver(bool sor)
Marks this column as containing the "sender/receiver" field.
Definition theme.cpp:644
void addGroupHeaderRow(Row *row)
Appends a group header row to this theme.
Definition theme.cpp:724
void setLabel(const QString &label)
Sets the label for this column.
Definition theme.cpp:624
void addMessageRow(Row *row)
Appends a message row to this theme column.
Definition theme.cpp:712
The ContentItem class defines a content item inside a Row.
Definition theme.h:56
void setSoftenByBlending(bool softenByBlending)
Sets the flag that causes this item to be painted "softly".
Definition theme.cpp:256
void setBold(bool isBold)
Makes this item use a bold font.
Definition theme.cpp:200
void setSoftenByBlendingWhenDisabled(bool softenByBlendingWhenDisabled)
Sets the flag that causes this item to be painted "softly" when disabled.
Definition theme.cpp:242
void setItalic(bool isItalic)
Makes this item use italic font.
Definition theme.cpp:214
Type
The available ContentItem types.
Definition theme.h:106
@ InvitationIcon
Whether the message is an invitation.
Definition theme.h:198
@ CombinedReadRepliedStateIcon
The combined icon that displays the unread/read/replied/forwarded state (never disabled)
Definition theme.h:190
@ SignatureStateIcon
The Signature state icon for messages.
Definition theme.h:174
@ Date
Formatted date time of the message/group.
Definition theme.h:114
@ MostRecentDate
The date of the most recent message in subtree.
Definition theme.h:186
@ ReadStateIcon
The icon that displays the unread/read state (never disabled)
Definition theme.h:134
@ RepliedStateIcon
The icon that displays the replied/forwarded state (may be disabled)
Definition theme.h:142
@ WatchedIgnoredStateIcon
The Watched/Ignored state icon.
Definition theme.h:162
@ ImportantStateIcon
The Important tag icon.
Definition theme.h:154
@ AttachmentStateIcon
The icon that displays the attachment state (may be disabled)
Definition theme.h:138
@ ExpandedStateIcon
The Expanded state icon for group headers.
Definition theme.h:166
@ SenderOrReceiver
From: or To: strip, depending on the folder settings.
Definition theme.h:118
@ GroupHeaderLabel
The group header label.
Definition theme.h:146
@ Subject
Display the subject of the message item.
Definition theme.h:110
@ EncryptionStateIcon
The Encryption state icon for messages.
Definition theme.h:170
@ TagList
The list of MessageItem::Tag entries.
Definition theme.h:194
@ Size
Formatted size of the message.
Definition theme.h:130
@ Receiver
To: strip, always.
Definition theme.h:126
@ ActionItemStateIcon
The ActionItem state icon.
Definition theme.h:150
@ Sender
From: strip, always.
Definition theme.h:122
@ SpamHamStateIcon
The Spam/Ham state icon.
Definition theme.h:158
void setHideWhenDisabled(bool hideWhenDisabled)
Sets the flag that causes this item to be hidden when disabled.
Definition theme.cpp:228
The Row class defines a row of items inside a Column.
Definition theme.h:408
void addRightItem(ContentItem *item)
Adds a right aligned item to this row.
Definition theme.cpp:379
void addLeftItem(ContentItem *item)
Adds a left aligned item to this row.
Definition theme.cpp:367
The Theme class defines the visual appearance of the MessageList.
Definition theme.h:48
void setViewHeaderPolicy(ViewHeaderPolicy vhp)
Sets the ViewHeaderPolicy for this theme.
Definition theme.cpp:1049
void addColumn(Column *column)
Appends a column to this theme.
Definition theme.cpp:967
void resetColumnState()
Resets the column state (visibility and width) to their default values (the "visible by default" ones...
Definition theme.cpp:935
Provides a widget which has the messagelist and the most important helper widgets,...
Definition widgetbase.h:41
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QAction * end(const QObject *recvr, const char *slot, QObject *parent)
The implementation independent part of the MessageList library.
Definition aggregation.h:22
const_iterator constBegin() const const
bool isEmpty() const const
QString number(double n, char format, int precision)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 11:54:19 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.