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 mInstance = nullptr;
53}
54
55void Manager::registerWidget(Widget *pWidget)
56{
57 if (!mInstance) {
58 mInstance = new Manager();
59 }
60
61 mInstance->mWidgetList.append(pWidget);
62}
63
64void Manager::unregisterWidget(Widget *pWidget)
65{
66 if (!mInstance) {
67 qCWarning(MESSAGELIST_LOG) << ("ERROR: MessageList::Manager::unregisterWidget() called when Manager::mInstance is null");
68 return;
69 }
70
71 mInstance->mWidgetList.removeAll(pWidget);
72
73 if (mInstance->mWidgetList.isEmpty()) {
74 delete mInstance;
75 mInstance = nullptr;
76 }
77}
78
79const Aggregation *Manager::aggregation(const QString &id)
80{
81 Aggregation *opt = mAggregations.value(id);
82 if (opt) {
83 return opt;
84 }
85
86 return defaultAggregation();
87}
88
89const Aggregation *Manager::defaultAggregation()
90{
91 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelAggregationsGroup());
92
93 const QString aggregationId = conf.readEntry(QStringLiteral("DefaultSet"), "");
94
95 Aggregation *opt = nullptr;
96
97 if (!aggregationId.isEmpty()) {
98 opt = mAggregations.value(aggregationId);
99 }
100
101 if (opt) {
102 return opt;
103 }
104
105 // try just the first one
106 QMap<QString, Aggregation *>::ConstIterator it = mAggregations.constBegin();
107 if (it != mAggregations.constEnd()) {
108 return *it;
109 }
110
111 // aargh
112 createDefaultAggregations();
113
114 return *(mAggregations.constBegin());
115}
116
117void Manager::saveAggregationForStorageModel(const Akonadi::Collection &col, const QString &id, bool storageUsesPrivateAggregation)
118{
119 if (!col.isValid()) {
120 return;
121 }
122 saveAggregationForStorageModel(QString::number(col.id()), id, storageUsesPrivateAggregation);
123}
124
125void Manager::saveAggregationForStorageModel(const StorageModel *storageModel, const QString &id, bool storageUsesPrivateAggregation)
126{
127 saveAggregationForStorageModel(storageModel->id(), id, storageUsesPrivateAggregation);
128}
129
130void Manager::saveAggregationForStorageModel(const QString &modelId, const QString &id, bool storageUsesPrivateAggregation)
131{
132 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelAggregationsGroup());
133
134 if (storageUsesPrivateAggregation) {
135 conf.writeEntry(MessageList::Util::setForStorageModelConfigName().arg(modelId), id);
136 } else {
137 conf.deleteEntry(MessageList::Util::setForStorageModelConfigName().arg(modelId));
138 }
139
140 if (!storageUsesPrivateAggregation) {
141 conf.writeEntry(QStringLiteral("DefaultSet"), id);
142 }
143 conf.sync();
144}
145
146const Aggregation *Manager::aggregationForStorageModel(const Akonadi::Collection &col, bool *storageUsesPrivateAggregation)
147{
148 Q_ASSERT(storageUsesPrivateAggregation);
149
150 *storageUsesPrivateAggregation = false; // this is by default
151
152 if (!col.isValid()) {
153 return defaultAggregation();
154 }
155 return Manager::aggregationForStorageModel(QString::number(col.id()), storageUsesPrivateAggregation);
156}
157
158const Aggregation *Manager::aggregationForStorageModel(const StorageModel *storageModel, bool *storageUsesPrivateAggregation)
159{
160 Q_ASSERT(storageUsesPrivateAggregation);
161
162 *storageUsesPrivateAggregation = false; // this is by default
163
164 if (!storageModel) {
165 return defaultAggregation();
166 }
167 return Manager::aggregationForStorageModel(storageModel->id(), storageUsesPrivateAggregation);
168}
169
170const Aggregation *Manager::aggregationForStorageModel(const QString &storageId, bool *storageUsesPrivateAggregation)
171{
172 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelAggregationsGroup());
173
174 const QString aggregationId = conf.readEntry(MessageList::Util::setForStorageModelConfigName().arg(storageId), "");
175
176 Aggregation *opt = nullptr;
177
178 if (!aggregationId.isEmpty()) {
179 // a private aggregation was stored
180 opt = mAggregations.value(aggregationId);
181 *storageUsesPrivateAggregation = (opt != nullptr);
182 }
183
184 if (opt) {
185 return opt;
186 }
187
188 // FIXME: If the storageModel is a mailing list, maybe suggest a mailing-list like preset...
189 // We could even try to guess if the storageModel is a mailing list
190
191 return defaultAggregation();
192}
193
194void Manager::addAggregation(Aggregation *set)
195{
196 Aggregation *old = mAggregations.value(set->id());
197 delete old;
198 mAggregations.insert(set->id(), set);
199}
200
201void Manager::createDefaultAggregations()
202{
203 addAggregation(new Aggregation(i18n("Current Activity, Threaded"),
204 i18n("This view uses smart date range groups. "
205 "Messages are threaded. "
206 "So for example, in \"Today\" you will find all the messages arrived today "
207 "and all the threads that have been active today."),
214 true));
215
216 addAggregation(new Aggregation(i18n("Current Activity, Flat"),
217 i18n("This view uses smart date range groups. "
218 "Messages are not threaded. "
219 "So for example, in \"Today\" you will simply find all the messages arrived today."),
226 true));
227
228 addAggregation(new Aggregation(i18n("Activity by Date, Threaded"),
229 i18n("This view uses day-by-day groups. "
230 "Messages are threaded. "
231 "So for example, in \"Today\" you will find all the messages arrived today "
232 "and all the threads that have been active today."),
239 true));
240
241 addAggregation(new Aggregation(i18n("Activity by Date, Flat"),
242 i18n("This view uses day-by-day groups. "
243 "Messages are not threaded. "
244 "So for example, in \"Today\" you will simply find all the messages arrived today."),
251 true));
252
253 addAggregation(new Aggregation(i18n("Standard Mailing List"),
254 i18n("This is a plain and old mailing list view: no groups and heavy threading."),
261 true));
262
263 addAggregation(new Aggregation(i18n("Flat Date View"),
264 i18n("This is a plain and old list of messages sorted by date: no groups and no threading."),
271 true
272
273 ));
274
275 addAggregation(new Aggregation(i18n("Senders/Receivers, Flat"),
276 i18n("This view groups the messages by senders or receivers (depending on the folder "
277 "type). "
278 "Messages are not threaded."),
285 true));
286
287 addAggregation(new Aggregation(i18n("Thread Starters"),
288 i18n("This view groups the messages in threads and then groups the threads by the starting user."),
295 true));
296
297 /*
298 FIX THIS
299 addAggregation(
300 new Aggregation(
301 i18n( "Recent Thread Starters" ),
302 i18n( "This view groups the messages in threads and then groups the threads by the starting user. " \
303 "Groups are sorted by the date of the first thread start. "
304 ),
305 Aggregation::GroupBySenderOrReceiver,
306 Aggregation::SortGroupsByDateTimeOfMostRecent,
307 Aggregation::Descending,
308 Aggregation::PerfectReferencesAndSubject,
309 Aggregation::TopmostMessage,
310 Aggregation::SortMessagesByDateTime,
311 Aggregation::Descending
312 )
313 );
314 */
315}
316
317void Manager::removeAllAggregations()
318{
319 QMap<QString, Aggregation *>::ConstIterator end(mAggregations.constEnd());
320 for (QMap<QString, Aggregation *>::ConstIterator it = mAggregations.constBegin(); it != end; ++it) {
321 delete (*it);
322 }
323
324 mAggregations.clear();
325}
326
327void Manager::aggregationsConfigurationCompleted()
328{
329 if (mAggregations.isEmpty()) {
330 createDefaultAggregations(); // panic
331 }
332
333 saveConfiguration(); // just to be sure :)
334
335 // notify all the widgets that they should reload the option set combos
336 Q_EMIT aggregationsChanged();
337}
338
339const SortOrder Manager::sortOrderForStorageModel(const StorageModel *storageModel, bool *storageUsesPrivateSortOrder)
340{
341 Q_ASSERT(storageUsesPrivateSortOrder);
342
343 *storageUsesPrivateSortOrder = false; // this is by default
344
345 if (!storageModel) {
346 return SortOrder();
347 }
348
349 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelSortOrderGroup());
350 SortOrder ret;
351 ret.readConfig(conf, storageModel->id(), storageUsesPrivateSortOrder);
352 return ret;
353}
354
355void Manager::saveSortOrderForStorageModel(const StorageModel *storageModel, SortOrder order, bool storageUsesPrivateSortOrder)
356{
357 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelSortOrderGroup());
358 order.writeConfig(conf, storageModel->id(), storageUsesPrivateSortOrder);
359}
360
361const Theme *Manager::theme(const QString &id)
362{
363 Theme *opt = mThemes.value(id);
364 if (opt) {
365 return opt;
366 }
367
368 return defaultTheme();
369}
370
371const Theme *Manager::defaultTheme()
372{
373 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelThemesGroup());
374
375 const QString themeId = conf.readEntry(QStringLiteral("DefaultSet"), "");
376
377 Theme *opt = nullptr;
378
379 if (!themeId.isEmpty()) {
380 opt = mThemes.value(themeId);
381 }
382
383 if (opt) {
384 return opt;
385 }
386
387 // try just the first one
389 if (it != mThemes.constEnd()) {
390 return *it;
391 }
392
393 // aargh
394 createDefaultThemes();
395
396 it = mThemes.constBegin();
397
398 Q_ASSERT(it != mThemes.constEnd());
399
400 return *it;
401}
402
403void Manager::saveThemeForStorageModel(int index, const QString &id, bool storageUsesPrivateTheme)
404{
405 saveThemeForStorageModel(QString::number(index), id, storageUsesPrivateTheme);
406}
407
408void Manager::saveThemeForStorageModel(const StorageModel *storageModel, const QString &id, bool storageUsesPrivateTheme)
409{
410 saveThemeForStorageModel(storageModel->id(), id, storageUsesPrivateTheme);
411}
412
413void Manager::saveThemeForStorageModel(const QString &storageModelIndex, const QString &id, bool storageUsesPrivateTheme)
414{
415 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelThemesGroup());
416
417 if (storageUsesPrivateTheme) {
418 conf.writeEntry(MessageList::Util::setForStorageModelConfigName().arg(storageModelIndex), id);
419 } else {
420 conf.deleteEntry(MessageList::Util::setForStorageModelConfigName().arg(storageModelIndex));
421 }
422
423 if (!storageUsesPrivateTheme) {
424 conf.writeEntry(QStringLiteral("DefaultSet"), id);
425 }
426 conf.sync();
427}
428
429const Theme *Manager::themeForStorageModel(const Akonadi::Collection &col, bool *storageUsesPrivateTheme)
430{
431 Q_ASSERT(storageUsesPrivateTheme);
432
433 *storageUsesPrivateTheme = false; // this is by default
434
435 if (!col.isValid()) {
436 return defaultTheme();
437 }
438 return Manager::themeForStorageModel(QString::number(col.id()), storageUsesPrivateTheme);
439}
440
441const Theme *Manager::themeForStorageModel(const StorageModel *storageModel, bool *storageUsesPrivateTheme)
442{
443 Q_ASSERT(storageUsesPrivateTheme);
444
445 *storageUsesPrivateTheme = false; // this is by default
446
447 if (!storageModel) {
448 return defaultTheme();
449 }
450 return Manager::themeForStorageModel(storageModel->id(), storageUsesPrivateTheme);
451}
452
453const Theme *Manager::themeForStorageModel(const QString &id, bool *storageUsesPrivateTheme)
454{
455 KConfigGroup conf(MessageListSettings::self()->config(), MessageList::Util::storageModelThemesGroup());
456 const QString themeId = conf.readEntry(MessageList::Util::setForStorageModelConfigName().arg(id), "");
457
458 Theme *opt = nullptr;
459
460 if (!themeId.isEmpty()) {
461 // a private theme was stored
462 opt = mThemes.value(themeId);
463 *storageUsesPrivateTheme = (opt != nullptr);
464 }
465
466 if (opt) {
467 return opt;
468 }
469
470 // FIXME: If the storageModel is a mailing list, maybe suggest a mailing-list like preset...
471 // We could even try to guess if the storageModel is a mailing list
472
473 // FIXME: Prefer right-to-left themes when application layout is RTL.
474
475 return defaultTheme();
476}
477
478void Manager::addTheme(Theme *set)
479{
480 Theme *old = mThemes.value(set->id());
481 delete old;
482 mThemes.insert(set->id(), set);
483}
484
485static Theme::Column *add_theme_simple_text_column(Theme *s,
486 const QString &name,
488 bool visibleByDefault,
489 SortOrder::MessageSorting messageSorting,
490 bool alignRight,
491 bool addGroupHeaderItem)
492{
493 auto c = new Theme::Column();
494 c->setLabel(name);
495 c->setVisibleByDefault(visibleByDefault);
496 c->setMessageSorting(messageSorting);
497
498 auto r = new Theme::Row();
499
500 auto i = new Theme::ContentItem(type);
501
502 if (alignRight) {
503 r->addRightItem(i);
504 } else {
505 r->addLeftItem(i);
506 }
507
508 c->addMessageRow(r);
509
510 if (addGroupHeaderItem) {
511 auto row = new Theme::Row();
512
513 auto iRow = new Theme::ContentItem(type);
514
515 if (alignRight) {
516 row->addRightItem(iRow);
517 } else {
518 row->addLeftItem(iRow);
519 }
520
521 c->addGroupHeaderRow(row);
522 }
523
524 s->addColumn(c);
525
526 return c;
527}
528
529static Theme::Column *add_theme_simple_icon_column(Theme *s,
530 const QString &name,
531 const QString &pixmapName,
533 bool visibleByDefault,
534 SortOrder::MessageSorting messageSorting)
535{
536 auto c = new Theme::Column();
537 c->setLabel(name);
538 c->setPixmapName(pixmapName);
539 c->setVisibleByDefault(visibleByDefault);
540 c->setMessageSorting(messageSorting);
541
542 auto r = new Theme::Row();
543
544 auto i = new Theme::ContentItem(type);
545 i->setSoftenByBlendingWhenDisabled(true);
546
547 r->addLeftItem(i);
548
549 c->addMessageRow(r);
550
551 s->addColumn(c);
552
553 return c;
554}
555
556void Manager::createDefaultThemes()
557{
558 Theme *s;
559 Theme::Column *c;
560 Theme::Row *r;
562
563 // The "Classic" backward compatible theme
564
565 s = new Theme(i18nc("Default theme name", "Classic"), i18n("A simple, backward compatible, single row theme"), true /*readOnly*/
566 );
567
568 c = new Theme::Column();
569 c->setLabel(i18nc("@title:column Subject of messages", "Subject"));
571
572 r = new Theme::Row();
574 r->addLeftItem(i);
576 i->setBold(true);
577 r->addLeftItem(i);
578 c->addGroupHeaderRow(r);
579
580 r = new Theme::Row();
582 r->addLeftItem(i);
584 i->setHideWhenDisabled(true);
585 r->addLeftItem(i);
587 i->setHideWhenDisabled(true);
588 r->addLeftItem(i);
590 i->setHideWhenDisabled(true);
591 r->addLeftItem(i);
593 i->setHideWhenDisabled(true);
594 r->addLeftItem(i);
596 r->addLeftItem(i);
597 c->addMessageRow(r);
598
599 s->addColumn(c);
600
601 c = add_theme_simple_text_column(s,
602 i18n("Sender/Receiver"),
604 true,
606 false,
607 false);
608 c->setIsSenderOrReceiver(true);
609 add_theme_simple_text_column(s, i18nc("Sender of a message", "Sender"), Theme::ContentItem::Sender, false, SortOrder::SortMessagesBySender, false, false);
610 add_theme_simple_text_column(s,
611 i18nc("Receiver of a message", "Receiver"),
613 false,
615 false,
616 false);
617 add_theme_simple_text_column(s, i18nc("Date of a message", "Date"), Theme::ContentItem::Date, true, SortOrder::SortMessagesByDateTime, false, false);
618 add_theme_simple_text_column(s,
619 i18n("Most Recent Date"),
621 false,
623 false,
624 true);
625 add_theme_simple_text_column(s, i18nc("Size of a message", "Size"), Theme::ContentItem::Size, false, SortOrder::SortMessagesBySize, false, false);
626 add_theme_simple_icon_column(s,
627 i18nc("Attachment indication", "Attachment"),
628 QStringLiteral("mail-attachment"),
630 false,
632 add_theme_simple_icon_column(s,
633 i18n("Read/Unread"),
634 QStringLiteral("mail-mark-unread-new"),
636 false,
638 add_theme_simple_icon_column(s, i18n("Replied"), QStringLiteral("mail-replied"), Theme::ContentItem::RepliedStateIcon, false, SortOrder::NoMessageSorting);
639 add_theme_simple_icon_column(s,
640 i18nc("Message importance indication", "Important"),
641 QStringLiteral("mail-mark-important"),
643 false,
644 SortOrder::SortMessagesByImportantStatus);
645 add_theme_simple_icon_column(s,
646 i18n("Action Item"),
647 QStringLiteral("mail-task"),
649 false,
651 add_theme_simple_icon_column(s,
652 i18n("Spam/Ham"),
653 QStringLiteral("mail-mark-junk"),
655 false,
657 add_theme_simple_icon_column(s,
658 i18n("Watched/Ignored"),
659 QStringLiteral("mail-thread-watch"),
661 false,
663 add_theme_simple_icon_column(s,
664 i18n("Encryption"),
665 QStringLiteral("mail-encrypted-full"),
667 false,
669 add_theme_simple_icon_column(s,
670 i18n("Signature"),
671 QStringLiteral("mail-signed-verified"),
673 false,
675 add_theme_simple_icon_column(s, i18n("Tag List"), QStringLiteral("feed-subscribe"), Theme::ContentItem::TagList, false, SortOrder::NoMessageSorting);
676
677 s->resetColumnState(); // so it's initially set from defaults
678
679 addTheme(s);
680
681 // The Fancy theme
682
683 s = new Theme(i18n("Smart"), i18n("A smart multiline and multi item theme"), true /*readOnly*/
684 );
685
686 c = new Theme::Column();
687 c->setLabel(i18n("Message"));
688
689 r = new Theme::Row();
691 r->addLeftItem(i);
693 i->setBold(true);
694 r->addLeftItem(i);
695 c->addGroupHeaderRow(r);
696
697 r = new Theme::Row();
699 r->addLeftItem(i);
701 r->addRightItem(i);
703 i->setHideWhenDisabled(true);
704 r->addRightItem(i);
706 i->setHideWhenDisabled(true);
707 r->addRightItem(i);
709 i->setHideWhenDisabled(true);
710 r->addRightItem(i);
712 i->setHideWhenDisabled(true);
713 r->addRightItem(i);
715 i->setHideWhenDisabled(true);
716 r->addRightItem(i);
718 i->setHideWhenDisabled(true);
719 r->addRightItem(i);
720 c->addMessageRow(r);
721
722 Theme::Row *firstFancyRow = r; // save it so we can continue adding stuff below (after cloning the theme)
723
724 r = new Theme::Row();
726 i->setSoftenByBlending(true);
727 i->setItalic(true);
728 r->addLeftItem(i);
730 i->setSoftenByBlending(true);
731 i->setItalic(true);
732 r->addRightItem(i);
733 c->addMessageRow(r);
734
735 s->addColumn(c);
736
737 // clone the "Fancy theme" here so we'll use it as starting point for the "Fancy with clickable status"
738 auto fancyWithClickableStatus = new Theme(*s);
739 fancyWithClickableStatus->detach();
740 fancyWithClickableStatus->generateUniqueId();
741
742 // and continue the "Fancy" specific settings
743 r = firstFancyRow;
744
746 i->setHideWhenDisabled(true);
747 r->addRightItem(i);
749 i->setHideWhenDisabled(true);
750 r->addRightItem(i);
752 i->setHideWhenDisabled(true);
753 r->addRightItem(i);
755 i->setHideWhenDisabled(true);
756 r->addRightItem(i);
757
758 s->setViewHeaderPolicy(Theme::NeverShowHeader);
759
760 s->resetColumnState(); // so it's initially set from defaults
761
762 addTheme(s);
763
764 // The "Fancy with Clickable Status" theme
765
766 s = fancyWithClickableStatus;
767
768 s->setName(i18n("Smart with Clickable Status"));
769 s->setDescription(i18n("A smart multiline and multi item theme with a clickable status column"));
770 s->setReadOnly(true);
771
772 c = new Theme::Column();
773 c->setLabel(i18n("Status"));
774 c->setVisibleByDefault(true);
775
776 r = new Theme::Row();
779 r->addLeftItem(i);
782 r->addLeftItem(i);
783 c->addMessageRow(r);
784
785 r = new Theme::Row();
788 r->addLeftItem(i);
791 r->addLeftItem(i);
792 c->addMessageRow(r);
793
794 s->addColumn(c);
795
796 s->resetColumnState(); // so it's initially set from defaults
797
798 addTheme(s);
799}
800
801void Manager::removeAllThemes()
802{
803 QMap<QString, Theme *>::ConstIterator end(mThemes.constEnd());
804 for (QMap<QString, Theme *>::ConstIterator it = mThemes.constBegin(); it != end; ++it) {
805 delete (*it);
806 }
807
808 mThemes.clear();
809}
810
811void Manager::themesConfigurationCompleted()
812{
813 if (mThemes.isEmpty()) {
814 createDefaultThemes(); // panic
815 }
816
817 saveConfiguration(); // just to be sure :)
818
819 // notify all the widgets that they should reload the option set combos
820 Q_EMIT themesChanged();
821}
822
823void Manager::reloadAllWidgets()
824{
825 QList<Widget *>::ConstIterator end(mWidgetList.constEnd());
826 for (QList<Widget *>::ConstIterator it = mWidgetList.constBegin(); it != end; ++it) {
827 if ((*it)->view()) {
828 (*it)->view()->reload();
829 }
830 }
831}
832
833void Manager::reloadGlobalConfiguration()
834{
835 // This is called when configuration changes (probably edited by the options dialog)
836 const int oldDateFormat = (int)mDateFormatter->format();
837 const QString oldDateCustomFormat = mDateFormatter->customFormat();
838
839 loadGlobalConfiguration();
840
841 if ((oldDateFormat != (int)mDateFormatter->format()) || (oldDateCustomFormat != mDateFormatter->customFormat())) {
842 reloadAllWidgets();
843 }
844}
845
846void Manager::loadGlobalConfiguration()
847{
848 // Load the date format
849 const auto type = static_cast<MessageCore::DateFormatter::FormatType>(MessageCore::MessageCoreSettings::self()->dateFormat());
850 mDateFormatter->setCustomFormat(MessageCore::MessageCoreSettings::self()->customDateFormat());
851 mDateFormatter->setFormat(type);
852}
853
854void Manager::loadConfiguration()
855{
856 loadGlobalConfiguration();
857
858 {
859 // load Aggregations
860
861 KConfigGroup conf(MessageListSettings::self()->config(), QStringLiteral("MessageListView::Aggregations"));
862
863 mAggregations.clear();
864
865 const int cnt = conf.readEntry("Count", 0);
866
867 int idx = 0;
868 while (idx < cnt) {
869 const QString data = conf.readEntry(QStringLiteral("Set%1").arg(idx), QString());
870 if (!data.isEmpty()) {
871 auto set = new Aggregation();
872 if (set->loadFromString(data)) {
873 if (Aggregation *old = mAggregations.value(set->id())) {
874 delete old;
875 }
876 mAggregations.insert(set->id(), set);
877 } else {
878 delete set; // b0rken
879 }
880 }
881 idx++;
882 }
883
884 if (mAggregations.isEmpty()) {
885 // don't allow zero configuration, create some presets
886 createDefaultAggregations();
887 }
888 }
889
890 {
891 // load Themes
892
893 KConfigGroup conf(MessageListSettings::self()->config(), QStringLiteral("MessageListView::Themes"));
894
895 mThemes.clear();
896
897 const int cnt = conf.readEntry("Count", 0);
898
899 int idx = 0;
900 while (idx < cnt) {
901 const QString data = conf.readEntry(QStringLiteral("Set%1").arg(idx), QString());
902 if (!data.isEmpty()) {
903 auto set = new Theme();
904 if (set->loadFromString(data)) {
905 if (Theme *old = mThemes.value(set->id())) {
906 delete old;
907 }
908 mThemes.insert(set->id(), set);
909 } else {
910 qCWarning(MESSAGELIST_LOG) << "Saved theme loading failed";
911 delete set; // b0rken
912 }
913 }
914 ++idx;
915 }
916
917 if (mThemes.isEmpty()) {
918 // don't allow zero configuration, create some presets
919 createDefaultThemes();
920 }
921 }
922}
923
924void Manager::saveGlobalConfiguration()
925{
926 MessageListSettings::self()->save();
927}
928
929void Manager::saveConfiguration()
930{
931 saveGlobalConfiguration();
932
933 {
934 // store aggregations
935
936 KConfigGroup conf(MessageListSettings::self()->config(), QStringLiteral("MessageListView::Aggregations"));
937 // conf.clear();
938
939 conf.writeEntry("Count", mAggregations.count());
940
941 int idx = 0;
943 for (QMap<QString, Aggregation *>::ConstIterator it = mAggregations.constBegin(); it != end; ++it) {
944 conf.writeEntry(QStringLiteral("Set%1").arg(idx), (*it)->saveToString());
945 ++idx;
946 }
947 }
948
949 {
950 // store themes
951
952 KConfigGroup conf(MessageListSettings::self()->config(), QStringLiteral("MessageListView::Themes"));
953 // conf.clear();
954
955 conf.writeEntry("Count", mThemes.count());
956
957 int idx = 0;
958 QMap<QString, Theme *>::ConstIterator end(mThemes.constEnd());
959 for (QMap<QString, Theme *>::ConstIterator it = mThemes.constBegin(); it != end; ++it) {
960 conf.writeEntry(QStringLiteral("Set%1").arg(idx), (*it)->saveToString());
961 ++idx;
962 }
963 }
964
965 MessageListSettings::self()->config()->sync();
966}
967
968#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
ConstIterator
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 Mon Nov 4 2024 16:33:26 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.