Mailcommon

folderselectiondialog.cpp
1/*
2
3 SPDX-FileCopyrightText: 2009-2024 Laurent Montel <montel@kde.org>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6*/
7
8#include "folderselectiondialog.h"
9
10#include "foldersettings.h"
11#include "foldertreeview.h"
12#include "foldertreewidget.h"
13#include "foldertreewidgetproxymodel.h"
14#include "kernel/mailkernel.h"
15
16#include <Akonadi/CollectionCreateJob>
17#include <Akonadi/EntityMimeTypeFilterModel>
18#include <Akonadi/EntityTreeModel>
19
20#include <KLocalizedString>
21#include <KMessageBox>
22#include <QInputDialog>
23#include <QMenu>
24
25#include <KConfigGroup>
26#include <QDialogButtonBox>
27#include <QPushButton>
28#include <QShowEvent>
29#include <QVBoxLayout>
30
31using namespace MailCommon;
32class Q_DECL_HIDDEN MailCommon::FolderSelectionDialog::FolderSelectionDialogPrivate
33{
34public:
35 FolderTreeWidget *folderTreeWidget = nullptr;
36 QPushButton *mUser1Button = nullptr;
37 QPushButton *mOkButton = nullptr;
38 bool mNotAllowToCreateNewFolder = false;
39 bool mUseGlobalSettings = true;
40};
41
42FolderSelectionDialog::FolderSelectionDialog(QWidget *parent, SelectionFolderOptions options)
43 : QDialog(parent)
44 , d(new FolderSelectionDialogPrivate())
45{
46 setObjectName(QLatin1StringView("folder dialog"));
47
48 d->mNotAllowToCreateNewFolder = (options & FolderSelectionDialog::NotAllowToCreateNewFolder);
50 auto mainLayout = new QVBoxLayout(this);
51 d->mOkButton = buttonBox->button(QDialogButtonBox::Ok);
52 d->mOkButton->setDefault(true);
53 d->mOkButton->setAutoDefault(true);
54 d->mOkButton->setShortcut(Qt::CTRL | Qt::Key_Return);
55 connect(buttonBox, &QDialogButtonBox::accepted, this, &FolderSelectionDialog::accept);
56 connect(buttonBox, &QDialogButtonBox::rejected, this, &FolderSelectionDialog::reject);
57
58 if (!d->mNotAllowToCreateNewFolder) {
59 d->mUser1Button = new QPushButton;
60 d->mUser1Button->setDefault(false);
61 d->mUser1Button->setAutoDefault(false);
62 buttonBox->addButton(d->mUser1Button, QDialogButtonBox::ActionRole);
63 KGuiItem::assign(d->mUser1Button,
64 KGuiItem(i18nc("@action:button", "&New Subfolder…"),
65 QStringLiteral("folder-new"),
66 i18n("Create a new subfolder under the currently selected folder")));
67 }
68 FolderTreeWidget::TreeViewOptions opt = FolderTreeWidget::None;
69 if (options & FolderSelectionDialog::ShowUnreadCount) {
70 opt |= FolderTreeWidget::ShowUnreadCount;
71 }
72 opt |= FolderTreeWidget::UseDistinctSelectionModel;
73
74 FolderTreeWidgetProxyModel::FolderTreeWidgetProxyModelOptions optReadableProxy = FolderTreeWidgetProxyModel::None;
75
76 if (options & FolderSelectionDialog::HideVirtualFolder) {
77 optReadableProxy |= FolderTreeWidgetProxyModel::HideVirtualFolder;
78 }
79
80 optReadableProxy |= FolderTreeWidgetProxyModel::HideSpecificFolder;
81
82 if (options & FolderSelectionDialog::HideOutboxFolder) {
83 optReadableProxy |= FolderTreeWidgetProxyModel::HideOutboxFolder;
84 }
85
86 d->folderTreeWidget = new FolderTreeWidget(this, nullptr, opt, optReadableProxy);
87 d->folderTreeWidget->readConfig();
88 d->folderTreeWidget->disableContextMenuAndExtraColumn();
89 d->folderTreeWidget->folderTreeWidgetProxyModel()->setEnabledCheck((options & EnableCheck));
90 // Necessary otherwise we overwrite tooltip config for all application
91 d->folderTreeWidget->folderTreeView()->disableSaveConfig();
92 d->folderTreeWidget->folderTreeView()->setTooltipsPolicy(FolderTreeWidget::DisplayNever);
93 d->folderTreeWidget->folderTreeView()->setEnableDragDrop(false);
94 mainLayout->addWidget(d->folderTreeWidget);
95 mainLayout->addWidget(buttonBox);
96
97 d->mOkButton->setEnabled(false);
98 if (!d->mNotAllowToCreateNewFolder) {
99 d->mUser1Button->setEnabled(false);
100 connect(d->mUser1Button, &QPushButton::clicked, this, &FolderSelectionDialog::slotAddChildFolder);
101 d->folderTreeWidget->folderTreeView()->setContextMenuPolicy(Qt::CustomContextMenu);
102 connect(d->folderTreeWidget->folderTreeView(),
104 this,
105 &FolderSelectionDialog::slotFolderTreeWidgetContextMenuRequested);
106 }
107
108 connect(d->folderTreeWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &FolderSelectionDialog::slotSelectionChanged);
109 connect(d->folderTreeWidget->folderTreeWidgetProxyModel(), &QAbstractItemModel::rowsInserted, this, &FolderSelectionDialog::rowsInserted);
110
111 connect(d->folderTreeWidget->folderTreeView(), &QAbstractItemView::doubleClicked, this, &FolderSelectionDialog::slotDoubleClick);
112
113 d->mUseGlobalSettings = !(options & NotUseGlobalSettings);
114 readConfig();
115}
116
117FolderSelectionDialog::~FolderSelectionDialog()
118{
119 writeConfig();
120}
121
122void FolderSelectionDialog::slotFolderTreeWidgetContextMenuRequested(const QPoint &pos)
123{
124 if (d->mUser1Button && d->mUser1Button->isEnabled() && d->folderTreeWidget->folderTreeView()->indexAt(pos).isValid()) {
125 QMenu menu(this);
126 menu.addAction(i18n("&New Subfolder…"), this, &FolderSelectionDialog::slotAddChildFolder);
127 menu.exec(QCursor::pos());
128 }
129}
130
131void FolderSelectionDialog::slotDoubleClick(const QModelIndex &index)
132{
133 Q_UNUSED(index)
134 const bool hasSelectedCollection = (!d->folderTreeWidget->selectionModel()->selectedIndexes().isEmpty());
135 if (hasSelectedCollection) {
136 accept();
137 }
138}
139
140void FolderSelectionDialog::focusTreeView()
141{
142 d->folderTreeWidget->folderTreeView()->expandAll();
143 d->folderTreeWidget->folderTreeView()->setFocus();
144}
145
146void FolderSelectionDialog::showEvent(QShowEvent *event)
147{
148 if (!event->spontaneous()) {
149 focusTreeView();
150 FolderTreeView *view = d->folderTreeWidget->folderTreeView();
151 view->scrollTo(view->currentIndex());
152 }
154}
155
156void FolderSelectionDialog::rowsInserted(const QModelIndex &, int, int)
157{
158 d->folderTreeWidget->folderTreeView()->expandAll();
159}
160
161bool FolderSelectionDialog::canCreateCollection(Akonadi::Collection &parentCol)
162{
163 parentCol = selectedCollection();
164 if (!parentCol.isValid()) {
165 return false;
166 }
167
169 return true;
170 }
171 return false;
172}
173
174void FolderSelectionDialog::slotAddChildFolder()
175{
176 Akonadi::Collection parentCol;
177 if (canCreateCollection(parentCol)) {
178 bool ok = false;
179 const QString name = QInputDialog::getText(this, i18nc("@title:window", "New Folder"), i18nc("@label:textbox, name of a thing", "Name"), {}, {}, &ok);
180
181 if (name.isEmpty() || !ok) {
182 return;
183 }
184
186 col.setName(name);
187 col.parentCollection().setId(parentCol.id());
188 auto job = new Akonadi::CollectionCreateJob(col);
189 connect(job, &Akonadi::CollectionCreateJob::result, this, &FolderSelectionDialog::collectionCreationResult);
190 }
191}
192
193void FolderSelectionDialog::collectionCreationResult(KJob *job)
194{
195 if (job->error()) {
196 KMessageBox::error(this, i18n("Could not create folder: %1", job->errorString()), i18n("Folder creation failed"));
197 }
198}
199
200void FolderSelectionDialog::slotSelectionChanged()
201{
202 const bool enablebuttons = (!d->folderTreeWidget->selectionModel()->selectedIndexes().isEmpty());
203 d->mOkButton->setEnabled(enablebuttons);
204
205 if (!d->mNotAllowToCreateNewFolder) {
207 d->mUser1Button->setEnabled(canCreateCollection(parent));
208 if (parent.isValid()) {
209 const QSharedPointer<FolderSettings> fd(FolderSettings::forCollection(parent, false));
210 d->mOkButton->setEnabled(fd->canCreateMessages());
211 }
212 }
213}
214
215void FolderSelectionDialog::setSelectionMode(QAbstractItemView::SelectionMode mode)
216{
217 d->folderTreeWidget->setSelectionMode(mode);
218}
219
220QAbstractItemView::SelectionMode FolderSelectionDialog::selectionMode() const
221{
222 return d->folderTreeWidget->selectionMode();
223}
224
225Akonadi::Collection FolderSelectionDialog::selectedCollection() const
226{
227 qDebug() << " d->folderTreeWidget->selectedCollection()" << d->folderTreeWidget->selectedCollection();
228 return d->folderTreeWidget->selectedCollection();
229}
230
231void FolderSelectionDialog::setSelectedCollection(const Akonadi::Collection &collection)
232{
233 d->folderTreeWidget->selectCollectionFolder(collection);
234}
235
236Akonadi::Collection::List FolderSelectionDialog::selectedCollections() const
237{
238 qDebug() << " selectedCollections " << d->folderTreeWidget->selectedCollections();
239 return d->folderTreeWidget->selectedCollections();
240}
241
242static const char myFilterConvertToSieveResultDialogGroupName[] = "FolderSelectionDialog";
243
244void FolderSelectionDialog::readConfig()
245{
246 KConfigGroup group(KernelIf->config(), QLatin1StringView(myFilterConvertToSieveResultDialogGroupName));
247
248 const QSize size = group.readEntry("Size", QSize(500, 300));
249 if (size.isValid()) {
250 resize(size);
251 }
252 if (d->mUseGlobalSettings) {
253 const Akonadi::Collection::Id id = SettingsIf->lastSelectedFolder();
254 if (id > -1) {
255 const Akonadi::Collection col = Kernel::self()->collectionFromId(id);
256 d->folderTreeWidget->selectCollectionFolder(col);
257 }
258 }
259}
260
261void FolderSelectionDialog::writeConfig()
262{
263 KConfigGroup group(KernelIf->config(), QLatin1StringView(myFilterConvertToSieveResultDialogGroupName));
264 group.writeEntry("Size", size());
265
266 if (d->mUseGlobalSettings) {
267 Akonadi::Collection col = selectedCollection();
268 if (col.isValid()) {
269 SettingsIf->setLastSelectedFolder(col.id());
270 }
271 }
272}
273
274void FolderSelectionDialog::hideEvent(QHideEvent *)
275{
276 d->folderTreeWidget->clearFilter();
277}
278
279#include "moc_folderselectiondialog.cpp"
QStringList contentMimeTypes() const
static QString mimeType()
bool isValid() const
void setName(const QString &name)
Rights rights() const
Collection & parentCollection()
void setId(Id identifier)
static void assign(QPushButton *button, const KGuiItem &item)
virtual QString errorString() const
int error() const
void result(KJob *job)
This is an enhanced EntityTreeView specially suited for the folders in KMail's main folder widget.
This is the widget that shows the main folder tree.
@ DisplayNever
Nevery display tooltips.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QString name(GameStandardAction id)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
The filter dialog.
void clicked(bool checked)
void rowsInserted(const QModelIndex &parent, int first, int last)
QModelIndex currentIndex() const const
void doubleClicked(const QModelIndex &index)
QPoint pos()
virtual void accept()
virtual void showEvent(QShowEvent *event) override
QString getText(QWidget *parent, const QString &title, const QString &label, QLineEdit::EchoMode mode, const QString &text, bool *ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints)
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
void setDefault(bool)
bool isEmpty() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
CustomContextMenu
Key_Return
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
virtual void scrollTo(const QModelIndex &index, ScrollHint hint) override
void customContextMenuRequested(const QPoint &pos)
virtual bool event(QEvent *event) override
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 12:00:48 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.