diff --git a/src/backends/abstractpersonaction.h b/src/backends/abstractpersonaction.h index 5e9f84d..238577e 100644 --- a/src/backends/abstractpersonaction.h +++ b/src/backends/abstractpersonaction.h @@ -1,48 +1,48 @@ /* Copyright (C) 2013 David Edmundson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef ABSTRACT_PERSON_ACTION_H #define ABSTRACT_PERSON_ACTION_H #include #include #include #include namespace KPeople { class PersonData; class KPEOPLEBACKEND_EXPORT AbstractPersonAction : public QObject { Q_OBJECT public: - AbstractPersonAction(QObject *parent); + explicit AbstractPersonAction(QObject *parent); /** A list of actions that can be executed for a contact * Disabled actions should not be added * * @param data passes the person we're creating the actions for * @param parent parent object for newly created actions */ virtual QList actionsForPerson(const PersonData &data, QObject *parent) const = 0; }; } #endif diff --git a/src/backends/allcontactsmonitor.cpp b/src/backends/allcontactsmonitor.cpp index cfed251..1411487 100644 --- a/src/backends/allcontactsmonitor.cpp +++ b/src/backends/allcontactsmonitor.cpp @@ -1,69 +1,67 @@ /* * Copyright (C) 2013 David Edmundson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #include "allcontactsmonitor.h" using namespace KPeople; class KPeople::AllContactsMonitorPrivate { public: - AllContactsMonitorPrivate(): - m_initialFetchDone(false), - m_initialFetchSucccess(false) + AllContactsMonitorPrivate() { } - bool m_initialFetchDone; - bool m_initialFetchSucccess; + bool m_initialFetchDone = false; + bool m_initialFetchSucccess = false; }; AllContactsMonitor::AllContactsMonitor(): QObject(), d_ptr(new AllContactsMonitorPrivate) { } AllContactsMonitor::~AllContactsMonitor() { delete d_ptr; } QMap AllContactsMonitor::contacts() { return QMap(); } bool AllContactsMonitor::isInitialFetchComplete() const { return d_ptr->m_initialFetchDone; } bool AllContactsMonitor::initialFetchSuccess() const { return d_ptr->m_initialFetchSucccess; } void AllContactsMonitor::emitInitialFetchComplete(bool success) { d_ptr->m_initialFetchDone = true; d_ptr->m_initialFetchSucccess = success; Q_EMIT initialFetchComplete(success); } diff --git a/src/declarative/declarativepersondata.h b/src/declarative/declarativepersondata.h index f434257..c3338bf 100644 --- a/src/declarative/declarativepersondata.h +++ b/src/declarative/declarativepersondata.h @@ -1,49 +1,49 @@ /* Copyright (C) 2013 David Edmundson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef DECLARATIVEPERSONDATA_H #define DECLARATIVEPERSONDATA_H #include "persondata.h" #include class DeclarativePersonData : public QObject { Q_OBJECT Q_PROPERTY(QString personUri READ personUri WRITE setPersonUri NOTIFY personChanged) Q_PROPERTY(KPeople::PersonData *person READ person NOTIFY personChanged) public: - DeclarativePersonData(QObject *parent = nullptr); + explicit DeclarativePersonData(QObject *parent = nullptr); void setPersonUri(const QString &id); QString personUri() const; KPeople::PersonData *person() const; Q_SIGNALS: void personChanged(); private: QString m_id; - KPeople::PersonData *m_person; + KPeople::PersonData *m_person = nullptr; }; #endif // DECLARATIVEPERSONDATA_H diff --git a/src/declarative/personactionsmodel_p.h b/src/declarative/personactionsmodel_p.h index 8f0f4b7..ffd64d5 100644 --- a/src/declarative/personactionsmodel_p.h +++ b/src/declarative/personactionsmodel_p.h @@ -1,69 +1,69 @@ /* Copyright (C) 2013 Martin Klapetek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PERSON_ACTIONS_H #define PERSON_ACTIONS_H #include class QAction; namespace KPeople { class PersonActionsPrivate; class PersonActionsModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(int count READ rowCount NOTIFY personChanged) Q_PROPERTY(QString personUri READ personUri WRITE setPersonUri NOTIFY personChanged) public: enum Roles { IconNameRole = Qt::UserRole + 1, ActionRole, ActionTypeRole }; - PersonActionsModel(QObject *parent = nullptr); - virtual ~PersonActionsModel(); + explicit PersonActionsModel(QObject *parent = nullptr); + ~PersonActionsModel() Q_DECL_OVERRIDE; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; QString personUri() const; void setPersonUri(const QString &personUri); QList actions() const; QHash roleNames() const Q_DECL_OVERRIDE; Q_INVOKABLE void triggerAction(int row) const; Q_SIGNALS: void personChanged(); private: void resetActions(); Q_DECLARE_PRIVATE(PersonActions) PersonActionsPrivate *const d_ptr; }; } #endif // PERSON_ACTIONS_H diff --git a/src/personmanager.cpp b/src/personmanager.cpp index 7d2412c..3371bb9 100644 --- a/src/personmanager.cpp +++ b/src/personmanager.cpp @@ -1,291 +1,291 @@ /* Copyright (C) 2013 David Edmundson Copyright 2013 Martin Klapetek This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "personmanager_p.h" #include #include #include #include #include #include #include class Transaction { public: Transaction(const QSqlDatabase &db); void cancel(); ~Transaction(); private: QSqlDatabase m_db; - bool m_cancelled; + bool m_cancelled = false; }; Transaction::Transaction(const QSqlDatabase &db) : m_db(db), m_cancelled(false) { m_db.transaction(); } void Transaction::cancel() { m_db.rollback(); m_cancelled = true; } Transaction::~Transaction() { if (!m_cancelled) { m_db.commit(); } } PersonManager::PersonManager(const QString &databasePath, QObject *parent): QObject(parent), m_db(QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), QStringLiteral("kpeoplePersonsManager"))) { m_db.setDatabaseName(databasePath); if (!m_db.open()) { qWarning() << "Couldn't open the database at" << databasePath; } m_db.exec(QStringLiteral("CREATE TABLE IF NOT EXISTS persons (contactID VARCHAR UNIQUE NOT NULL, personID INT NOT NULL)")); m_db.exec(QStringLiteral("CREATE INDEX IF NOT EXISTS contactIdIndex ON persons (contactId)")); m_db.exec(QStringLiteral("CREATE INDEX IF NOT EXISTS personIdIndex ON persons (personId)")); QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/KPeople"), QStringLiteral("org.kde.KPeople"), QStringLiteral("ContactAddedToPerson"), this, SIGNAL(contactAddedToPerson(QString,QString))); QDBusConnection::sessionBus().connect(QString(), QStringLiteral("/KPeople"), QStringLiteral("org.kde.KPeople"), QStringLiteral("ContactRemovedFromPerson"), this, SIGNAL(contactRemovedFromPerson(QString))); } PersonManager::~PersonManager() { } QMultiHash< QString, QString > PersonManager::allPersons() const { QMultiHash contactMapping; QSqlQuery query = m_db.exec(QStringLiteral("SELECT personID, contactID FROM persons")); while (query.next()) { const QString personUri = QLatin1String("kpeople://") + query.value(0).toString(); // we store as ints internally, convert it to a string here const QString contactID = query.value(1).toString(); contactMapping.insertMulti(personUri, contactID); } return contactMapping; } QStringList PersonManager::contactsForPersonUri(const QString &personUri) const { if (!personUri.startsWith(QLatin1String("kpeople://"))) { return QStringList(); } QStringList contactUris; //TODO port to the proper qsql method for args QSqlQuery query(m_db); query.prepare(QStringLiteral("SELECT contactID FROM persons WHERE personId = ?")); query.bindValue(0, personUri.mid(strlen("kpeople://"))); query.exec(); while (query.next()) { contactUris << query.value(0).toString(); } return contactUris; } QString PersonManager::personUriForContact(const QString &contactUri) const { QSqlQuery query(m_db); query.prepare(QStringLiteral("SELECT personId FROM persons WHERE contactId = ?")); query.bindValue(0, contactUri); query.exec(); if (query.next()) { return QLatin1String("kpeople://") + query.value(0).toString(); } return QString(); } QString PersonManager::mergeContacts(const QStringList &ids) { // no merging if we have only 0 || 1 ids if (ids.size() < 2) { return QString(); } QStringList metacontacts; QStringList contacts; bool rc = true; QList pendingMessages; // separate the passed ids to metacontacts and simple contacts Q_FOREACH (const QString &id, ids) { if (id.startsWith(QLatin1String("kpeople://"))) { metacontacts << id; } else { contacts << id; } } // create new personUriString // - if we're merging two simple contacts, create completely new id // - if we're merging an existing metacontact, take the first id and use it QString personUriString; if (metacontacts.count() == 0) { // query for the highest existing ID in the database and +1 it int personUri = 0; QSqlQuery query = m_db.exec(QStringLiteral("SELECT MAX(personID) FROM persons")); if (query.next()) { personUri = query.value(0).toInt(); personUri++; } personUriString = QLatin1String("kpeople://") + QString::number(personUri); } else { personUriString = metacontacts.first(); } // start a db transaction (ends automatically on destruction) Transaction t(m_db); // processed passed metacontacts if (metacontacts.count() > 1) { // collect all the contacts from other persons QStringList personContacts; Q_FOREACH (const QString &id, metacontacts) { if (id != personUriString) { personContacts << contactsForPersonUri(id); } } // iterate over all of the contacts and change their personID to the new personUriString Q_FOREACH (const QString &id, personContacts) { QSqlQuery updateQuery(m_db); updateQuery.prepare(QStringLiteral("UPDATE persons SET personID = ? WHERE contactID = ?")); updateQuery.bindValue(0, personUriString.mid(strlen("kpeople://"))); updateQuery.bindValue(1, id); if (!updateQuery.exec()) { rc = false; } QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KPeople"), QStringLiteral("org.kde.KPeople"), QStringLiteral("ContactRemovedFromPerson")); message.setArguments(QVariantList() << id); pendingMessages << message; message = QDBusMessage::createSignal(QStringLiteral("/KPeople"), QStringLiteral("org.kde.KPeople"), QStringLiteral("ContactAddedToPerson")); message.setArguments(QVariantList() << id << personUriString); } } // process passed contacts if (contacts.size() > 0) { Q_FOREACH (const QString &id, contacts) { QSqlQuery insertQuery(m_db); insertQuery.prepare(QStringLiteral("INSERT INTO persons VALUES (?, ?)")); insertQuery.bindValue(0, id); insertQuery.bindValue(1, personUriString.mid(strlen("kpeople://"))); //strip kpeople:// if (!insertQuery.exec()) { rc = false; } //FUTURE OPTIMIZATION - this would be best as one signal, but arguments become complex QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KPeople"), QStringLiteral("org.kde.KPeople"), QStringLiteral("ContactAddedToPerson")); message.setArguments(QVariantList() << id << personUriString); pendingMessages << message; } } //if success send all messages to other clients //otherwise roll back our database changes and return an empty string if (rc) { Q_FOREACH (const QDBusMessage &message, pendingMessages) { QDBusConnection::sessionBus().send(message); } } else { t.cancel(); personUriString.clear(); } return personUriString; } bool PersonManager::unmergeContact(const QString &id) { //remove rows from DB if (id.startsWith(QLatin1String("kpeople://"))) { QSqlQuery query(m_db); const QStringList contactUris = contactsForPersonUri(id); query.prepare(QStringLiteral("DELETE FROM persons WHERE personId = ?")); query.bindValue(0, id.mid(strlen("kpeople://"))); query.exec(); Q_FOREACH (const QString &contactUri, contactUris) { //FUTURE OPTIMIZATION - this would be best as one signal, but arguments become complex QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KPeople"), QStringLiteral("org.kde.KPeople"), QStringLiteral("ContactRemovedFromPerson")); message.setArguments(QVariantList() << contactUri); QDBusConnection::sessionBus().send(message); } } else { QSqlQuery query(m_db); query.prepare(QStringLiteral("DELETE FROM persons WHERE contactId = ?")); query.bindValue(0, id); query.exec(); //emit signal(dbus) Q_EMIT contactRemovedFromPerson(id); } //TODO return if removing rows worked return true; } PersonManager *PersonManager::instance(const QString &databasePath) { static PersonManager *s_instance = nullptr; if (!s_instance) { QString path = databasePath; if (path.isEmpty()) { path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/kpeople/"); QDir().mkpath(path); path += QLatin1String("persondb"); } s_instance = new PersonManager(path); } return s_instance; } diff --git a/src/personsmodel.h b/src/personsmodel.h index 81beadb..aa7d9fa 100644 --- a/src/personsmodel.h +++ b/src/personsmodel.h @@ -1,102 +1,102 @@ /* Persons Model Copyright (C) 2012 Martin Klapetek Copyright (C) 2012 Aleix Pol Gonzalez Copyright (C) 2013 David Edmundson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PERSONS_MODEL_H #define PERSONS_MODEL_H #include #include #include "global.h" namespace KPeople { class ContactItem; class PersonItem; class MetaContact; class PersonsModelPrivate; /** * This class creates a model of all known contacts from all sources * Contacts are represented as a tree where the top level represents a "person" which is an * amalgamation of all the sub-contacts * * @since 5.8 */ class KPEOPLE_EXPORT PersonsModel : public QAbstractItemModel { Q_OBJECT /** specifies whether the model has already been initialized */ Q_PROPERTY(bool isInitialized READ isInitialized NOTIFY modelInitialized) public: enum Role { FormattedNameRole = Qt::DisplayRole,//QString best name for this person PhotoRole = Qt::DecorationRole, //QPixmap best photo for this person PersonUriRole = Qt::UserRole, //QString ID of this person PersonVCardRole, //AbstractContact::Ptr ContactsVCardRole, //AbstractContact::List (FIXME or map?) GroupsRole, ///groups QStringList UserRole = Qt::UserRole + 0x1000 ///< in case it's needed to extend, use this one to start from }; Q_ENUM(Role) - PersonsModel(QObject *parent = nullptr); + explicit PersonsModel(QObject *parent = nullptr); - virtual ~PersonsModel(); + ~PersonsModel() Q_DECL_OVERRIDE; int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE; int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; QHash roleNames() const Q_DECL_OVERRIDE; /** @returns the index for a given @p personUri */ QModelIndex indexForPersonUri(const QString &personUri) const; /** Returns if all the backends have been initialized yet. */ bool isInitialized() const; /** Helper class to ease model access through QML */ Q_SCRIPTABLE QVariant get(int row, int role); /** * Makes it possible to access custom properties that are not available to the model * * @returns the property for the contact at @p index defined by the @p key */ QVariant contactCustomProperty(const QModelIndex &index, const QString &key) const; Q_SIGNALS: /** Will emit when the model is finally initialized. @p success will specify if it succeeded */ void modelInitialized(bool success); private: Q_DISABLE_COPY(PersonsModel) QScopedPointer const d_ptr; Q_DECLARE_PRIVATE(PersonsModel) }; } #endif // PERSONS_MODEL_H diff --git a/src/personssortfilterproxymodel.h b/src/personssortfilterproxymodel.h index faebb1b..b8ada2d 100644 --- a/src/personssortfilterproxymodel.h +++ b/src/personssortfilterproxymodel.h @@ -1,63 +1,63 @@ /* Copyright (C) 2015 Aleix Pol i Gonzalez This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PERSONSSORTFILTERMODEL_H #define PERSONSSORTFILTERMODEL_H #include #include #include namespace KPeople { class PersonsSortFilterProxyModelPrivate; /** * Helps filtering and sorting PresonsModel * * Especially useful for creating interfaces around specific properties rather * than the complete set as a whole. * * @sa PersonsModel * @since 5.12 */ class KPEOPLE_EXPORT PersonsSortFilterProxyModel : public QSortFilterProxyModel { Q_OBJECT /** Specifies the properties that should be provided by the contact for the contact to be shown. */ Q_PROPERTY(QStringList requiredProperties READ requiredProperties WRITE setRequiredProperties) public: - PersonsSortFilterProxyModel(QObject *parent = nullptr); - ~PersonsSortFilterProxyModel(); + explicit PersonsSortFilterProxyModel(QObject *parent = nullptr); + ~PersonsSortFilterProxyModel() Q_DECL_OVERRIDE; QStringList requiredProperties() const; void setRequiredProperties(const QStringList &props); bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const Q_DECL_OVERRIDE; private: Q_DISABLE_COPY(PersonsSortFilterProxyModel) QScopedPointer const d_ptr; Q_DECLARE_PRIVATE(PersonsSortFilterProxyModel) }; } #endif // PERSONSSORTFILTERMODEL_H diff --git a/src/widgets/mergedelegate.h b/src/widgets/mergedelegate.h index 7ef0505..690a5c5 100644 --- a/src/widgets/mergedelegate.h +++ b/src/widgets/mergedelegate.h @@ -1,56 +1,56 @@ /* KPeople - Duplicates Copyright (C) 2013 Franck Arrecot This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MERGEDELEGATE_H #define MERGEDELEGATE_H #include #include #include #include class QAbstractItemView; class QItemSelection; class KPEOPLEWIDGETS_EXPORT MergeDelegate: public KExtendableItemDelegate { Q_OBJECT public: explicit MergeDelegate(QAbstractItemView *parent); - ~MergeDelegate(); + ~MergeDelegate() Q_DECL_OVERRIDE; static QSize pictureSize(); public Q_SLOTS: void onClickContactParent(const QModelIndex &parent); void onSelectedContactsChanged(const QItemSelection &now, const QItemSelection &old); private: void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index)const Q_DECL_OVERRIDE; QWidget *buildExtensionWidget(const QModelIndex &idx); QWidget *buildMultipleLineLabel(const QModelIndex &idx); static QSize s_arrowSize; static QSize s_decorationSize; }; #endif // MERGEDELEGATE_H diff --git a/src/widgets/persondetailsview.cpp b/src/widgets/persondetailsview.cpp index e28e7ba..433b416 100644 --- a/src/widgets/persondetailsview.cpp +++ b/src/widgets/persondetailsview.cpp @@ -1,221 +1,221 @@ /* Copyright (C) 2011 Martin Klapetek Copyright (C) 2013 David Edmundson This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "persondetailsview.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "abstractfieldwidgetfactory.h" #include "plugins/emaildetailswidget.h" #include "global.h" #include "ui_person-details-presentation.h" namespace KPeople { class PersonDetailsViewPrivate { public: PersonData *m_person; Ui::PersonDetailsPresentation *m_personDetailsPresentation; QWidget *m_mainWidget; QList m_plugins; }; } using namespace KPeople; class CoreFieldsPlugin : public AbstractFieldWidgetFactory { public: CoreFieldsPlugin(const QString &field); - virtual ~CoreFieldsPlugin(); + ~CoreFieldsPlugin() Q_DECL_OVERRIDE; QString label() const Q_DECL_OVERRIDE; int sortWeight() const Q_DECL_OVERRIDE; QWidget *createDetailsWidget(const PersonData &person, QWidget *parent) const Q_DECL_OVERRIDE; private: QString m_field; }; CoreFieldsPlugin::CoreFieldsPlugin(const QString &field): m_field(field) { } CoreFieldsPlugin::~CoreFieldsPlugin() { } QString CoreFieldsPlugin::label() const { #ifdef __GNUC__ #warning fixme, should be made user-visible somehow #endif return m_field; } int CoreFieldsPlugin::sortWeight() const { return 1; } QWidget *CoreFieldsPlugin::createDetailsWidget(const PersonData &person, QWidget *parent) const { // we have a plugin specific for e-mails. if (m_field == QLatin1String("email")) { return nullptr; } QString text = person.contactCustomProperty(m_field).toString(); if (text.isEmpty()) { return nullptr; } return new QLabel(text, parent); } PersonDetailsView::PersonDetailsView(QWidget *parent) : QWidget(parent), d_ptr(new PersonDetailsViewPrivate()) { Q_D(PersonDetailsView); setLayout(new QVBoxLayout(this)); d->m_mainWidget = new QWidget(this); d->m_person = nullptr; QWidget *details = new QWidget(); d->m_personDetailsPresentation = new Ui::PersonDetailsPresentation(); d->m_personDetailsPresentation->setupUi(details); layout()->addWidget(details); layout()->addWidget(d->m_mainWidget); layout()->addItem(new QSpacerItem(1, 1, QSizePolicy::Fixed, QSizePolicy::Expanding)); //create plugins #ifdef __GNUC__ #warning figure out a way to list properties #endif QStringList fields { QStringLiteral("name"), QStringLiteral("all-email") }; Q_FOREACH (const QString &field, fields) { d->m_plugins << new CoreFieldsPlugin(field); } d->m_plugins << new EmailFieldsPlugin(); // load every KPeopleWidgets Plugin QVector personPluginList = KPluginLoader::findPlugins(QStringLiteral("kpeople/widgets")); Q_FOREACH (const KPluginMetaData &service, personPluginList) { KPluginLoader loader(service.fileName()); KPluginFactory *factory = loader.factory(); AbstractFieldWidgetFactory *f = qobject_cast(factory->create()); Q_ASSERT(f); if (f) { d->m_plugins << f; } } //TODO: Remove as soon as KTp sources are released with the new plugin system KService::List pluginList = KServiceTypeTrader::self()->query(QStringLiteral("KPeopleWidgets/Plugin")); QList plugins = KPluginInfo::fromServices(pluginList); Q_FOREACH (const KPluginInfo &p, plugins) { QString error; AbstractFieldWidgetFactory *f = p.service()->createInstance(this, QVariantList(), &error); if (f) { d->m_plugins << f; } } //TODO Sort plugins } PersonDetailsView::~PersonDetailsView() { delete d_ptr; } void PersonDetailsView::setPerson(PersonData *person) { Q_D(PersonDetailsView); if (d->m_person) { disconnect(d->m_person, SIGNAL(dataChanged()), this, SLOT(reload())); } d->m_person = person; connect(d->m_person, SIGNAL(dataChanged()), this, SLOT(reload())); reload(); } // void PersonDetailsView::setPersonsModel(PersonsModel *model) // { // Q_D(PersonDetailsView); // Q_FOREACH (AbstractPersonDetailsWidget *detailsWidget, d->m_detailWidgets) { // detailsWidget->setPersonsModel(model); // } // } void PersonDetailsView::reload() { Q_D(PersonDetailsView); //replace the entire main widget int layoutIndex = layout()->indexOf(d->m_mainWidget); layout()->takeAt(layoutIndex); d->m_mainWidget->deleteLater(); d->m_mainWidget = new QWidget(this); dynamic_cast(layout())->insertWidget(layoutIndex, d->m_mainWidget); QFormLayout *layout = new QFormLayout(d->m_mainWidget); layout->setSpacing(4); //update header information //FIXME - possibly split this out into a new class with a nice setPerson method QPixmap avatar = d->m_person->photo(); d->m_personDetailsPresentation->avatarPixmapLabel->setPixmap(avatar.scaled(96, 96, Qt::KeepAspectRatio)); //FIXME d->m_personDetailsPresentation->presencePixmapLabel->setPixmap(QIcon::fromTheme(d->m_person->presenceIconName()).pixmap(32, 32)); //FIXME d->m_personDetailsPresentation->nameLabel->setText(d->m_person->name()); Q_FOREACH (AbstractFieldWidgetFactory *widgetFactory, d->m_plugins) { const QString label = widgetFactory->label() + QLatin1Char(':'); QWidget *widget = widgetFactory->createDetailsWidget(d->m_person->personUri(), this); if (widget) { QFont font = widget->font(); font.setBold(true); widget->setFont(font); QLabel *widgetLabel = new QLabel(label, this); layout->addRow(widgetLabel, widget); } } } diff --git a/src/widgets/plugins/mergecontactswidget.cpp b/src/widgets/plugins/mergecontactswidget.cpp index 327f3d0..c20516e 100644 --- a/src/widgets/plugins/mergecontactswidget.cpp +++ b/src/widgets/plugins/mergecontactswidget.cpp @@ -1,192 +1,192 @@ /* Copyright (C) 2013 Franck Arrecot This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "mergecontactswidget.h" #include "personpresentationwidget.h" #include "persondata.h" #include "personsmodel.h" #include "duplicatesfinder_p.h" #include #include #include #include #include #include #include #include K_PLUGIN_FACTORY(MergeContactsWidgetFactory, registerPlugin();) K_EXPORT_PLUGIN(MergeContactsWidgetFactory("mergecontactswidgetplugin")) using namespace KPeople; MergeContactsWidget::MergeContactsWidget(QWidget *parent, const QVariantList &args) : AbstractPersonDetailsWidget(parent) - , m_person(0) - , m_model(0) - , m_containerListDetails(0) - , m_duplicatesBuster(0) + , m_person(nullptr) + , m_model(nullptr) + , m_containerListDetails(nullptr) + , m_duplicatesBuster(nullptr) { Q_UNUSED(args); setLayout(new QVBoxLayout()); m_mergeButton = new QPushButton(this); m_mergeButton->setText(i18n("Show Merge Suggestions...")); m_mergeButton->setVisible(false); connect(m_mergeButton, SIGNAL(clicked(bool)), this, SLOT(onMergePossibilitiesButtonPressed())); layout()->addWidget(m_mergeButton); } void MergeContactsWidget::setPerson(PersonData *person) { m_person = person; searchForDuplicates(); } void MergeContactsWidget::setPersonsModel(PersonsModel *model) { m_model = model; searchForDuplicates(); } void MergeContactsWidget::fillDuplicatesWidget(const QList &duplicates) { // clean the previous list delete m_containerListDetails; m_listMergeContacts.clear(); m_mergeButton->setVisible(!duplicates.isEmpty()); // 1- Vertical list of person-presentation-widget : one contact, one checkbox m_containerListDetails = new QWidget(this); m_containerListDetails->setLayout(new QVBoxLayout()); layout()->addWidget(m_containerListDetails); m_containerListDetails->setVisible(false); if (!duplicates.size()) { return ; } // building the new button QPushButton *triggerButton = new QPushButton(m_containerListDetails); triggerButton->setText(i18n("Merge with Selected Contacts")); connect(triggerButton, SIGNAL(clicked(bool)), this, SLOT(onMergeButtonPressed())); m_containerListDetails->layout()->addWidget(triggerButton); // building personPresentationWidget to fill up the list Q_FOREACH (const QPersistentModelIndex &duplicate, duplicates) { // displaying contact in a user friendly way kDebug() << "Name retireved form the duplicate :" << duplicate.data(Qt::DisplayRole).toString(); QIcon avatar ; QString name = duplicate.data(Qt::DisplayRole).toString(); QVariant decoration = duplicate.data(Qt::DecorationRole); if (decoration.type() == (QVariant::Icon)) { avatar = decoration.value(); } else if (decoration.type() == (QVariant::Pixmap)) { avatar = QIcon(decoration.value()); } // memorise the link between checkbox widget and model index PersonPresentationWidget *myMergeContactWidget = new PersonPresentationWidget(name, avatar, m_containerListDetails); m_containerListDetails->layout()->addWidget(myMergeContactWidget); m_listMergeContacts.append(qMakePair(duplicate, myMergeContactWidget)); } } QList MergeContactsWidget::duplicateBusterFromPerson(const QUrl &uri) const { Q_ASSERT(m_duplicatesBuster); QList wrongFormatResults = m_duplicatesBuster->results(); QList duplicateMatching; Q_FOREACH (const Match &match, wrongFormatResults) { // pick up only the couple with match with our parameter index QUrl uriA = match.indexA.data(PersonsModel::UriRole).toUrl(); // Tested with URI because QModelIndex isn't reliable if (uriA == uri) { duplicateMatching.append(match.indexB); } QUrl uriB = match.indexB.data(PersonsModel::UriRole).toUrl(); if (uriB == uri) { duplicateMatching.append(match.indexA); } } kDebug() << "Result of the duplicates Buster :" << duplicateMatching.size(); return duplicateMatching; } void MergeContactsWidget::searchForDuplicates() { m_mergeButton->setVisible(false); if (m_duplicatesBuster || !m_person || !m_person->isValid() || !m_model) { kDebug() << "Merge Widget failed to launch the duplicates search"; return; } m_duplicatesBuster = new DuplicatesFinder(m_model , this); connect(m_duplicatesBuster, SIGNAL(result(KJob*)), SLOT(searchForDuplicatesFinished())); m_duplicatesBuster->setSpecificPerson(m_person->uri()); m_duplicatesBuster->start(); } void MergeContactsWidget::searchForDuplicatesFinished() { QList duplicates = duplicateBusterFromPerson(m_person->uri()); fillDuplicatesWidget(duplicates); m_duplicatesBuster = 0; } void MergeContactsWidget::onMergePossibilitiesButtonPressed() { m_mergeButton->setVisible(false); m_containerListDetails->setVisible(true); } void MergeContactsWidget::onMergeButtonPressed() { // Retrieve the selected contacts QList urisToMerge; urisToMerge << m_person->uri(); // do the merge Q_FOREACH (const QPersistentModelIndex &pIndex, getContactsCheckedToMerge()) { urisToMerge << pIndex.data(PersonsModel::UriRole).toUrl(); } m_model->createPersonFromUris(urisToMerge); searchForDuplicates(); } QList MergeContactsWidget::getContactsCheckedToMerge() const { QList indexesToMerge; // retrieve all the widget where the box is checked QPair mergeContact ; Q_FOREACH (mergeContact, m_listMergeContacts) { if (mergeContact.second->isContactSelected()) { indexesToMerge.append(mergeContact.first); } } kDebug() << "Amount of checked box enable :" << indexesToMerge.size(); return indexesToMerge; } diff --git a/src/widgets/plugins/personpresentationwidget.h b/src/widgets/plugins/personpresentationwidget.h index a9077d6..ecb74f6 100644 --- a/src/widgets/plugins/personpresentationwidget.h +++ b/src/widgets/plugins/personpresentationwidget.h @@ -1,47 +1,47 @@ /* Copyright (C) 2013 Franck Arrecot This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef PERSONPRESENTATIONWIDGET_H #define PERSONPRESENTATIONWIDGET_H #include #include class QLabel; class PersonPresentationWidget : public QWidget { Q_OBJECT public: - PersonPresentationWidget(const QString &name, const QIcon &avatar, QWidget *parent = 0); + PersonPresentationWidget(const QString &name, const QIcon &avatar, QWidget *parent = nullptr); ~PersonPresentationWidget(); bool isContactSelected() const { return m_selected->isChecked() ; } private: void draw(); QLabel *m_pixmap; QLabel *m_phone; QLabel *m_email; QLabel *m_name; QCheckBox *m_selected; }; #endif // PERSONPRESENTATIONWIDGET_H