8#include "foldertreewidget.h"
9#include "entitycollectionorderproxymodel.h"
10#include "foldertreeview.h"
11#include "hierarchicalfoldermatcher_p.h"
12#include "kernel/mailkernel.h"
14#include <PimCommon/PimUtil>
15#include <PimCommonAkonadi/ImapAclAttribute>
17#include <Akonadi/AttributeFactory>
18#include <Akonadi/ChangeRecorder>
19#include <Akonadi/EntityMimeTypeFilterModel>
20#include <Akonadi/EntityTreeModel>
21#include <Akonadi/ItemFetchScope>
22#include <Akonadi/StatisticsProxyModel>
24#include <Akonadi/ETMViewStateSaver>
25#include <Akonadi/EntityTreeView>
27#include <KMime/Message>
29#include <MessageCore/MessageCoreSettings>
31#include <KLocalizedString>
33#include <QApplication>
34#include <QFontDatabase>
44class Q_DECL_HIDDEN
MailCommon::FolderTreeWidget::FolderTreeWidgetPrivate
53 QLineEdit *filterFolderLineEdit =
nullptr;
58 bool dontKeyFilter =
false;
61FolderTreeWidget::FolderTreeWidget(
QWidget *parent,
66 , d(new FolderTreeWidgetPrivate())
70 d->folderTreeView =
new FolderTreeView(xmlGuiClient,
this, options & ShowUnreadCount);
71 d->folderTreeView->showStatisticAnimation(options & ShowCollectionStatisticAnimation);
73 connect(d->folderTreeView, &FolderTreeView::manualSortingChanged,
this, &FolderTreeWidget::slotManualSortingChanged);
76 lay->setContentsMargins({});
78 d->label =
new QLabel(
i18nc(
"@label:textbox",
"You can start typing to filter the list of folders."),
this);
79 lay->addWidget(d->label);
81 d->filterFolderLineEdit =
new QLineEdit(
this);
83 d->filterFolderLineEdit->setClearButtonEnabled(
true);
84 d->filterFolderLineEdit->setPlaceholderText(
i18nc(
"@info Displayed grayed-out inside the textbox, verb to search",
"Search"));
85 lay->addWidget(d->filterFolderLineEdit);
87 if (!(options & HideStatistics)) {
89 d->filterModel->setSourceModel(KernelIf->collectionModel());
91 if (options & HideHeaderViewMenu) {
96 d->readableproxy->setSourceModel((options & HideStatistics) ?
static_cast<QAbstractItemModel *
>(KernelIf->collectionModel())
100 connect(d->folderTreeView, &FolderTreeView::changeTooltipsPolicy,
this, &FolderTreeWidget::slotChangeTooltipsPolicy);
104 d->folderTreeView->installEventFilter(
this);
108 d->entityOrderProxy->setSourceModel(d->readableproxy);
110 KConfigGroup grp(KernelIf->config(), QStringLiteral(
"CollectionTreeOrder"));
111 d->entityOrderProxy->setOrderConfig(grp);
112 d->folderTreeView->setModel(d->entityOrderProxy);
114 if (options & UseDistinctSelectionModel) {
118 lay->addWidget(d->folderTreeView);
120 d->dontKeyFilter = (options & DontKeyFilter);
122 if ((options & UseLineEditForFiltering)) {
126 d->filterFolderLineEdit->hide();
131FolderTreeWidget::~FolderTreeWidget() =
default;
133void FolderTreeWidget::slotFilterFixedString(
const QString &text)
136 if (d->oldFilterStr.isEmpty()) {
138 Akonadi::ETMViewStateSaver saver;
139 saver.setView(folderTreeView());
140 d->expandedItems = saver.expansionKeys();
141 d->currentItem = saver.currentIndexKey();
143 d->saver =
new Akonadi::ETMViewStateSaver;
144 d->saver->setView(folderTreeView());
145 QString currentIndex = d->saver->currentIndexKey();
146 if (d->saver->selectionKeys().isEmpty()) {
147 currentIndex = d->currentItem;
148 }
else if (!currentIndex.
isEmpty()) {
149 d->expandedItems << currentIndex;
151 d->saver->restoreExpanded(d->expandedItems);
152 d->saver->restoreCurrentItem(currentIndex);
154 d->folderTreeView->expandAll();
156 d->oldFilterStr = text;
157 d->entityOrderProxy->setFilterWildcard(text);
160void FolderTreeWidget::disableContextMenuAndExtraColumn()
162 d->folderTreeView->disableContextMenuAndExtraColumn();
165void FolderTreeWidget::selectCollectionFolder(
const Akonadi::Collection &collection,
bool expand)
169 d->folderTreeView->setCurrentIndex(index);
171 d->folderTreeView->setExpanded(index,
true);
173 d->folderTreeView->scrollTo(index);
178 d->folderTreeView->setSelectionMode(mode);
183 return d->folderTreeView->selectionMode();
188 return d->folderTreeView->selectionModel();
193 return d->folderTreeView->currentIndex();
203 return lstCollection.
at(0);
214 const QModelIndexList selectedIndexes = selectionModel->
selectedIndexes();
219 collections.
append(collection);
229 return d->folderTreeView;
232void FolderTreeWidget::slotGeneralFontChanged()
235 if (MessageCore::MessageCoreSettings::self()->useDefaultFonts()) {
240void FolderTreeWidget::slotGeneralPaletteChanged()
242 d->readableproxy->updatePalette();
243 d->folderTreeView->updatePalette();
246void FolderTreeWidget::readConfig()
250 d->folderTreeView->readConfig();
251 d->folderTreeView->setDropActionMenuEnabled(SettingsIf->showPopupAfterDnD());
252 d->readableproxy->setWarningThreshold(SettingsIf->closeToQuotaThreshold());
253 d->readableproxy->readConfig();
255 KConfigGroup readerConfig(KernelIf->config(), QStringLiteral(
"AccountOrder"));
257 if (readerConfig.readEntry(
"EnableAccountOrder",
true)) {
258 listOrder = readerConfig.readEntry(
"order",
QStringList());
260 d->entityOrderProxy->setTopLevelOrder(listOrder);
263void FolderTreeWidget::restoreHeaderState(
const QByteArray &data)
265 d->folderTreeView->restoreHeaderState(data);
270 changeToolTipsPolicyConfig(policy);
273void FolderTreeWidget::changeToolTipsPolicyConfig(ToolTipDisplayPolicy policy)
278 if (d->filterModel) {
279 d->filterModel->setToolTipEnabled(
true);
283 if (d->filterModel) {
284 d->filterModel->setToolTipEnabled(
false);
287 d->folderTreeView->setTooltipsPolicy(policy);
292 return d->filterModel;
297 return d->readableproxy;
302 return d->entityOrderProxy;
305QLineEdit *FolderTreeWidget::filterFolderLineEdit()
const
307 return d->filterFolderLineEdit;
310void FolderTreeWidget::applyFilter(
const QString &filter)
312 d->label->setText(
filter.isEmpty() ?
i18n(
"You can start typing to filter the list of folders.") :
i18n(
"Path: (%1)", filter));
314 HierarchicalFolderMatcher matcher;
315 matcher.setFilter(filter, d->entityOrderProxy->filterCaseSensitivity());
316 d->entityOrderProxy->setFolderMatcher(matcher);
319 const QModelIndex current = d->folderTreeView->currentIndex();
323 d->folderTreeView->setCurrentIndex(firstMatch);
325 d->folderTreeView->scrollTo(firstMatch);
329void FolderTreeWidget::clearFilter()
332 applyFilter(d->filter);
333 const QModelIndexList lst = d->folderTreeView->selectionModel()->selectedIndexes();
334 if (!lst.isEmpty()) {
335 d->folderTreeView->scrollTo(lst.first());
339void FolderTreeWidget::slotManualSortingChanged(
bool active)
341 d->entityOrderProxy->setManualSortingActive(active);
342 d->folderTreeView->setManualSortingActive(active);
348 if (d->dontKeyFilter) {
356 const int filterLength(d->filter.length());
357 if (filterLength > 0) {
358 d->filter.truncate(filterLength - 1);
359 applyFilter(d->filter);
365 applyFilter(d->filter);
371 applyFilter(d->filter);
380 applyFilter(d->filter);
386bool FolderTreeWidget::event(
QEvent *e)
389 slotGeneralPaletteChanged();
394void FolderTreeWidget::setAccountActivities(Akonadi::AccountActivitiesAbstract *accountActivities)
396 d->readableproxy->setAccountActivities(accountActivities);
399#include "moc_foldertreewidget.cpp"
static void registerAttribute()
static QModelIndex modelIndexForCollection(const QAbstractItemModel *model, const Collection &collection)
static QString mimeType()
The EntityCollectionOrderProxyModel class implements ordering of mail collections.
This is an enhanced EntityTreeView specially suited for the folders in KMail's main folder widget.
Q_SCRIPTABLE Q_NOREPLY void start()
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
const FMH::MODEL filterModel(const MODEL &model, const QVector< MODEL_KEY > &keys)
QString label(StandardShortcut id)
virtual QVariant data(const QModelIndex &index, int role) const const=0
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
bool isPrint(char32_t ucs4)
QFont systemFont(SystemFont type)
QString text() const const
void textChanged(const QString &text)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
bool isEmpty() const const
bool isValid() const const
const QAbstractItemModel * model() const const
const QChar at(qsizetype position) const const
bool isEmpty() const const
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)