File indexing completed on 2024-11-10 04:50:10

0001 /*
0002 
0003   SPDX-FileCopyrightText: 2009-2024 Laurent Montel <montel@kde.org>
0004 
0005   SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "folderselectiondialog.h"
0009 
0010 #include "foldersettings.h"
0011 #include "foldertreeview.h"
0012 #include "foldertreewidget.h"
0013 #include "foldertreewidgetproxymodel.h"
0014 #include "kernel/mailkernel.h"
0015 
0016 #include <Akonadi/CollectionCreateJob>
0017 #include <Akonadi/EntityMimeTypeFilterModel>
0018 #include <Akonadi/EntityTreeModel>
0019 
0020 #include <KLocalizedString>
0021 #include <KMessageBox>
0022 #include <QInputDialog>
0023 #include <QMenu>
0024 
0025 #include <KConfigGroup>
0026 #include <QDialogButtonBox>
0027 #include <QPushButton>
0028 #include <QShowEvent>
0029 #include <QVBoxLayout>
0030 
0031 using namespace MailCommon;
0032 class Q_DECL_HIDDEN MailCommon::FolderSelectionDialog::FolderSelectionDialogPrivate
0033 {
0034 public:
0035     FolderTreeWidget *folderTreeWidget = nullptr;
0036     QPushButton *mUser1Button = nullptr;
0037     QPushButton *mOkButton = nullptr;
0038     bool mNotAllowToCreateNewFolder = false;
0039     bool mUseGlobalSettings = true;
0040 };
0041 
0042 FolderSelectionDialog::FolderSelectionDialog(QWidget *parent, SelectionFolderOptions options)
0043     : QDialog(parent)
0044     , d(new FolderSelectionDialogPrivate())
0045 {
0046     setObjectName(QLatin1StringView("folder dialog"));
0047 
0048     d->mNotAllowToCreateNewFolder = (options & FolderSelectionDialog::NotAllowToCreateNewFolder);
0049     auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
0050     auto mainLayout = new QVBoxLayout(this);
0051     d->mOkButton = buttonBox->button(QDialogButtonBox::Ok);
0052     d->mOkButton->setDefault(true);
0053     d->mOkButton->setAutoDefault(true);
0054     d->mOkButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0055     connect(buttonBox, &QDialogButtonBox::accepted, this, &FolderSelectionDialog::accept);
0056     connect(buttonBox, &QDialogButtonBox::rejected, this, &FolderSelectionDialog::reject);
0057 
0058     if (!d->mNotAllowToCreateNewFolder) {
0059         d->mUser1Button = new QPushButton;
0060         d->mUser1Button->setDefault(false);
0061         d->mUser1Button->setAutoDefault(false);
0062         buttonBox->addButton(d->mUser1Button, QDialogButtonBox::ActionRole);
0063         KGuiItem::assign(d->mUser1Button,
0064                          KGuiItem(i18n("&New Subfolder..."), QStringLiteral("folder-new"), i18n("Create a new subfolder under the currently selected folder")));
0065     }
0066     FolderTreeWidget::TreeViewOptions opt = FolderTreeWidget::None;
0067     if (options & FolderSelectionDialog::ShowUnreadCount) {
0068         opt |= FolderTreeWidget::ShowUnreadCount;
0069     }
0070     opt |= FolderTreeWidget::UseDistinctSelectionModel;
0071 
0072     FolderTreeWidgetProxyModel::FolderTreeWidgetProxyModelOptions optReadableProxy = FolderTreeWidgetProxyModel::None;
0073 
0074     if (options & FolderSelectionDialog::HideVirtualFolder) {
0075         optReadableProxy |= FolderTreeWidgetProxyModel::HideVirtualFolder;
0076     }
0077 
0078     optReadableProxy |= FolderTreeWidgetProxyModel::HideSpecificFolder;
0079 
0080     if (options & FolderSelectionDialog::HideOutboxFolder) {
0081         optReadableProxy |= FolderTreeWidgetProxyModel::HideOutboxFolder;
0082     }
0083 
0084     d->folderTreeWidget = new FolderTreeWidget(this, nullptr, opt, optReadableProxy);
0085     d->folderTreeWidget->readConfig();
0086     d->folderTreeWidget->disableContextMenuAndExtraColumn();
0087     d->folderTreeWidget->folderTreeWidgetProxyModel()->setEnabledCheck((options & EnableCheck));
0088     // Necessary otherwise we overwrite tooltip config for all application
0089     d->folderTreeWidget->folderTreeView()->disableSaveConfig();
0090     d->folderTreeWidget->folderTreeView()->setTooltipsPolicy(FolderTreeWidget::DisplayNever);
0091     d->folderTreeWidget->folderTreeView()->setEnableDragDrop(false);
0092     mainLayout->addWidget(d->folderTreeWidget);
0093     mainLayout->addWidget(buttonBox);
0094 
0095     d->mOkButton->setEnabled(false);
0096     if (!d->mNotAllowToCreateNewFolder) {
0097         d->mUser1Button->setEnabled(false);
0098         connect(d->mUser1Button, &QPushButton::clicked, this, &FolderSelectionDialog::slotAddChildFolder);
0099         d->folderTreeWidget->folderTreeView()->setContextMenuPolicy(Qt::CustomContextMenu);
0100         connect(d->folderTreeWidget->folderTreeView(),
0101                 &QWidget::customContextMenuRequested,
0102                 this,
0103                 &FolderSelectionDialog::slotFolderTreeWidgetContextMenuRequested);
0104     }
0105 
0106     connect(d->folderTreeWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &FolderSelectionDialog::slotSelectionChanged);
0107     connect(d->folderTreeWidget->folderTreeWidgetProxyModel(), &QAbstractItemModel::rowsInserted, this, &FolderSelectionDialog::rowsInserted);
0108 
0109     connect(d->folderTreeWidget->folderTreeView(), &QAbstractItemView::doubleClicked, this, &FolderSelectionDialog::slotDoubleClick);
0110 
0111     d->mUseGlobalSettings = !(options & NotUseGlobalSettings);
0112     readConfig();
0113 }
0114 
0115 FolderSelectionDialog::~FolderSelectionDialog()
0116 {
0117     writeConfig();
0118 }
0119 
0120 void FolderSelectionDialog::slotFolderTreeWidgetContextMenuRequested(const QPoint &pos)
0121 {
0122     if (d->mUser1Button && d->mUser1Button->isEnabled() && d->folderTreeWidget->folderTreeView()->indexAt(pos).isValid()) {
0123         QMenu menu(this);
0124         menu.addAction(i18n("&New Subfolder..."), this, &FolderSelectionDialog::slotAddChildFolder);
0125         menu.exec(QCursor::pos());
0126     }
0127 }
0128 
0129 void FolderSelectionDialog::slotDoubleClick(const QModelIndex &index)
0130 {
0131     Q_UNUSED(index)
0132     const bool hasSelectedCollection = (!d->folderTreeWidget->selectionModel()->selectedIndexes().isEmpty());
0133     if (hasSelectedCollection) {
0134         accept();
0135     }
0136 }
0137 
0138 void FolderSelectionDialog::focusTreeView()
0139 {
0140     d->folderTreeWidget->folderTreeView()->expandAll();
0141     d->folderTreeWidget->folderTreeView()->setFocus();
0142 }
0143 
0144 void FolderSelectionDialog::showEvent(QShowEvent *event)
0145 {
0146     if (!event->spontaneous()) {
0147         focusTreeView();
0148         FolderTreeView *view = d->folderTreeWidget->folderTreeView();
0149         view->scrollTo(view->currentIndex());
0150     }
0151     QDialog::showEvent(event);
0152 }
0153 
0154 void FolderSelectionDialog::rowsInserted(const QModelIndex &, int, int)
0155 {
0156     d->folderTreeWidget->folderTreeView()->expandAll();
0157 }
0158 
0159 bool FolderSelectionDialog::canCreateCollection(Akonadi::Collection &parentCol)
0160 {
0161     parentCol = selectedCollection();
0162     if (!parentCol.isValid()) {
0163         return false;
0164     }
0165 
0166     if ((parentCol.rights() & Akonadi::Collection::CanCreateCollection) && parentCol.contentMimeTypes().contains(Akonadi::Collection::mimeType())) {
0167         return true;
0168     }
0169     return false;
0170 }
0171 
0172 void FolderSelectionDialog::slotAddChildFolder()
0173 {
0174     Akonadi::Collection parentCol;
0175     if (canCreateCollection(parentCol)) {
0176         bool ok = false;
0177         const QString name = QInputDialog::getText(this, i18nc("@title:window", "New Folder"), i18nc("@label:textbox, name of a thing", "Name"), {}, {}, &ok);
0178 
0179         if (name.isEmpty() || !ok) {
0180             return;
0181         }
0182 
0183         Akonadi::Collection col;
0184         col.setName(name);
0185         col.parentCollection().setId(parentCol.id());
0186         auto job = new Akonadi::CollectionCreateJob(col);
0187         connect(job, &Akonadi::CollectionCreateJob::result, this, &FolderSelectionDialog::collectionCreationResult);
0188     }
0189 }
0190 
0191 void FolderSelectionDialog::collectionCreationResult(KJob *job)
0192 {
0193     if (job->error()) {
0194         KMessageBox::error(this, i18n("Could not create folder: %1", job->errorString()), i18n("Folder creation failed"));
0195     }
0196 }
0197 
0198 void FolderSelectionDialog::slotSelectionChanged()
0199 {
0200     const bool enablebuttons = (!d->folderTreeWidget->selectionModel()->selectedIndexes().isEmpty());
0201     d->mOkButton->setEnabled(enablebuttons);
0202 
0203     if (!d->mNotAllowToCreateNewFolder) {
0204         Akonadi::Collection parent;
0205         d->mUser1Button->setEnabled(canCreateCollection(parent));
0206         if (parent.isValid()) {
0207             const QSharedPointer<FolderSettings> fd(FolderSettings::forCollection(parent, false));
0208             d->mOkButton->setEnabled(fd->canCreateMessages());
0209         }
0210     }
0211 }
0212 
0213 void FolderSelectionDialog::setSelectionMode(QAbstractItemView::SelectionMode mode)
0214 {
0215     d->folderTreeWidget->setSelectionMode(mode);
0216 }
0217 
0218 QAbstractItemView::SelectionMode FolderSelectionDialog::selectionMode() const
0219 {
0220     return d->folderTreeWidget->selectionMode();
0221 }
0222 
0223 Akonadi::Collection FolderSelectionDialog::selectedCollection() const
0224 {
0225     qDebug() << " d->folderTreeWidget->selectedCollection()" << d->folderTreeWidget->selectedCollection();
0226     return d->folderTreeWidget->selectedCollection();
0227 }
0228 
0229 void FolderSelectionDialog::setSelectedCollection(const Akonadi::Collection &collection)
0230 {
0231     d->folderTreeWidget->selectCollectionFolder(collection);
0232 }
0233 
0234 Akonadi::Collection::List FolderSelectionDialog::selectedCollections() const
0235 {
0236     qDebug() << " selectedCollections " << d->folderTreeWidget->selectedCollections();
0237     return d->folderTreeWidget->selectedCollections();
0238 }
0239 
0240 static const char myFilterConvertToSieveResultDialogGroupName[] = "FolderSelectionDialog";
0241 
0242 void FolderSelectionDialog::readConfig()
0243 {
0244     KConfigGroup group(KernelIf->config(), QLatin1StringView(myFilterConvertToSieveResultDialogGroupName));
0245 
0246     const QSize size = group.readEntry("Size", QSize(500, 300));
0247     if (size.isValid()) {
0248         resize(size);
0249     }
0250     if (d->mUseGlobalSettings) {
0251         const Akonadi::Collection::Id id = SettingsIf->lastSelectedFolder();
0252         if (id > -1) {
0253             const Akonadi::Collection col = Kernel::self()->collectionFromId(id);
0254             d->folderTreeWidget->selectCollectionFolder(col);
0255         }
0256     }
0257 }
0258 
0259 void FolderSelectionDialog::writeConfig()
0260 {
0261     KConfigGroup group(KernelIf->config(), QLatin1StringView(myFilterConvertToSieveResultDialogGroupName));
0262     group.writeEntry("Size", size());
0263 
0264     if (d->mUseGlobalSettings) {
0265         Akonadi::Collection col = selectedCollection();
0266         if (col.isValid()) {
0267             SettingsIf->setLastSelectedFolder(col.id());
0268         }
0269     }
0270 }
0271 
0272 void FolderSelectionDialog::hideEvent(QHideEvent *)
0273 {
0274     d->folderTreeWidget->clearFilter();
0275 }
0276 
0277 #include "moc_folderselectiondialog.cpp"