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"