8#include "mergedialog.h"
9#include "duplicatesfinder_p.h"
10#include "matchessolver_p.h"
11#include "mergedelegate.h"
12#include "persondata.h"
13#include "personsmodel.h"
15#include "kpeople_widgets_debug.h"
17#include <QDialogButtonBox>
22#include <QStandardItemModel>
24#include <KLocalizedString>
25#include <KPixmapSequence>
26#include <KPixmapSequenceWidget>
28using namespace KPeople;
30class MergeDialogPrivate
33 PersonsModel *personsModel;
35 MergeDelegate *delegate;
37 QStandardItemModel *model;
38 DuplicatesFinder *duplicatesFinder;
39 KPixmapSequenceWidget *sequence;
42MergeDialog::MergeDialog(
QWidget *parent)
44 , d_ptr(new MergeDialogPrivate)
48 d_ptr->personsModel =
nullptr;
49 d_ptr->delegate =
nullptr;
50 d_ptr->duplicatesFinder =
nullptr;
52 setWindowTitle(
i18n(
"Duplicates Manager"));
56 setMinimumSize(450, 350);
60 d->view->setModel(d->model);
68 connect(buttons, SIGNAL(accepted()), SLOT(onMergeButtonClicked()));
69 connect(buttons, SIGNAL(rejected()), SLOT(reject()));
72 d->sequence->setSequence(
KPixmapSequence(QStringLiteral(
"process-working"), 22));
73 d->sequence->setInterval(100);
74 d->sequence->setVisible(
false);
76 layout->addWidget(topLabel);
77 layout->addWidget(d->view);
78 layout->addWidget(d->sequence);
79 layout->addWidget(buttons);
82MergeDialog::~MergeDialog()
90 d->personsModel = model;
91 if (d->personsModel) {
92 searchForDuplicates();
93 connect(d->personsModel, SIGNAL(modelInitialized(
bool)), SLOT(searchForDuplicates()));
97void MergeDialog::searchForDuplicates()
100 if (!d->personsModel || !d->personsModel->rowCount() || d->duplicatesFinder) {
101 qCWarning(KPEOPLE_WIDGETS_LOG) <<
"MergeDialog failed to launch the duplicates research";
104 d->duplicatesFinder =
new DuplicatesFinder(d->personsModel);
106 d->duplicatesFinder->start();
109void MergeDialog::onMergeButtonClicked()
112 QList<Match> matches;
113 for (
int i = 0, rows = d->model->rowCount(); i < rows; i++) {
114 QStandardItem *item = d->model->item(i, 0);
116 for (
int j = 0, contactsCount = item->
rowCount(); j < contactsCount; ++j) {
117 QStandardItem *matchItem = item->
child(j);
118 matches << matchItem->
data(MergeDialog::MergeReasonRole).
value<Match>();
123 MatchesSolver *solverJob =
new MatchesSolver(matches, d->personsModel,
this);
125 d->sequence->setVisible(
true);
126 d->view->setEnabled(
false);
130void MergeDialog::searchForDuplicatesFinished(KJob *)
133 feedDuplicateModelFromMatches(d->duplicatesFinder->results());
135 d->delegate =
new MergeDelegate(d->view);
136 d->view->setItemDelegate(d->delegate);
139 connect(d->view->selectionModel(),
140 SIGNAL(selectionChanged(QItemSelection, QItemSelection)),
142 SLOT(onSelectedContactsChanged(QItemSelection, QItemSelection)));
144 connect(d->view, SIGNAL(doubleClicked(QModelIndex)), d->delegate, SLOT(onClickContactParent(QModelIndex)));
147void MergeDialog::feedDuplicateModelFromMatches(
const QList<Match> &matches)
150 QHash<QPersistentModelIndex, QList<Match>> compareTable;
151 QHash<QPersistentModelIndex, QPersistentModelIndex> doneIndexes;
153 for (
const Match &match : matches) {
154 QPersistentModelIndex destination = doneIndexes.
value(
match.indexA,
match.indexA);
155 QHash<QPersistentModelIndex, QList<Match>>::iterator currentValue = compareTable.
find(destination);
157 if (currentValue == compareTable.
end()) {
158 compareTable[
match.indexA] = QList<Match>() <<
match;
160 currentValue->append(match);
162 doneIndexes[
match.indexB] = destination;
165 QStandardItem *rootItem = d->model->invisibleRootItem();
166 QHash<QPersistentModelIndex, QList<Match>>::const_iterator i;
170 QStandardItem *
parent = itemMergeContactFromMatch(
true, i->first());
173 for (
const Match &matchChild : std::as_const(*i)) {
174 parent->appendRow(itemMergeContactFromMatch(
false, matchChild));
181QStandardItem *MergeDialog::itemMergeContactFromMatch(
bool isParent,
const Match &match)
183 QStandardItem *item =
new QStandardItem;
188 item->
setData(
true, KExtendableItemDelegate::ShowExtensionIndicatorRole);
192 QString uri =
match.indexB.data(PersonsModel::PersonUriRole).toString();
200 QString uri =
match.indexA.data(PersonsModel::PersonUriRole).toString();
209 icon = deco.
value<QIcon>();
211 icon = QIcon(deco.
value<QPixmap>());
215 qCWarning(KPEOPLE_WIDGETS_LOG) <<
"unknown decoration type" << deco.
typeName();
221#include "moc_mergedialog.cpp"
The merge dialog will be used to provide a GUI to attempt to figure out what contacts should be merge...
void setPersonsModel(PersonsModel *model)
Specifies which PersonsModel will be used to look for duplicates.
This class creates a model of all known contacts from all sources Contacts are represented as a tree ...
QString i18n(const char *text, const TYPE &arg...)
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
void finished(int result)
const_iterator constBegin() const const
const_iterator constEnd() const const
iterator find(const Key &key)
T value(const Key &key) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
QPixmap fromImage(QImage &&image, Qt::ImageConversionFlags flags)
void appendRow(QStandardItem *item)
Qt::CheckState checkState() const const
QStandardItem * child(int row, int column) const const
virtual QVariant data(int role) const const
int rowCount() const const
void setCheckState(Qt::CheckState state)
void setCheckable(bool checkable)
virtual void setData(const QVariant &value, int role)
void setIcon(const QIcon &icon)
void setSizeHint(const QSize &size)
void setText(const QString &text)
void sortChildren(int column, Qt::SortOrder order)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QVariant fromValue(T &&value)
const char * typeName() const const
int userType() const const