File indexing completed on 2024-11-24 04:43:04

0001 /*
0002     SPDX-FileCopyrightText: 2015-2024 Laurent Montel <montel@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "searchduplicateresultwidget.h"
0008 #include "job/mergecontactsjob.h"
0009 #include "widgets/mergecontactloseinformationwarning.h"
0010 
0011 #include "resultduplicatetreewidget.h"
0012 #include <Akonadi/CollectionComboBox>
0013 #include <Akonadi/GrantleeContactViewer>
0014 #include <KLocalizedString>
0015 #include <KTreeWidgetSearchLine>
0016 #include <KTreeWidgetSearchLineWidget>
0017 #include <QHBoxLayout>
0018 #include <QLabel>
0019 #include <QMenu>
0020 #include <QPushButton>
0021 #include <QSplitter>
0022 
0023 namespace KABMergeContacts
0024 {
0025 KADDRESSBOOKMERGELIB_EXPORT QAbstractItemModel *_k_searchDuplicateResultStubModel = nullptr;
0026 }
0027 
0028 using namespace KABMergeContacts;
0029 SearchDuplicateResultWidget::SearchDuplicateResultWidget(QWidget *parent)
0030     : QWidget(parent)
0031     , mResultTreeWidget(new ResultDuplicateTreeWidget(this))
0032     , mContactViewer(new KAddressBookGrantlee::GrantleeContactViewer(this))
0033     , mMergeContactWarning(new MergeContactLoseInformationWarning(this))
0034 {
0035     auto mainLayout = new QVBoxLayout(this);
0036     mainLayout->setContentsMargins({});
0037 
0038     auto splitter = new QSplitter;
0039     splitter->setObjectName(QLatin1StringView("splitter"));
0040     splitter->setChildrenCollapsible(false);
0041     mainLayout->addWidget(splitter);
0042     mResultTreeWidget->setObjectName(QLatin1StringView("result_treewidget"));
0043     mContactViewer->setObjectName(QLatin1StringView("contact_viewer"));
0044 
0045     mSearchInResultLineEdit = new KTreeWidgetSearchLineWidget(this, mResultTreeWidget);
0046     mSearchInResultLineEdit->setObjectName(QLatin1StringView("searchinresultlineedit"));
0047     mSearchInResultLineEdit->searchLine()->setClearButtonEnabled(true);
0048     mSearchInResultLineEdit->searchLine()->setPlaceholderText(i18n("Search in result..."));
0049 
0050     auto resultWidget = new QWidget(this);
0051     auto resultWidgetLayout = new QVBoxLayout(resultWidget);
0052     resultWidgetLayout->setContentsMargins({});
0053     resultWidgetLayout->addWidget(mSearchInResultLineEdit);
0054     resultWidgetLayout->addWidget(mResultTreeWidget);
0055     splitter->addWidget(resultWidget);
0056     splitter->addWidget(mContactViewer);
0057     connect(mResultTreeWidget, &ResultDuplicateTreeWidget::showContactPreview, mContactViewer, &KAddressBookGrantlee::GrantleeContactViewer::setContact);
0058     connect(mResultTreeWidget, &ResultDuplicateTreeWidget::customContextMenuRequested, this, &SearchDuplicateResultWidget::slotCustomContextMenuRequested);
0059 
0060     mMergeContactWarning->setObjectName(QLatin1StringView("mergecontactwarning"));
0061     connect(mMergeContactWarning, &MergeContactLoseInformationWarning::continueMerging, this, &SearchDuplicateResultWidget::slotAutomaticMerging);
0062     connect(mMergeContactWarning,
0063             &MergeContactLoseInformationWarning::customizeMergingContacts,
0064             this,
0065             &SearchDuplicateResultWidget::slotCustomizeMergingContacts);
0066     mainLayout->addWidget(mMergeContactWarning);
0067 
0068     auto mergeLayout = new QHBoxLayout;
0069     mainLayout->addLayout(mergeLayout);
0070     mergeLayout->addStretch();
0071 
0072     auto lab = new QLabel(i18n("Select AddressBook:"));
0073     lab->setObjectName(QLatin1StringView("select_addressbook_label"));
0074     mergeLayout->addWidget(lab);
0075 
0076     mCollectionCombobox = new Akonadi::CollectionComboBox(_k_searchDuplicateResultStubModel, this);
0077     mCollectionCombobox->setAccessRightsFilter(Akonadi::Collection::CanCreateItem);
0078     mCollectionCombobox->setMinimumWidth(250);
0079     mCollectionCombobox->setMimeTypeFilter(QStringList() << KContacts::Addressee::mimeType());
0080     mCollectionCombobox->setObjectName(QLatin1StringView("akonadicombobox"));
0081     connect(mCollectionCombobox, &Akonadi::CollectionComboBox::currentIndexChanged, this, &SearchDuplicateResultWidget::slotUpdateMergeButton);
0082     connect(mCollectionCombobox, &Akonadi::CollectionComboBox::activated, this, &SearchDuplicateResultWidget::slotUpdateMergeButton);
0083     mergeLayout->addWidget(mCollectionCombobox);
0084 
0085     mMergeContact = new QPushButton(i18n("Merge"), this);
0086     mMergeContact->setObjectName(QLatin1StringView("merge_contact_button"));
0087     connect(mMergeContact, &QPushButton::clicked, this, &SearchDuplicateResultWidget::slotMergeContact);
0088     mergeLayout->addWidget(mMergeContact);
0089     mMergeContact->setEnabled(false);
0090     // TODO make mMergeContact enable when selected item and collection valid
0091 }
0092 
0093 SearchDuplicateResultWidget::~SearchDuplicateResultWidget() = default;
0094 
0095 void SearchDuplicateResultWidget::slotCustomContextMenuRequested(const QPoint &)
0096 {
0097     QMenu menu(this);
0098     menu.addAction(i18n("Expand All"), this, &SearchDuplicateResultWidget::slotExpandAll);
0099     menu.addAction(i18n("Collapse All"), this, &SearchDuplicateResultWidget::slotCollapseAll);
0100     menu.addSeparator();
0101     menu.addAction(i18n("Select All"), this, &SearchDuplicateResultWidget::slotSelectAll);
0102     menu.addAction(i18n("Deselect All"), this, &SearchDuplicateResultWidget::slotDeselectAll);
0103     menu.exec(QCursor::pos());
0104 }
0105 
0106 void SearchDuplicateResultWidget::slotExpandAll()
0107 {
0108     mResultTreeWidget->expandAll();
0109 }
0110 
0111 void SearchDuplicateResultWidget::slotCollapseAll()
0112 {
0113     mResultTreeWidget->collapseAll();
0114 }
0115 
0116 void SearchDuplicateResultWidget::slotSelectAll()
0117 {
0118     mResultTreeWidget->checkAllItems();
0119 }
0120 
0121 void SearchDuplicateResultWidget::slotDeselectAll()
0122 {
0123     mResultTreeWidget->uncheckAllItems();
0124 }
0125 
0126 void SearchDuplicateResultWidget::setContacts(const QList<Akonadi::Item::List> &lstItem)
0127 {
0128     mResultTreeWidget->setContacts(lstItem);
0129 }
0130 
0131 void SearchDuplicateResultWidget::slotMergeContact()
0132 {
0133     mIndexListContact = 0;
0134     mListContactToMerge = mResultTreeWidget->selectedContactsToMerge();
0135     if (!mListContactToMerge.isEmpty()) {
0136         KABMergeContacts::MergeContacts mergeContacts;
0137         bool conflictFound = false;
0138         mResultConflictList.clear();
0139         for (const Akonadi::Item::List &lst : std::as_const(mListContactToMerge)) {
0140             mergeContacts.setItems(lst);
0141             const MergeContacts::ConflictInformations conflicts = mergeContacts.requiresManualSelectionOfInformation();
0142             if (conflicts != MergeContacts::None) {
0143                 conflictFound = true;
0144             }
0145             MergeConflictResult result;
0146             result.list = lst;
0147             result.conflictInformation = conflicts;
0148             mResultConflictList.append(result);
0149         }
0150 
0151         mMergeContact->setEnabled(false);
0152         if (conflictFound) {
0153             mMergeContactWarning->animatedShow();
0154         } else {
0155             // Detect if conflict.
0156             mergeContact();
0157         }
0158     }
0159 }
0160 
0161 void SearchDuplicateResultWidget::mergeContact()
0162 {
0163     if (mIndexListContact < mListContactToMerge.count()) {
0164         auto job = new KABMergeContacts::MergeContactsJob(this);
0165         job->setListItem(mListContactToMerge.at(mIndexListContact));
0166         job->setDestination(mCollectionCombobox->currentCollection());
0167         connect(job, &KABMergeContacts::MergeContactsJob::finished, this, &SearchDuplicateResultWidget::slotMergeDone);
0168         job->start();
0169     } else {
0170         Q_EMIT mergeDone();
0171     }
0172 }
0173 
0174 void SearchDuplicateResultWidget::slotMergeDone(const Akonadi::Item &item)
0175 {
0176     ++mIndexListContact;
0177     Q_EMIT contactMerged(item);
0178     mergeContact();
0179 }
0180 
0181 void SearchDuplicateResultWidget::slotUpdateMergeButton()
0182 {
0183     mMergeContact->setEnabled(mCollectionCombobox->currentCollection().isValid());
0184 }
0185 
0186 void SearchDuplicateResultWidget::slotAutomaticMerging()
0187 {
0188     mergeContact();
0189 }
0190 
0191 void SearchDuplicateResultWidget::slotCustomizeMergingContacts()
0192 {
0193     Q_EMIT customizeMergeContact(mResultConflictList, mCollectionCombobox->currentCollection());
0194 }
0195 
0196 #include "moc_searchduplicateresultwidget.cpp"