File indexing completed on 2025-01-05 04:47:08

0001 /*
0002     SPDX-FileCopyrightText: 2008 Ingo Klöcker <kloecker@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "collectionrequester.h"
0008 #include "collectionfetchjob.h"
0009 #include "collectionfetchscope.h"
0010 #include "entitydisplayattribute.h"
0011 
0012 #include <KLocalizedString>
0013 #include <KStandardShortcut>
0014 #include <QLineEdit>
0015 
0016 #include <QAction>
0017 #include <QEvent>
0018 #include <QHBoxLayout>
0019 #include <QPushButton>
0020 
0021 using namespace Akonadi;
0022 
0023 class Akonadi::CollectionRequesterPrivate
0024 {
0025 public:
0026     explicit CollectionRequesterPrivate(CollectionRequester *parent)
0027         : q(parent)
0028     {
0029     }
0030 
0031     ~CollectionRequesterPrivate()
0032     {
0033     }
0034 
0035     void fetchCollection(const Collection &collection);
0036 
0037     void init();
0038 
0039     // slots
0040     void _k_slotOpenDialog();
0041     void _k_collectionReceived(KJob *job);
0042     void _k_collectionsNamesReceived(KJob *job);
0043 
0044     CollectionRequester *const q;
0045     Collection collection;
0046     QLineEdit *edit = nullptr;
0047     QPushButton *button = nullptr;
0048     CollectionDialog *collectionDialog = nullptr;
0049 };
0050 
0051 void CollectionRequesterPrivate::fetchCollection(const Collection &collection)
0052 {
0053     auto job = new CollectionFetchJob(collection, Akonadi::CollectionFetchJob::Base, q);
0054     job->setProperty("OriginalCollectionId", collection.id());
0055     job->fetchScope().setAncestorRetrieval(CollectionFetchScope::All);
0056     QObject::connect(job, &CollectionFetchJob::finished, q, [this](KJob *job) {
0057         _k_collectionReceived(job);
0058     });
0059 }
0060 
0061 void CollectionRequesterPrivate::_k_collectionReceived(KJob *job)
0062 {
0063     auto fetch = qobject_cast<CollectionFetchJob *>(job);
0064     if (!fetch) {
0065         return;
0066     }
0067     if (fetch->collections().size() == 1) {
0068         Collection::List chain;
0069         Collection currentCollection = fetch->collections().at(0);
0070         while (currentCollection.isValid()) {
0071             chain << currentCollection;
0072             currentCollection = Collection(currentCollection.parentCollection());
0073         }
0074 
0075         auto namesFetch = new CollectionFetchJob(chain, CollectionFetchJob::Base, q);
0076         namesFetch->setProperty("OriginalCollectionId", job->property("OriginalCollectionId"));
0077         namesFetch->fetchScope().setAncestorRetrieval(CollectionFetchScope::Parent);
0078         QObject::connect(namesFetch, &CollectionFetchJob::finished, q, [this](KJob *job) {
0079             _k_collectionsNamesReceived(job);
0080         });
0081     } else {
0082         _k_collectionsNamesReceived(job);
0083     }
0084 }
0085 
0086 void CollectionRequesterPrivate::_k_collectionsNamesReceived(KJob *job)
0087 {
0088     auto fetch = qobject_cast<CollectionFetchJob *>(job);
0089     const qint64 originalId = fetch->property("OriginalCollectionId").toLongLong();
0090 
0091     QMap<qint64, Collection> names;
0092     const Akonadi::Collection::List lstCols = fetch->collections();
0093     for (const Collection &collection : lstCols) {
0094         names.insert(collection.id(), collection);
0095     }
0096 
0097     QStringList namesList;
0098     Collection currentCollection = names.take(originalId);
0099     while (currentCollection.isValid()) {
0100         namesList.prepend(currentCollection.displayName());
0101         currentCollection = names.take(currentCollection.parentCollection().id());
0102     }
0103     edit->setText(namesList.join(QLatin1Char('/')));
0104 }
0105 
0106 void CollectionRequesterPrivate::init()
0107 {
0108     auto hbox = new QHBoxLayout(q);
0109     hbox->setContentsMargins({});
0110 
0111     edit = new QLineEdit(q);
0112     edit->setReadOnly(true);
0113     edit->setPlaceholderText(i18n("No Folder"));
0114     edit->setClearButtonEnabled(false);
0115     edit->setFocusPolicy(Qt::NoFocus);
0116     hbox->addWidget(edit);
0117 
0118     button = new QPushButton(q);
0119     button->setIcon(QIcon::fromTheme(QStringLiteral("document-open")));
0120     const int buttonSize = edit->sizeHint().height();
0121     button->setFixedSize(buttonSize, buttonSize);
0122     button->setToolTip(i18n("Open collection dialog"));
0123     hbox->addWidget(button);
0124 
0125     hbox->setSpacing(-1);
0126 
0127     edit->installEventFilter(q);
0128     q->setFocusProxy(button);
0129     q->setFocusPolicy(Qt::StrongFocus);
0130 
0131     q->connect(button, &QPushButton::clicked, q, [this]() {
0132         _k_slotOpenDialog();
0133     });
0134 
0135     auto openAction = new QAction(q);
0136     openAction->setShortcut(KStandardShortcut::Open);
0137     q->connect(openAction, &QAction::triggered, q, [this]() {
0138         _k_slotOpenDialog();
0139     });
0140 
0141     collectionDialog = new CollectionDialog(q);
0142     collectionDialog->setWindowIcon(QIcon::fromTheme(QStringLiteral("akonadi")));
0143     collectionDialog->setWindowTitle(i18nc("@title:window", "Select a Collection"));
0144     collectionDialog->setSelectionMode(QAbstractItemView::SingleSelection);
0145     collectionDialog->changeCollectionDialogOptions(CollectionDialog::KeepTreeExpanded);
0146 }
0147 
0148 void CollectionRequesterPrivate::_k_slotOpenDialog()
0149 {
0150     CollectionDialog *dlg = collectionDialog;
0151 
0152     if (dlg->exec() != QDialog::Accepted) {
0153         return;
0154     }
0155 
0156     const Akonadi::Collection collection = dlg->selectedCollection();
0157     q->setCollection(collection);
0158     Q_EMIT q->collectionChanged(collection);
0159 }
0160 
0161 CollectionRequester::CollectionRequester(QWidget *parent)
0162     : QWidget(parent)
0163     , d(new CollectionRequesterPrivate(this))
0164 {
0165     d->init();
0166 }
0167 
0168 CollectionRequester::CollectionRequester(const Akonadi::Collection &collection, QWidget *parent)
0169     : QWidget(parent)
0170     , d(new CollectionRequesterPrivate(this))
0171 {
0172     d->init();
0173     setCollection(collection);
0174 }
0175 
0176 CollectionRequester::~CollectionRequester() = default;
0177 
0178 Collection CollectionRequester::collection() const
0179 {
0180     return d->collection;
0181 }
0182 
0183 void CollectionRequester::setCollection(const Collection &collection)
0184 {
0185     d->collection = collection;
0186     QString name;
0187     if (collection.isValid()) {
0188         name = collection.displayName();
0189     }
0190 
0191     d->edit->setText(name);
0192     Q_EMIT collectionChanged(collection);
0193     d->fetchCollection(collection);
0194 }
0195 
0196 void CollectionRequester::setMimeTypeFilter(const QStringList &mimeTypes)
0197 {
0198     if (d->collectionDialog) {
0199         d->collectionDialog->setMimeTypeFilter(mimeTypes);
0200     }
0201 }
0202 
0203 QStringList CollectionRequester::mimeTypeFilter() const
0204 {
0205     if (d->collectionDialog) {
0206         return d->collectionDialog->mimeTypeFilter();
0207     } else {
0208         return QStringList();
0209     }
0210 }
0211 
0212 void CollectionRequester::setAccessRightsFilter(Collection::Rights rights)
0213 {
0214     if (d->collectionDialog) {
0215         d->collectionDialog->setAccessRightsFilter(rights);
0216     }
0217 }
0218 
0219 Collection::Rights CollectionRequester::accessRightsFilter() const
0220 {
0221     if (d->collectionDialog) {
0222         return d->collectionDialog->accessRightsFilter();
0223     } else {
0224         return Akonadi::Collection::ReadOnly;
0225     }
0226 }
0227 
0228 void CollectionRequester::changeCollectionDialogOptions(CollectionDialog::CollectionDialogOptions options)
0229 {
0230     if (d->collectionDialog) {
0231         d->collectionDialog->changeCollectionDialogOptions(options);
0232     }
0233 }
0234 
0235 void CollectionRequester::setContentMimeTypes(const QStringList &mimetypes)
0236 {
0237     if (d->collectionDialog) {
0238         d->collectionDialog->setContentMimeTypes(mimetypes);
0239     }
0240 }
0241 
0242 void CollectionRequester::changeEvent(QEvent *event)
0243 {
0244     if (event->type() == QEvent::WindowTitleChange) {
0245         if (d->collectionDialog) {
0246             d->collectionDialog->setWindowTitle(windowTitle());
0247         }
0248     } else if (event->type() == QEvent::EnabledChange) {
0249         if (d->collectionDialog) {
0250             d->collectionDialog->setEnabled(true);
0251         }
0252     }
0253     QWidget::changeEvent(event);
0254 }
0255 
0256 #include "moc_collectionrequester.cpp"