diff --git a/autotests/libs/cachepolicytest.cpp b/autotests/libs/cachepolicytest.cpp index 918ba5d07..1e98c5af8 100644 --- a/autotests/libs/cachepolicytest.cpp +++ b/autotests/libs/cachepolicytest.cpp @@ -1,46 +1,46 @@ /* - Copyright (C) 2017-2018 Laurent Montel + Copyright (C) 2017-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "cachepolicytest.h" #include "cachepolicy.h" #include CachePolicyTest::CachePolicyTest(QObject *parent) : QObject(parent) { } CachePolicyTest::~CachePolicyTest() { } void CachePolicyTest::shouldHaveDefaultValue() { Akonadi::CachePolicy c; QVERIFY(c.inheritFromParent()); QCOMPARE(c.intervalCheckTime(), -1); QCOMPARE(c.cacheTimeout(), -1); QVERIFY(!c.syncOnDemand()); QVERIFY(c.localParts().isEmpty()); } QTEST_MAIN(CachePolicyTest) diff --git a/autotests/libs/cachepolicytest.h b/autotests/libs/cachepolicytest.h index 38563a985..30fa9c611 100644 --- a/autotests/libs/cachepolicytest.h +++ b/autotests/libs/cachepolicytest.h @@ -1,35 +1,35 @@ /* - Copyright (C) 2017-2018 Laurent Montel + Copyright (C) 2017-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef CACHEPOLICYTEST_H #define CACHEPOLICYTEST_H #include class CachePolicyTest : public QObject { Q_OBJECT public: explicit CachePolicyTest(QObject *parent = nullptr); ~CachePolicyTest(); private Q_SLOTS: void shouldHaveDefaultValue(); }; #endif // CACHEPOLICYTEST_H diff --git a/autotests/libs/conflictresolvedialogtest.cpp b/autotests/libs/conflictresolvedialogtest.cpp index 7d0e82f5f..dfbdc026c 100644 --- a/autotests/libs/conflictresolvedialogtest.cpp +++ b/autotests/libs/conflictresolvedialogtest.cpp @@ -1,64 +1,64 @@ /* - Copyright (C) 2017-2018 Laurent Montel + Copyright (C) 2017-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "conflictresolvedialogtest.h" #include "../src/widgets/conflictresolvedialog_p.h" #include #include #include #include QTEST_MAIN(ConflictResolveDialogTest) ConflictResolveDialogTest::ConflictResolveDialogTest(QObject *parent) : QObject(parent) { } void ConflictResolveDialogTest::shouldHaveDefaultValues() { Akonadi::ConflictResolveDialog dlg; QVERIFY(!dlg.windowTitle().isEmpty()); QPushButton *takeLeftButton = dlg.findChild(QStringLiteral("takeLeftButton")); QVERIFY(takeLeftButton); QVERIFY(!takeLeftButton->text().isEmpty()); QPushButton *takeRightButton = dlg.findChild(QStringLiteral("takeRightButton")); QVERIFY(takeRightButton); QVERIFY(!takeRightButton->text().isEmpty()); QPushButton *keepBothButton = dlg.findChild(QStringLiteral("keepBothButton")); QVERIFY(keepBothButton); QVERIFY(!keepBothButton->text().isEmpty()); QVERIFY(keepBothButton->isDefault()); QTextBrowser *mView = dlg.findChild(QStringLiteral("view")); QVERIFY(mView); QVERIFY(mView->toPlainText().isEmpty()); QLabel *docuLabel = dlg.findChild(QStringLiteral("doculabel")); QVERIFY(docuLabel); QVERIFY(!docuLabel->text().isEmpty()); QVERIFY(docuLabel->wordWrap()); QCOMPARE(docuLabel->contextMenuPolicy(), Qt::NoContextMenu); } diff --git a/autotests/libs/conflictresolvedialogtest.h b/autotests/libs/conflictresolvedialogtest.h index 8f73bf688..acf6dd4d3 100644 --- a/autotests/libs/conflictresolvedialogtest.h +++ b/autotests/libs/conflictresolvedialogtest.h @@ -1,36 +1,36 @@ /* - Copyright (C) 2017-2018 Laurent Montel + Copyright (C) 2017-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef CONFLICTRESOLVEDIALOGTEST_H #define CONFLICTRESOLVEDIALOGTEST_H #include class ConflictResolveDialogTest : public QObject { Q_OBJECT public: explicit ConflictResolveDialogTest(QObject *parent = nullptr); ~ConflictResolveDialogTest() = default; private Q_SLOTS: void shouldHaveDefaultValues(); }; #endif // CONFLICTRESOLVEDIALOGTEST_H diff --git a/autotests/libs/newmailnotifierattributetest.cpp b/autotests/libs/newmailnotifierattributetest.cpp index 9925d0f87..b0c702316 100644 --- a/autotests/libs/newmailnotifierattributetest.cpp +++ b/autotests/libs/newmailnotifierattributetest.cpp @@ -1,75 +1,75 @@ /* - Copyright (c) 2014-2018 Montel Laurent + Copyright (c) 2014-2019 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "newmailnotifierattributetest.h" #include "newmailnotifierattribute.h" #include using namespace Akonadi; NewMailNotifierAttributeTest::NewMailNotifierAttributeTest(QObject *parent) : QObject(parent) { } NewMailNotifierAttributeTest::~NewMailNotifierAttributeTest() { } void NewMailNotifierAttributeTest::shouldHaveDefaultValue() { NewMailNotifierAttribute attr; QVERIFY(!attr.ignoreNewMail()); } void NewMailNotifierAttributeTest::shouldSetIgnoreNotification() { NewMailNotifierAttribute attr; bool ignore = false; attr.setIgnoreNewMail(ignore); QCOMPARE(attr.ignoreNewMail(), ignore); ignore = true; attr.setIgnoreNewMail(ignore); QCOMPARE(attr.ignoreNewMail(), ignore); } void NewMailNotifierAttributeTest::shouldSerializedData() { NewMailNotifierAttribute attr; attr.setIgnoreNewMail(true); QByteArray ba = attr.serialized(); NewMailNotifierAttribute result; result.deserialize(ba); QVERIFY(attr == result); } void NewMailNotifierAttributeTest::shouldCloneAttribute() { NewMailNotifierAttribute attr; attr.setIgnoreNewMail(true); NewMailNotifierAttribute *result = attr.clone(); QVERIFY(attr == *result); delete result; } void NewMailNotifierAttributeTest::shouldHaveType() { NewMailNotifierAttribute attr; QCOMPARE(attr.type(), QByteArray("newmailnotifierattribute")); } QTEST_MAIN(NewMailNotifierAttributeTest) diff --git a/autotests/libs/newmailnotifierattributetest.h b/autotests/libs/newmailnotifierattributetest.h index 535b20621..2de9b123c 100644 --- a/autotests/libs/newmailnotifierattributetest.h +++ b/autotests/libs/newmailnotifierattributetest.h @@ -1,37 +1,37 @@ /* - Copyright (c) 2014-2018 Montel Laurent + Copyright (c) 2014-2019 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef NEWMAILNOTIFIERATTRIBUTETEST_H #define NEWMAILNOTIFIERATTRIBUTETEST_H #include class NewMailNotifierAttributeTest : public QObject { Q_OBJECT public: explicit NewMailNotifierAttributeTest(QObject *parent = nullptr); ~NewMailNotifierAttributeTest(); private Q_SLOTS: void shouldHaveDefaultValue(); void shouldSetIgnoreNotification(); void shouldSerializedData(); void shouldCloneAttribute(); void shouldHaveType(); }; #endif // NEWMAILNOTIFIERATTRIBUTETEST_H diff --git a/autotests/libs/pop3resourceattributetest.cpp b/autotests/libs/pop3resourceattributetest.cpp index f0c7da94e..d92ccbda8 100644 --- a/autotests/libs/pop3resourceattributetest.cpp +++ b/autotests/libs/pop3resourceattributetest.cpp @@ -1,73 +1,73 @@ /* - Copyright (c) 2014-2018 Montel Laurent + Copyright (c) 2014-2019 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "pop3resourceattributetest.h" #include "pop3resourceattribute.h" #include Pop3ResourceAttributeTest::Pop3ResourceAttributeTest(QObject *parent) : QObject(parent) { } Pop3ResourceAttributeTest::~Pop3ResourceAttributeTest() { } void Pop3ResourceAttributeTest::shouldHaveDefaultValue() { Akonadi::Pop3ResourceAttribute attr; QVERIFY(attr.pop3AccountName().isEmpty()); } void Pop3ResourceAttributeTest::shouldAssignValue() { Akonadi::Pop3ResourceAttribute attr; QString accountName; attr.setPop3AccountName(accountName); QCOMPARE(attr.pop3AccountName(), accountName); accountName = QStringLiteral("foo"); attr.setPop3AccountName(accountName); QCOMPARE(attr.pop3AccountName(), accountName); accountName.clear(); attr.setPop3AccountName(accountName); QCOMPARE(attr.pop3AccountName(), accountName); } void Pop3ResourceAttributeTest::shouldDeserializeValue() { Akonadi::Pop3ResourceAttribute attr; QString accountName = QStringLiteral("foo"); attr.setPop3AccountName(accountName); const QByteArray ba = attr.serialized(); Akonadi::Pop3ResourceAttribute result; result.deserialize(ba); QVERIFY(attr == result); } void Pop3ResourceAttributeTest::shouldCloneAttribute() { Akonadi::Pop3ResourceAttribute attr; QString accountName = QStringLiteral("foo"); attr.setPop3AccountName(accountName); Akonadi::Pop3ResourceAttribute *result = attr.clone(); QVERIFY(attr == *result); delete result; } QTEST_MAIN(Pop3ResourceAttributeTest) diff --git a/autotests/libs/pop3resourceattributetest.h b/autotests/libs/pop3resourceattributetest.h index 8c04290b4..01c14c750 100644 --- a/autotests/libs/pop3resourceattributetest.h +++ b/autotests/libs/pop3resourceattributetest.h @@ -1,36 +1,36 @@ /* - Copyright (c) 2014-2018 Montel Laurent + Copyright (c) 2014-2019 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef POP3RESOURCEATTRIBUTETEST_H #define POP3RESOURCEATTRIBUTETEST_H #include class Pop3ResourceAttributeTest : public QObject { Q_OBJECT public: explicit Pop3ResourceAttributeTest(QObject *parent = nullptr); ~Pop3ResourceAttributeTest(); private Q_SLOTS: void shouldHaveDefaultValue(); void shouldAssignValue(); void shouldDeserializeValue(); void shouldCloneAttribute(); }; #endif // POP3RESOURCEATTRIBUTETEST_H diff --git a/autotests/libs/tagselectwidgettest.cpp b/autotests/libs/tagselectwidgettest.cpp index a66aeeebd..fa3e60d4b 100644 --- a/autotests/libs/tagselectwidgettest.cpp +++ b/autotests/libs/tagselectwidgettest.cpp @@ -1,40 +1,40 @@ /* - Copyright (c) 2015-2018 Montel Laurent + Copyright (c) 2015-2019 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "tagselectwidgettest.h" #include "../src/widgets/tagselectwidget.h" #include "../src/widgets/tageditwidget.h" #include TagSelectWidgetTest::TagSelectWidgetTest(QObject *parent) : QObject(parent) { } TagSelectWidgetTest::~TagSelectWidgetTest() { } void TagSelectWidgetTest::shouldHaveDefaultValue() { Akonadi::TagSelectWidget widget; Akonadi::TagEditWidget *edit = widget.findChild(QStringLiteral("tageditwidget")); QVERIFY(edit); } QTEST_MAIN(TagSelectWidgetTest) diff --git a/autotests/libs/tagselectwidgettest.h b/autotests/libs/tagselectwidgettest.h index 3370a160b..89bb54fc7 100644 --- a/autotests/libs/tagselectwidgettest.h +++ b/autotests/libs/tagselectwidgettest.h @@ -1,33 +1,33 @@ /* - Copyright (c) 2015-2018 Montel Laurent + Copyright (c) 2015-2019 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef TAGSELECTWIDGETTEST_H #define TAGSELECTWIDGETTEST_H #include class TagSelectWidgetTest : public QObject { Q_OBJECT public: explicit TagSelectWidgetTest(QObject *parent = nullptr); ~TagSelectWidgetTest(); private Q_SLOTS: void shouldHaveDefaultValue(); }; #endif // TAGSELECTWIDGETTEST_H diff --git a/src/agentbase/resourcesettings.cpp b/src/agentbase/resourcesettings.cpp index d942e97f1..8b9ce6870 100644 --- a/src/agentbase/resourcesettings.cpp +++ b/src/agentbase/resourcesettings.cpp @@ -1,42 +1,42 @@ /* - Copyright (C) 2010-2018 Laurent Montel + Copyright (C) 2010-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "resourcesettings.h" using namespace Akonadi; ResourceSettings *ResourceSettings::mSelf = nullptr; ResourceSettings *ResourceSettings::self() { if (!mSelf) { mSelf = new ResourceSettings(); mSelf->load(); } return mSelf; } ResourceSettings::ResourceSettings() { } ResourceSettings::~ResourceSettings() { } diff --git a/src/agentbase/resourcesettings.h b/src/agentbase/resourcesettings.h index 8c9b30276..9c81545ba 100644 --- a/src/agentbase/resourcesettings.h +++ b/src/agentbase/resourcesettings.h @@ -1,43 +1,43 @@ /* - Copyright (C) 2010-2018 Laurent Montel + Copyright (C) 2010-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef RESOURCESETTINGS_H #define RESOURCESETTINGS_H #include "akonadiagentbase_export.h" #include "resourcebasesettings.h" namespace Akonadi { class AKONADIAGENTBASE_EXPORT ResourceSettings : public Akonadi::ResourceBaseSettings //krazy:exclude=dpointer { Q_OBJECT public: static ResourceSettings *self(); private: ResourceSettings(); ~ResourceSettings() override; static ResourceSettings *mSelf; }; } #endif /* RESOURCESETTINGS_H */ diff --git a/src/core/models/recursivecollectionfilterproxymodel.cpp b/src/core/models/recursivecollectionfilterproxymodel.cpp index 4302dc96e..0273e0ad6 100644 --- a/src/core/models/recursivecollectionfilterproxymodel.cpp +++ b/src/core/models/recursivecollectionfilterproxymodel.cpp @@ -1,149 +1,149 @@ /* Copyright (c) 2009 Stephen Kelly - Copyright (C) 2012-2018 Laurent Montel + Copyright (C) 2012-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "recursivecollectionfilterproxymodel.h" #include "entitytreemodel.h" #include "mimetypechecker.h" #include using namespace Akonadi; namespace Akonadi { class RecursiveCollectionFilterProxyModelPrivate { Q_DECLARE_PUBLIC(RecursiveCollectionFilterProxyModel) RecursiveCollectionFilterProxyModel *q_ptr; public: RecursiveCollectionFilterProxyModelPrivate(RecursiveCollectionFilterProxyModel *model) : q_ptr(model) { } QSet includedMimeTypes; Akonadi::MimeTypeChecker checker; QString pattern; bool checkOnlyChecked = false; }; } RecursiveCollectionFilterProxyModel::RecursiveCollectionFilterProxyModel(QObject *parent) : KRecursiveFilterProxyModel(parent) , d_ptr(new RecursiveCollectionFilterProxyModelPrivate(this)) { } RecursiveCollectionFilterProxyModel::~RecursiveCollectionFilterProxyModel() { delete d_ptr; } bool RecursiveCollectionFilterProxyModel::acceptRow(int sourceRow, const QModelIndex &sourceParent) const { Q_D(const RecursiveCollectionFilterProxyModel); const QModelIndex rowIndex = sourceModel()->index(sourceRow, 0, sourceParent); const Akonadi::Collection collection = rowIndex.data(Akonadi::EntityTreeModel::CollectionRole).value(); if (!collection.isValid()) { return false; } const bool checked = (rowIndex.data(Qt::CheckStateRole).toInt() == Qt::Checked); const bool isCheckable = sourceModel()->flags(rowIndex) & Qt::ItemIsUserCheckable; if (isCheckable && (d->checkOnlyChecked && !checked)) { return false; } const bool collectionWanted = d->checker.isWantedCollection(collection); if (collectionWanted) { if (!d->pattern.isEmpty()) { const QString text = rowIndex.data(Qt::DisplayRole).toString(); return text.contains(d->pattern, Qt::CaseInsensitive); } } return collectionWanted; } void RecursiveCollectionFilterProxyModel::addContentMimeTypeInclusionFilter(const QString &mimeType) { Q_D(RecursiveCollectionFilterProxyModel); d->includedMimeTypes << mimeType; d->checker.setWantedMimeTypes(d->includedMimeTypes.toList()); invalidateFilter(); } void RecursiveCollectionFilterProxyModel::addContentMimeTypeInclusionFilters(const QStringList &mimeTypes) { Q_D(RecursiveCollectionFilterProxyModel); d->includedMimeTypes.unite(mimeTypes.toSet()); d->checker.setWantedMimeTypes(d->includedMimeTypes.toList()); invalidateFilter(); } void RecursiveCollectionFilterProxyModel::clearFilters() { Q_D(RecursiveCollectionFilterProxyModel); d->includedMimeTypes.clear(); d->checker.setWantedMimeTypes(QStringList()); invalidateFilter(); } void RecursiveCollectionFilterProxyModel::setContentMimeTypeInclusionFilters(const QStringList &mimeTypes) { Q_D(RecursiveCollectionFilterProxyModel); d->includedMimeTypes = mimeTypes.toSet(); d->checker.setWantedMimeTypes(d->includedMimeTypes.toList()); invalidateFilter(); } QStringList RecursiveCollectionFilterProxyModel::contentMimeTypeInclusionFilters() const { Q_D(const RecursiveCollectionFilterProxyModel); return d->includedMimeTypes.toList(); } int Akonadi::RecursiveCollectionFilterProxyModel::columnCount(const QModelIndex &index) const { // Optimization: we know that we're not changing the number of columns, so skip QSortFilterProxyModel return sourceModel()->columnCount(mapToSource(index)); } void Akonadi::RecursiveCollectionFilterProxyModel::setSearchPattern(const QString &pattern) { Q_D(RecursiveCollectionFilterProxyModel); if (d->pattern != pattern) { d->pattern = pattern; invalidate(); } } void Akonadi::RecursiveCollectionFilterProxyModel::setIncludeCheckedOnly(bool checked) { Q_D(RecursiveCollectionFilterProxyModel); if (d->checkOnlyChecked != checked) { d->checkOnlyChecked = checked; invalidate(); } } diff --git a/src/core/models/recursivecollectionfilterproxymodel.h b/src/core/models/recursivecollectionfilterproxymodel.h index 323660e95..7f85855ad 100644 --- a/src/core/models/recursivecollectionfilterproxymodel.h +++ b/src/core/models/recursivecollectionfilterproxymodel.h @@ -1,112 +1,112 @@ /* Copyright (c) 2009 Stephen Kelly - Copyright (C) 2012-2018 Laurent Montel + Copyright (C) 2012-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_RECURSIVECOLLECTIONFILTERPROXYMODEL_H #define AKONADI_RECURSIVECOLLECTIONFILTERPROXYMODEL_H #include #include "akonadicore_export.h" namespace Akonadi { class RecursiveCollectionFilterProxyModelPrivate; /** * @short A model to filter out collections of non-matching content types. * * @author Stephen Kelly * @since 4.6 */ class AKONADICORE_EXPORT RecursiveCollectionFilterProxyModel : public KRecursiveFilterProxyModel { Q_OBJECT public: /** * Creates a new recursive collection filter proxy model. * * @param parent The parent object. */ explicit RecursiveCollectionFilterProxyModel(QObject *parent = nullptr); /** * Destroys the recursive collection filter proxy model. */ ~RecursiveCollectionFilterProxyModel() override; /** * Add content mime type to be shown by the filter. * * @param mimeType A mime type to be shown. */ void addContentMimeTypeInclusionFilter(const QString &mimeType); /** * Add content mime types to be shown by the filter. * * @param mimeTypes A list of content mime types to be included. */ void addContentMimeTypeInclusionFilters(const QStringList &mimeTypes); /** * Clears the current filters. */ void clearFilters(); /** * Replace the content mime types to be shown by the filter. * * @param mimeTypes A list of content mime types to be included. */ void setContentMimeTypeInclusionFilters(const QStringList &mimeTypes); /** * Returns the currently included mimetypes in the filter. */ Q_REQUIRED_RESULT QStringList contentMimeTypeInclusionFilters() const; /** * Add search pattern * @param pattern the search pattern to add * @since 4.8.1 */ void setSearchPattern(const QString &pattern); /** * Show only checked item * @param checked only shows checked item if set as @c true * @since 4.9 */ void setIncludeCheckedOnly(bool checked); protected: bool acceptRow(int sourceRow, const QModelIndex &sourceParent) const override; int columnCount(const QModelIndex &index) const override; protected: RecursiveCollectionFilterProxyModelPrivate *const d_ptr; Q_DECLARE_PRIVATE(RecursiveCollectionFilterProxyModel) }; } #endif diff --git a/src/core/newmailnotifierattribute.cpp b/src/core/newmailnotifierattribute.cpp index a620292aa..d9c884e24 100644 --- a/src/core/newmailnotifierattribute.cpp +++ b/src/core/newmailnotifierattribute.cpp @@ -1,90 +1,90 @@ /* - Copyright (c) 2013-2018 Montel Laurent + Copyright (c) 2013-2019 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "newmailnotifierattribute.h" #include #include #include namespace Akonadi { class NewMailNotifierAttributePrivate { public: NewMailNotifierAttributePrivate() : ignoreNewMail(false) { } bool ignoreNewMail; }; NewMailNotifierAttribute::NewMailNotifierAttribute() : d(new NewMailNotifierAttributePrivate) { } NewMailNotifierAttribute::~NewMailNotifierAttribute() { delete d; } NewMailNotifierAttribute *NewMailNotifierAttribute::clone() const { NewMailNotifierAttribute *attr = new NewMailNotifierAttribute(); attr->setIgnoreNewMail(ignoreNewMail()); return attr; } QByteArray NewMailNotifierAttribute::type() const { static const QByteArray sType("newmailnotifierattribute"); return sType; } QByteArray NewMailNotifierAttribute::serialized() const { QByteArray result; QDataStream s(&result, QIODevice::WriteOnly); s << ignoreNewMail(); return result; } void NewMailNotifierAttribute::deserialize(const QByteArray &data) { QDataStream s(data); s >> d->ignoreNewMail; } bool NewMailNotifierAttribute::ignoreNewMail() const { return d->ignoreNewMail; } void NewMailNotifierAttribute::setIgnoreNewMail(bool b) { d->ignoreNewMail = b; } bool NewMailNotifierAttribute::operator==(const NewMailNotifierAttribute &other) const { return d->ignoreNewMail == other.ignoreNewMail(); } } diff --git a/src/core/newmailnotifierattribute.h b/src/core/newmailnotifierattribute.h index b7ed57ac7..f27807d91 100644 --- a/src/core/newmailnotifierattribute.h +++ b/src/core/newmailnotifierattribute.h @@ -1,52 +1,52 @@ /* - Copyright (c) 2013-2018 Montel Laurent + Copyright (c) 2013-2019 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef NEWMAILNOTIFIERATTRIBUTE_H #define NEWMAILNOTIFIERATTRIBUTE_H #include "akonadicore_export.h" #include namespace Akonadi { class NewMailNotifierAttributePrivate; class AKONADICORE_EXPORT NewMailNotifierAttribute : public Akonadi::Attribute { public: NewMailNotifierAttribute(); ~NewMailNotifierAttribute() override; /* reimpl */ NewMailNotifierAttribute *clone() const override; QByteArray type() const override; QByteArray serialized() const override; void deserialize(const QByteArray &data) override; bool ignoreNewMail() const; void setIgnoreNewMail(bool b); bool operator==(const NewMailNotifierAttribute &other) const; private: friend class NewMailNotifierAttributePrivate; NewMailNotifierAttributePrivate *const d; }; } #endif // NEWMAILNOTIFIERATTRIBUTE_H diff --git a/src/core/pop3resourceattribute.cpp b/src/core/pop3resourceattribute.cpp index b0c59c3ab..8e46d1037 100644 --- a/src/core/pop3resourceattribute.cpp +++ b/src/core/pop3resourceattribute.cpp @@ -1,90 +1,90 @@ /* - Copyright (c) 2013-2018 Montel Laurent + Copyright (c) 2013-2019 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "pop3resourceattribute.h" #include #include #include namespace Akonadi { class Pop3ResourceAttributePrivate { public: Pop3ResourceAttributePrivate() { } QString accountName; }; Pop3ResourceAttribute::Pop3ResourceAttribute() : d(new Pop3ResourceAttributePrivate) { } Pop3ResourceAttribute::~Pop3ResourceAttribute() { delete d; } Pop3ResourceAttribute *Pop3ResourceAttribute::clone() const { Pop3ResourceAttribute *attr = new Pop3ResourceAttribute(); attr->setPop3AccountName(pop3AccountName()); return attr; } QByteArray Pop3ResourceAttribute::type() const { static const QByteArray sType("pop3resourceattribute"); return sType; } QByteArray Pop3ResourceAttribute::serialized() const { QByteArray result; QDataStream s(&result, QIODevice::WriteOnly); s << pop3AccountName(); return result; } void Pop3ResourceAttribute::deserialize(const QByteArray &data) { QDataStream s(data); QString value; s >> value; d->accountName = value; } QString Pop3ResourceAttribute::pop3AccountName() const { return d->accountName; } void Pop3ResourceAttribute::setPop3AccountName(const QString &accountName) { d->accountName = accountName; } bool Pop3ResourceAttribute::operator==(const Pop3ResourceAttribute &other) const { return d->accountName == other.pop3AccountName(); } } diff --git a/src/core/pop3resourceattribute.h b/src/core/pop3resourceattribute.h index 467a78596..d67cfac94 100644 --- a/src/core/pop3resourceattribute.h +++ b/src/core/pop3resourceattribute.h @@ -1,51 +1,51 @@ /* - Copyright (c) 2013-2018 Montel Laurent + Copyright (c) 2013-2019 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADICORE_POP3RESOURCEATTRIBUTE_H #define AKONADICORE_POP3RESOURCEATTRIBUTE_H #include #include "akonadicore_export.h" namespace Akonadi { class Pop3ResourceAttributePrivate; class AKONADICORE_EXPORT Pop3ResourceAttribute : public Akonadi::Attribute { public: Pop3ResourceAttribute(); ~Pop3ResourceAttribute() override; /* reimpl */ Pop3ResourceAttribute *clone() const override; QByteArray type() const override; QByteArray serialized() const override; void deserialize(const QByteArray &data) override; QString pop3AccountName() const; void setPop3AccountName(const QString &accountName); bool operator==(const Pop3ResourceAttribute &other) const; private: friend class Pop3ResourceAttributePrivate; Pop3ResourceAttributePrivate *const d; }; } #endif // AKONADICORE_POP3RESOURCEATTRIBUTE_H diff --git a/src/shared/vectorhelper.h b/src/shared/vectorhelper.h index 04e75d902..11c3fdb19 100644 --- a/src/shared/vectorhelper.h +++ b/src/shared/vectorhelper.h @@ -1,65 +1,65 @@ /* - Copyright (C) 2015-2018 Laurent Montel + Copyright (C) 2015-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef VECTORHELPER_H #define VECTORHELPER_H #include #include #include namespace Akonadi { template class Container> QVector valuesToVector(const Container &container) { QVector values; values.reserve(container.size()); for (const auto &value : container) { values.append(value); } return values; } template QSet vectorToSet(const QVector &container) { QSet set; set.reserve(container.size()); for (const auto &value : container) { set.insert(value); } return set; } template class Container> QVector setToVector(const Container &container) { QVector values; values.reserve(container.size()); for (const auto &value : container) { values.append(value); } return values; } } // namespace Akonadi #endif // VECTORHELPER_H diff --git a/src/widgets/agentinstancewidget.h b/src/widgets/agentinstancewidget.h index e430be41b..4d4495b83 100644 --- a/src/widgets/agentinstancewidget.h +++ b/src/widgets/agentinstancewidget.h @@ -1,144 +1,144 @@ /* Copyright (c) 2006-2008 Tobias Koenig - Copyright (C) 2012-2018 Laurent Montel + Copyright (C) 2012-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_AGENTINSTANCEWIDGET_H #define AKONADI_AGENTINSTANCEWIDGET_H #include "akonadiwidgets_export.h" #include class QAbstractItemView; namespace Akonadi { class AgentInstance; class AgentFilterProxyModel; /** * @short Provides a widget that lists all available agent instances. * * The widget is listening on the dbus for changes, so the * widget is updated automatically as soon as new agent instances * are added to or removed from the system. * * @code * * MyWidget::MyWidget( QWidget *parent ) * : QWidget( parent ) * { * QVBoxLayout *layout = new QVBoxLayout( this ); * * mAgentInstanceWidget = new Akonadi::AgentInstanceWidget( this ); * layout->addWidget( mAgentInstanceWidget ); * * connect( mAgentInstanceWidget, SIGNAL(doubleClicked(Akonadi::AgentInstance)), * this, SLOT(slotInstanceSelected(Akonadi::AgentInstance)) ); * } * * ... * * MyWidget::slotInstanceSelected( Akonadi::AgentInstance &instance ) * { * qCDebug(AKONADIWIDGETS_LOG) << "Selected instance" << instance.name(); * } * * @endcode * * @author Tobias Koenig */ class AKONADIWIDGETS_EXPORT AgentInstanceWidget : public QWidget { Q_OBJECT public: /** * Creates a new agent instance widget. * * @param parent The parent widget. */ explicit AgentInstanceWidget(QWidget *parent = nullptr); /** * Destroys the agent instance widget. */ ~AgentInstanceWidget(); /** * Returns the current agent instance or an invalid agent instance * if no agent instance is selected. */ Q_REQUIRED_RESULT AgentInstance currentAgentInstance() const; /** * Returns the selected agent instances. * @since 4.5 */ Q_REQUIRED_RESULT QVector selectedAgentInstances() const; /** * Returns the agent filter proxy model, use this to filter by * agent mimetype or capabilities. */ Q_REQUIRED_RESULT AgentFilterProxyModel *agentFilterProxyModel() const; /** * Returns the view used in the widget. * @since 4.5 */ Q_REQUIRED_RESULT QAbstractItemView *view() const; Q_SIGNALS: /** * This signal is emitted whenever the current agent instance changes. * * @param current The current agent instance. * @param previous The previous agent instance. */ void currentChanged(const Akonadi::AgentInstance ¤t, const Akonadi::AgentInstance &previous); /** * This signal is emitted whenever there is a double click on an agent instance. * * @param current The current agent instance. */ void doubleClicked(const Akonadi::AgentInstance ¤t); /** * This signal is emitted whenever there is a click on an agent instance. * * @param current The current agent instance. * @since 4.9.1 */ void clicked(const Akonadi::AgentInstance ¤t); private: //@cond PRIVATE class Private; Private *const d; Q_PRIVATE_SLOT(d, void currentAgentInstanceChanged(const QModelIndex &, const QModelIndex &)) Q_PRIVATE_SLOT(d, void currentAgentInstanceClicked(const QModelIndex ¤tIndex)) //@endcond }; } #endif diff --git a/src/widgets/collectiondialog.cpp b/src/widgets/collectiondialog.cpp index 4b4cb051e..9cb43235e 100644 --- a/src/widgets/collectiondialog.cpp +++ b/src/widgets/collectiondialog.cpp @@ -1,421 +1,421 @@ /* Copyright 2008 Ingo Klöcker - Copyright 2010-2018 Laurent Montel + Copyright 2010-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "collectiondialog.h" #include "asyncselectionhandler_p.h" #include "monitor.h" #include "collectionfetchscope.h" #include "collectionfilterproxymodel.h" #include "entityrightsfiltermodel.h" #include "entitytreemodel.h" #include "entitytreeview.h" #include "session.h" #include "collectioncreatejob.h" #include "collectionutils.h" #include #include #include #include #include #include #include #include #include #include #include #include using namespace Akonadi; class Q_DECL_HIDDEN CollectionDialog::Private { public: Private(QAbstractItemModel *customModel, CollectionDialog *parent, CollectionDialogOptions options) : mParent(parent) { // setup GUI QVBoxLayout *layout = new QVBoxLayout(mParent); mTextLabel = new QLabel(mParent); layout->addWidget(mTextLabel); mTextLabel->hide(); QLineEdit *filterCollectionLineEdit = new QLineEdit(mParent); filterCollectionLineEdit->setClearButtonEnabled(true); filterCollectionLineEdit->setPlaceholderText(i18nc("@info Displayed grayed-out inside the " "textbox, verb to search", "Search")); layout->addWidget(filterCollectionLineEdit); mView = new EntityTreeView(mParent); mView->setDragDropMode(QAbstractItemView::NoDragDrop); mView->header()->hide(); layout->addWidget(mView); mUseByDefault = new QCheckBox(i18n("Use folder by default"), mParent); mUseByDefault->hide(); layout->addWidget(mUseByDefault); mButtonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, mParent); mParent->connect(mButtonBox, &QDialogButtonBox::accepted, mParent, &QDialog::accept); mParent->connect(mButtonBox, &QDialogButtonBox::rejected, mParent, &QDialog::reject); layout->addWidget(mButtonBox); mButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false); // setup models QAbstractItemModel *baseModel = nullptr; if (customModel) { baseModel = customModel; } else { mMonitor = new Akonadi::Monitor(mParent); mMonitor->setObjectName(QStringLiteral("CollectionDialogMonitor")); mMonitor->fetchCollection(true); mMonitor->setCollectionMonitored(Akonadi::Collection::root()); EntityTreeModel *model = new EntityTreeModel(mMonitor, mParent); model->setItemPopulationStrategy(EntityTreeModel::NoItemPopulation); model->setListFilter(CollectionFetchScope::Display); baseModel = model; } mMimeTypeFilterModel = new CollectionFilterProxyModel(mParent); mMimeTypeFilterModel->setSourceModel(baseModel); mMimeTypeFilterModel->setExcludeVirtualCollections(true); mRightsFilterModel = new EntityRightsFilterModel(mParent); mRightsFilterModel->setSourceModel(mMimeTypeFilterModel); mFilterCollection = new QSortFilterProxyModel(mParent); mFilterCollection->setRecursiveFilteringEnabled(true); mFilterCollection->setSourceModel(mRightsFilterModel); mFilterCollection->setFilterCaseSensitivity(Qt::CaseInsensitive); mView->setModel(mFilterCollection); changeCollectionDialogOptions(options); mParent->connect(filterCollectionLineEdit, &QLineEdit::textChanged, mParent, [this](const QString &str) { slotFilterFixedString(str); }); mParent->connect(mView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), mParent, SLOT(slotSelectionChanged())); mParent->connect(mView, SIGNAL(doubleClicked(QModelIndex)), mParent, SLOT(slotDoubleClicked())); mSelectionHandler = new AsyncSelectionHandler(mFilterCollection, mParent); mParent->connect(mSelectionHandler, &AsyncSelectionHandler::collectionAvailable, mParent, [this](const QModelIndex &index) {slotCollectionAvailable(index);}); readConfig(); } ~Private() { writeConfig(); } void slotCollectionAvailable(const QModelIndex &index) { mView->expandAll(); mView->setCurrentIndex(index); } void slotFilterFixedString(const QString &filter) { mFilterCollection->setFilterFixedString(filter); if (mKeepTreeExpanded) { mView->expandAll(); } } void readConfig() { KConfig config(QStringLiteral("akonadi_contactrc")); KConfigGroup group(&config, QStringLiteral("CollectionDialog")); const QSize size = group.readEntry("Size", QSize(800, 500)); if (size.isValid()) { mParent->resize(size); } } void writeConfig() { KConfig config(QStringLiteral("akonadi_contactrc")); KConfigGroup group(&config, QStringLiteral("CollectionDialog")); group.writeEntry("Size", mParent->size()); group.sync(); } CollectionDialog *mParent = nullptr; Monitor *mMonitor = nullptr; CollectionFilterProxyModel *mMimeTypeFilterModel = nullptr; EntityRightsFilterModel *mRightsFilterModel = nullptr; EntityTreeView *mView = nullptr; AsyncSelectionHandler *mSelectionHandler = nullptr; QLabel *mTextLabel = nullptr; QSortFilterProxyModel *mFilterCollection = nullptr; QCheckBox *mUseByDefault = nullptr; QStringList mContentMimeTypes; QDialogButtonBox *mButtonBox = nullptr; QPushButton *mNewSubfolderButton = nullptr; bool mAllowToCreateNewChildCollection = false; bool mKeepTreeExpanded = false; void slotDoubleClicked(); void slotSelectionChanged(); void slotAddChildCollection(); void slotCollectionCreationResult(KJob *job); bool canCreateCollection(const Akonadi::Collection &parentCollection) const; void changeCollectionDialogOptions(CollectionDialogOptions options); bool canSelectCollection() const; }; void CollectionDialog::Private::slotDoubleClicked() { if (canSelectCollection()) { mParent->accept(); } } bool CollectionDialog::Private::canSelectCollection() const { bool result = (!mView->selectionModel()->selectedIndexes().isEmpty()); if (mAllowToCreateNewChildCollection) { const Akonadi::Collection parentCollection = mParent->selectedCollection(); if (parentCollection.isValid()) { result = (parentCollection.rights() & Akonadi::Collection::CanCreateItem); } } return result; } void CollectionDialog::Private::slotSelectionChanged() { mButtonBox->button(QDialogButtonBox::Ok)->setEnabled(!mView->selectionModel()->selectedIndexes().isEmpty()); if (mAllowToCreateNewChildCollection) { const Akonadi::Collection parentCollection = mParent->selectedCollection(); const bool canCreateChildCollections = canCreateCollection(parentCollection); mNewSubfolderButton->setEnabled(canCreateChildCollections && !parentCollection.isVirtual()); if (parentCollection.isValid()) { const bool canCreateItems = (parentCollection.rights() & Akonadi::Collection::CanCreateItem); mButtonBox->button(QDialogButtonBox::Ok)->setEnabled(canCreateItems); } } } void CollectionDialog::Private::changeCollectionDialogOptions(CollectionDialogOptions options) { mAllowToCreateNewChildCollection = (options & AllowToCreateNewChildCollection); if (mAllowToCreateNewChildCollection) { mNewSubfolderButton = mButtonBox->addButton(i18n("&New Subfolder..."), QDialogButtonBox::NoRole); mNewSubfolderButton->setIcon(QIcon::fromTheme(QStringLiteral("folder-new"))); mNewSubfolderButton->setToolTip(i18n("Create a new subfolder under the currently selected folder")); mNewSubfolderButton->setEnabled(false); connect(mNewSubfolderButton, SIGNAL(clicked(bool)), mParent, SLOT(slotAddChildCollection())); } mKeepTreeExpanded = (options & KeepTreeExpanded); if (mKeepTreeExpanded) { mParent->connect(mRightsFilterModel, &EntityRightsFilterModel::rowsInserted, mView, &EntityTreeView::expandAll, Qt::UniqueConnection); mView->expandAll(); } } bool CollectionDialog::Private::canCreateCollection(const Akonadi::Collection &parentCollection) const { if (!parentCollection.isValid()) { return false; } if ((parentCollection.rights() & Akonadi::Collection::CanCreateCollection)) { const QStringList dialogMimeTypeFilter = mParent->mimeTypeFilter(); const QStringList parentCollectionMimeTypes = parentCollection.contentMimeTypes(); for (const QString &mimetype : dialogMimeTypeFilter) { if (parentCollectionMimeTypes.contains(mimetype)) { return true; } } return true; } return false; } void CollectionDialog::Private::slotAddChildCollection() { const Akonadi::Collection parentCollection = mParent->selectedCollection(); if (canCreateCollection(parentCollection)) { const QString name = QInputDialog::getText(mParent, i18nc("@title:window", "New Folder"), i18nc("@label:textbox, name of a thing", "Name")); if (name.trimmed().isEmpty()) { return; } Akonadi::Collection collection; collection.setName(name); collection.setParentCollection(parentCollection); if (!mContentMimeTypes.isEmpty()) { collection.setContentMimeTypes(mContentMimeTypes); } Akonadi::CollectionCreateJob *job = new Akonadi::CollectionCreateJob(collection); connect(job, &Akonadi::CollectionCreateJob::result, mParent, [this](KJob *job) {slotCollectionCreationResult(job);}); } } void CollectionDialog::Private::slotCollectionCreationResult(KJob *job) { if (job->error()) { QMessageBox::critical(mParent, i18n("Folder creation failed"), i18n("Could not create folder: %1", job->errorString())); } } CollectionDialog::CollectionDialog(QWidget *parent) : QDialog(parent) , d(new Private(nullptr, this, CollectionDialog::None)) { } CollectionDialog::CollectionDialog(QAbstractItemModel *model, QWidget *parent) : QDialog(parent) , d(new Private(model, this, CollectionDialog::None)) { } CollectionDialog::CollectionDialog(CollectionDialogOptions options, QAbstractItemModel *model, QWidget *parent) : QDialog(parent) , d(new Private(model, this, options)) { } CollectionDialog::~CollectionDialog() { delete d; } Akonadi::Collection CollectionDialog::selectedCollection() const { if (selectionMode() == QAbstractItemView::SingleSelection) { const QModelIndex index = d->mView->currentIndex(); if (index.isValid()) { return index.model()->data(index, EntityTreeModel::CollectionRole).value(); } } return Collection(); } Akonadi::Collection::List CollectionDialog::selectedCollections() const { Collection::List collections; const QItemSelectionModel *selectionModel = d->mView->selectionModel(); const QModelIndexList selectedIndexes = selectionModel->selectedIndexes(); for (const QModelIndex &index : selectedIndexes) { if (index.isValid()) { const Collection collection = index.model()->data(index, EntityTreeModel::CollectionRole).value(); if (collection.isValid()) { collections.append(collection); } } } return collections; } void CollectionDialog::setMimeTypeFilter(const QStringList &mimeTypes) { if (mimeTypeFilter() == mimeTypes) { return; } d->mMimeTypeFilterModel->clearFilters(); d->mMimeTypeFilterModel->addMimeTypeFilters(mimeTypes); if (d->mMonitor) { for (const QString &mimetype : mimeTypes) { d->mMonitor->setMimeTypeMonitored(mimetype); } } } QStringList CollectionDialog::mimeTypeFilter() const { return d->mMimeTypeFilterModel->mimeTypeFilters(); } void CollectionDialog::setAccessRightsFilter(Collection::Rights rights) { if (accessRightsFilter() == rights) { return; } d->mRightsFilterModel->setAccessRights(rights); } Akonadi::Collection::Rights CollectionDialog::accessRightsFilter() const { return d->mRightsFilterModel->accessRights(); } void CollectionDialog::setDescription(const QString &text) { d->mTextLabel->setText(text); d->mTextLabel->show(); } void CollectionDialog::setDefaultCollection(const Collection &collection) { d->mSelectionHandler->waitForCollection(collection); } void CollectionDialog::setSelectionMode(QAbstractItemView::SelectionMode mode) { d->mView->setSelectionMode(mode); } QAbstractItemView::SelectionMode CollectionDialog::selectionMode() const { return d->mView->selectionMode(); } void CollectionDialog::changeCollectionDialogOptions(CollectionDialogOptions options) { d->changeCollectionDialogOptions(options); } void CollectionDialog::setUseFolderByDefault(bool b) { d->mUseByDefault->setChecked(b); d->mUseByDefault->show(); } bool CollectionDialog::useFolderByDefault() const { return d->mUseByDefault->isChecked(); } void CollectionDialog::setContentMimeTypes(const QStringList &mimetypes) { d->mContentMimeTypes = mimetypes; } #include "moc_collectiondialog.cpp" diff --git a/src/widgets/collectiondialog.h b/src/widgets/collectiondialog.h index 56e885ca9..4d336e7ad 100644 --- a/src/widgets/collectiondialog.h +++ b/src/widgets/collectiondialog.h @@ -1,222 +1,222 @@ /* Copyright 2008 Ingo Klöcker - Copyright 2010-2018 Laurent Montel + Copyright 2010-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_COLLECTIONDIALOG_H #define AKONADI_COLLECTIONDIALOG_H #include "akonadiwidgets_export.h" #include "collection.h" #include #include namespace Akonadi { /** * @short A collection selection dialog. * * Provides a dialog that lists collections that are available * on the Akonadi storage and allows the selection of one or multiple * collections. * * The list of shown collections can be filtered by mime type and access * rights. Note that mime types are not enabled by default, so * setMimeTypeFilter() must be called to enable the desired mime types. * * Example: * * @code * * using namespace Akonadi; * * // Show the user a dialog to select a writable collection of contacts * CollectionDialog dlg( this ); * dlg.setMimeTypeFilter( QStringList() << KContacts::Addressee::mimeType() ); * dlg.setAccessRightsFilter( Collection::CanCreateItem ); * dlg.setDescription( i18n( "Select an address book for saving:" ) ); * * if ( dlg.exec() ) { * const Collection collection = dlg.selectedCollection(); * ... * } * * @endcode * * @author Ingo Klöcker * @since 4.3 */ class AKONADIWIDGETS_EXPORT CollectionDialog : public QDialog { Q_OBJECT Q_DISABLE_COPY(CollectionDialog) public: /* @since 4.6 */ enum CollectionDialogOption { None = 0, AllowToCreateNewChildCollection = 1, KeepTreeExpanded = 2 }; Q_DECLARE_FLAGS(CollectionDialogOptions, CollectionDialogOption) /** * Creates a new collection dialog. * * @param parent The parent widget. */ explicit CollectionDialog(QWidget *parent = nullptr); /** * Creates a new collection dialog with a custom @p model. * * The filtering by content mime type and access rights is done * on top of the custom model. * * @param model The custom model to use. * @param parent The parent widget. * * @since 4.4 */ explicit CollectionDialog(QAbstractItemModel *model, QWidget *parent = nullptr); /** * Creates a new collection dialog with a custom @p model. * * The filtering by content mime type and access rights is done * on top of the custom model. * * @param options The collection dialog options. * @param model The custom model to use. * @param parent The parent widget. * * @since 4.6 */ explicit CollectionDialog(CollectionDialogOptions options, QAbstractItemModel *model = nullptr, QWidget *parent = nullptr); /** * Destroys the collection dialog. */ ~CollectionDialog(); /** * Sets the mime types any of which the selected collection(s) shall support. * Note that mime types are not enabled by default. * @param mimeTypes MIME type filter values */ void setMimeTypeFilter(const QStringList &mimeTypes); /** * Returns the mime types any of which the selected collection(s) shall support. */ Q_REQUIRED_RESULT QStringList mimeTypeFilter() const; /** * Sets the access @p rights that the listed collections shall match with. * @param rights access rights filter values * @since 4.4 */ void setAccessRightsFilter(Collection::Rights rights); /** * Sets the access @p rights that the listed collections shall match with. * * @since 4.4 */ Q_REQUIRED_RESULT Collection::Rights accessRightsFilter() const; /** * Sets the @p text that will be shown in the dialog. * @param text the dialog's description text * @since 4.4 */ void setDescription(const QString &text); /** * Sets the @p collection that shall be selected by default. * @param collection the dialog's pre-selected collection * @since 4.4 */ void setDefaultCollection(const Collection &collection); /** * Sets the selection mode. The initial default mode is * QAbstractItemView::SingleSelection. * @param mode the selection mode to use * @see QAbstractItemView::setSelectionMode() */ void setSelectionMode(QAbstractItemView::SelectionMode mode); /** * Returns the selection mode. * @see QAbstractItemView::selectionMode() */ Q_REQUIRED_RESULT QAbstractItemView::SelectionMode selectionMode() const; /** * Returns the selected collection if the selection mode is * QAbstractItemView::SingleSelection. If another selection mode was set, * or nothing is selected, an invalid collection is returned. */ Q_REQUIRED_RESULT Akonadi::Collection selectedCollection() const; /** * Returns the list of selected collections. */ Q_REQUIRED_RESULT Akonadi::Collection::List selectedCollections() const; /** * Change collection dialog options. * @param options the collection dialog options to change * @since 4.6 */ void changeCollectionDialogOptions(CollectionDialogOptions options); /** * @since 4.13 */ void setUseFolderByDefault(bool b); /** * @since 4.13 */ Q_REQUIRED_RESULT bool useFolderByDefault() const; /** * Allow to specify collection content mimetype when we create new one. * @since 4.14.6 */ void setContentMimeTypes(const QStringList &mimetypes); private: //@cond PRIVATE class Private; Private *const d; Q_PRIVATE_SLOT(d, void slotSelectionChanged()) Q_PRIVATE_SLOT(d, void slotAddChildCollection()) Q_PRIVATE_SLOT(d, void slotDoubleClicked()) //@endcond }; } // namespace Akonadi #endif // AKONADI_COLLECTIONDIALOG_H diff --git a/src/widgets/collectionmaintenancepage.cpp b/src/widgets/collectionmaintenancepage.cpp index 9bef1f58d..47a0a22f9 100644 --- a/src/widgets/collectionmaintenancepage.cpp +++ b/src/widgets/collectionmaintenancepage.cpp @@ -1,175 +1,175 @@ /* - Copyright (C) 2009-2018 Montel Laurent + Copyright (C) 2009-2019 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "collectionmaintenancepage.h" #include "ui_collectionmaintenancepage.h" #include "core/collectionstatistics.h" #include "monitor.h" #include "agentmanager.h" #include "akonadiwidgets_debug.h" #include "indexpolicyattribute.h" #include "cachepolicy.h" #include "servermanager.h" #include #include #include #include #include #include #include using namespace Akonadi; class CollectionMaintenancePage::Private { public: Private() {} void slotReindexCollection() { if (currentCollection.isValid()) { //Don't allow to reindex twice. ui.reindexButton->setEnabled(false); const auto service = ServerManager::agentServiceName(ServerManager::Agent, QStringLiteral("akonadi_indexing_agent")); QDBusInterface indexingAgentIface(service, QStringLiteral("/"), QStringLiteral("org.freedesktop.Akonadi.Indexer")); if (indexingAgentIface.isValid()) { indexingAgentIface.call(QStringLiteral("reindexCollection"), static_cast(currentCollection.id())); ui.indexedCountLbl->setText(i18n("Remember that indexing can take some minutes.")); } else { qCWarning(AKONADIWIDGETS_LOG) << "indexer interface not valid"; } } } void updateLabel(qint64 nbMail, qint64 nbUnreadMail, qint64 size) { ui.itemsCountLbl->setText(QString::number(qMax(0LL, nbMail))); ui.unreadItemsCountLbl->setText(QString::number(qMax(0LL, nbUnreadMail))); ui.folderSizeLbl->setText(KFormat().formatByteSize(qMax(0LL, size))); } Akonadi::Collection currentCollection; Akonadi::Monitor *monitor = nullptr; Ui::CollectionMaintenancePage ui; }; CollectionMaintenancePage::CollectionMaintenancePage(QWidget *parent) : CollectionPropertiesPage(parent) , d(new Private) { setObjectName(QStringLiteral("Akonadi::CollectionMaintenancePage")); setPageTitle(i18n("Maintenance")); } CollectionMaintenancePage::~CollectionMaintenancePage() { delete d; } void CollectionMaintenancePage::init(const Collection &col) { d->ui.setupUi(this); d->currentCollection = col; d->monitor = new Monitor(this); d->monitor->setObjectName(QStringLiteral("CollectionMaintenancePageMonitor")); d->monitor->setCollectionMonitored(col, true); d->monitor->fetchCollectionStatistics(true); connect(d->monitor, &Monitor::collectionStatisticsChanged, this, [this](Collection::Id, const CollectionStatistics &stats) { d->updateLabel(stats.count(), stats.unreadCount(), stats.size()); }); if (!col.isVirtual()) { const AgentInstance instance = Akonadi::AgentManager::self()->instance(col.resource()); d->ui.folderTypeLbl->setText(instance.type().name()); } else { d->ui.folderTypeLbl->hide(); d->ui.filesLayout->labelForField(d->ui.folderTypeLbl)->hide(); } connect(d->ui.reindexButton, &QPushButton::clicked, this, [this]() { d->slotReindexCollection(); }); // Check if the resource caches full payloads or at least has local storage // (so that the indexer can retrieve the payloads on demand) const auto resource = Akonadi::AgentManager::self()->instance(col.resource()).type(); if (!col.cachePolicy().localParts().contains(QLatin1String("RFC822")) && resource.customProperties().value(QStringLiteral("HasLocalStorage"), QString()) != QLatin1String("true")) { d->ui.indexingGroup->hide(); } } void CollectionMaintenancePage::load(const Collection &col) { init(col); if (col.isValid()) { d->updateLabel(col.statistics().count(), col.statistics().unreadCount(), col.statistics().size()); Akonadi::IndexPolicyAttribute *attr = col.attribute(); const bool indexingWasEnabled(!attr || attr->indexingEnabled()); d->ui.enableIndexingChkBox->setChecked(indexingWasEnabled); if (indexingWasEnabled) { const auto service = ServerManager::agentServiceName(ServerManager::Agent, QStringLiteral("akonadi_indexing_agent")); QDBusInterface indexingAgentIface(service, QStringLiteral("/"), QStringLiteral("org.freedesktop.Akonadi.Indexer")); if (indexingAgentIface.isValid()) { auto reply = indexingAgentIface.asyncCall(QStringLiteral("indexedItems"), (qlonglong) col.id()); auto w = new QDBusPendingCallWatcher(reply, this); connect(w, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher *w) { QDBusPendingReply reply = *w; if (reply.isError()) { d->ui.indexedCountLbl->setText(i18n("Error while retrieving indexed items count")); qCWarning(AKONADIWIDGETS_LOG) << "Failed to retrieve indexed items count:" << reply.error().message(); } else { d->ui.indexedCountLbl->setText(i18np("Indexed %1 item in this folder", "Indexed %1 items in this folder", reply.argumentAt<0>())); } w->deleteLater(); }); d->ui.indexedCountLbl->setText(i18n("Calculating indexed items...")); } else { qCDebug(AKONADIWIDGETS_LOG) << "Failed to obtain Indexer interface"; d->ui.indexedCountLbl->hide(); } } else { d->ui.indexedCountLbl->hide(); } } } void CollectionMaintenancePage::save(Collection &collection) { if (!collection.hasAttribute() && d->ui.enableIndexingChkBox->isChecked()) { return; } Akonadi::IndexPolicyAttribute *attr = collection.attribute(Akonadi::Collection::AddIfMissing); attr->setIndexingEnabled(d->ui.enableIndexingChkBox->isChecked()); } diff --git a/src/widgets/collectionmaintenancepage.h b/src/widgets/collectionmaintenancepage.h index 7e1a8548c..dff219da0 100644 --- a/src/widgets/collectionmaintenancepage.h +++ b/src/widgets/collectionmaintenancepage.h @@ -1,55 +1,55 @@ /* - Copyright (C) 2009-2018 Montel Laurent + Copyright (C) 2009-2019 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_COLLECTIONMAINTENANCEPAGE_H #define AKONADI_COLLECTIONMAINTENANCEPAGE_H #include "akonadiwidgets_export.h" #include "collectionpropertiespage.h" namespace Akonadi { class AKONADIWIDGETS_EXPORT CollectionMaintenancePage : public Akonadi::CollectionPropertiesPage { Q_OBJECT public: explicit CollectionMaintenancePage(QWidget *parent = nullptr); ~CollectionMaintenancePage() override; void load(const Akonadi::Collection &col) override; void save(Akonadi::Collection &col) override; protected: void init(const Akonadi::Collection &); private: //@cond PRIVATE class Private; Private *const d; //@endcond }; AKONADI_COLLECTION_PROPERTIES_PAGE_FACTORY(CollectionMaintenancePageFactory, CollectionMaintenancePage) } #endif /* COLLECTIONMAINTENANCEPAGE_H */ diff --git a/src/widgets/collectionstatisticsdelegate.cpp b/src/widgets/collectionstatisticsdelegate.cpp index 8480b6df0..e3fceb565 100644 --- a/src/widgets/collectionstatisticsdelegate.cpp +++ b/src/widgets/collectionstatisticsdelegate.cpp @@ -1,370 +1,370 @@ /* Copyright (c) 2008 Thomas McGuire - Copyright (C) 2012-2018 Laurent Montel + Copyright (C) 2012-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "collectionstatisticsdelegate.h" #include #include #include "akonadiwidgets_debug.h" #include #include #include #include #include #include #include "entitytreemodel.h" #include "collectionstatistics.h" #include "collection.h" #include "progressspinnerdelegate_p.h" using namespace Akonadi; namespace Akonadi { enum CountType { UnreadCount, TotalCount }; class CollectionStatisticsDelegatePrivate { public: QAbstractItemView *parent = nullptr; bool drawUnreadAfterFolder = false; DelegateAnimator *animator = nullptr; QColor mSelectedUnreadColor; QColor mDeselectedUnreadColor; CollectionStatisticsDelegatePrivate(QAbstractItemView *treeView) : parent(treeView) { updateColor(); } void getCountRecursive(const QModelIndex &index, qint64 &totalCount, qint64 &unreadCount, qint64 &totalSize) const { Collection collection = qvariant_cast(index.data(EntityTreeModel::CollectionRole)); // Do not assert on invalid collections, since a collection may be deleted // in the meantime and deleted collections are invalid. if (collection.isValid()) { CollectionStatistics statistics = collection.statistics(); totalCount += qMax(0LL, statistics.count()); unreadCount += qMax(0LL, statistics.unreadCount()); totalSize += qMax(0LL, statistics.size()); if (index.model()->hasChildren(index)) { const int rowCount = index.model()->rowCount(index); for (int row = 0; row < rowCount; row++) { static const int column = 0; getCountRecursive(index.model()->index(row, column, index), totalCount, unreadCount, totalSize); } } } } void updateColor() { mSelectedUnreadColor = KColorScheme(QPalette::Active, KColorScheme::Selection) .foreground(KColorScheme::LinkText).color(); mDeselectedUnreadColor = KColorScheme(QPalette::Active, KColorScheme::View) .foreground(KColorScheme::LinkText).color(); } }; } CollectionStatisticsDelegate::CollectionStatisticsDelegate(QAbstractItemView *parent) : QStyledItemDelegate(parent) , d_ptr(new CollectionStatisticsDelegatePrivate(parent)) { } CollectionStatisticsDelegate::CollectionStatisticsDelegate(QTreeView *parent) : QStyledItemDelegate(parent) , d_ptr(new CollectionStatisticsDelegatePrivate(parent)) { } CollectionStatisticsDelegate::~CollectionStatisticsDelegate() { delete d_ptr; } void CollectionStatisticsDelegate::setUnreadCountShown(bool enable) { Q_D(CollectionStatisticsDelegate); d->drawUnreadAfterFolder = enable; } bool CollectionStatisticsDelegate::unreadCountShown() const { Q_D(const CollectionStatisticsDelegate); return d->drawUnreadAfterFolder; } void CollectionStatisticsDelegate::setProgressAnimationEnabled(bool enable) { Q_D(CollectionStatisticsDelegate); if (enable == (d->animator != nullptr)) { return; } if (enable) { Q_ASSERT(!d->animator); Akonadi::DelegateAnimator *animator = new Akonadi::DelegateAnimator(d->parent); d->animator = animator; } else { delete d->animator; d->animator = nullptr; } } bool CollectionStatisticsDelegate::progressAnimationEnabled() const { Q_D(const CollectionStatisticsDelegate); return (d->animator != nullptr); } void CollectionStatisticsDelegate::initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const { Q_D(const CollectionStatisticsDelegate); QStyleOptionViewItem *noTextOption = qstyleoption_cast(option); QStyledItemDelegate::initStyleOption(noTextOption, index); if (option->decorationPosition != QStyleOptionViewItem::Top) { if (noTextOption) { noTextOption->text.clear(); } } if (d->animator) { const QVariant fetchState = index.data(Akonadi::EntityTreeModel::FetchStateRole); if (!fetchState.isValid() || fetchState.toInt() != Akonadi::EntityTreeModel::FetchingState) { d->animator->pop(index); return; } d->animator->push(index); if (QStyleOptionViewItem *v4 = qstyleoption_cast(option)) { v4->icon = d->animator->sequenceFrame(index); } } } class PainterStateSaver { public: PainterStateSaver(QPainter *painter) { mPainter = painter; mPainter->save(); } ~PainterStateSaver() { mPainter->restore(); } private: Q_DISABLE_COPY(PainterStateSaver) QPainter *mPainter = nullptr; }; void CollectionStatisticsDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { Q_D(const CollectionStatisticsDelegate); PainterStateSaver stateSaver(painter); const QColor textColor = index.data(Qt::ForegroundRole).value(); // First, paint the basic, but without the text. We remove the text // in initStyleOption(), which gets called by QStyledItemDelegate::paint(). QStyledItemDelegate::paint(painter, option, index); // Now, we retrieve the correct style option by calling initStyleOption from // the superclass. QStyleOptionViewItem option4 = option; QStyledItemDelegate::initStyleOption(&option4, index); QString text = option4.text; // Now calculate the rectangle for the text QStyle *s = d->parent->style(); const QWidget *widget = option4.widget; const QRect textRect = s->subElementRect(QStyle::SE_ItemViewItemText, &option4, widget); // When checking if the item is expanded, we need to check that for the first // column, as Qt only recognizes the index as expanded for the first column const QModelIndex firstColumn = index.sibling(index.row(), 0); QTreeView *treeView = qobject_cast(d->parent); bool expanded = treeView && treeView->isExpanded(firstColumn); if (index.data(EntityTreeModel::PendingCutRole).toBool()) { painter->setPen(option.palette.color(QPalette::Disabled, QPalette::Text)); } else if (option.state & QStyle::State_Selected) { painter->setPen(textColor.isValid() ? textColor : option.palette.highlightedText().color()); } else { painter->setPen(textColor.isValid() ? textColor : option.palette.text().color()); } Collection collection = firstColumn.data(EntityTreeModel::CollectionRole).value(); if (!collection.isValid()) { qCCritical(AKONADIWIDGETS_LOG) << "Invalid collection at index" << firstColumn << firstColumn.data().toString() << "sibling of" << index << "rowCount=" << index.model()->rowCount(index.parent()) << "parent=" << index.parent().data().toString(); return; } CollectionStatistics statistics = collection.statistics(); qint64 unreadCount = qMax(0LL, statistics.unreadCount()); qint64 totalRecursiveCount = 0; qint64 unreadRecursiveCount = 0; qint64 totalSize = 0; bool needRecursiveCounts = false; bool needTotalSize = false; if (d->drawUnreadAfterFolder && index.column() == 0) { needRecursiveCounts = true; } else if ((index.column() == 1 || index.column() == 2)) { needRecursiveCounts = true; } else if (index.column() == 3 && !expanded) { needTotalSize = true; } if (needRecursiveCounts || needTotalSize) { d->getCountRecursive(firstColumn, totalRecursiveCount, unreadRecursiveCount, totalSize); } // Draw the unread count after the folder name (in parenthesis) if (d->drawUnreadAfterFolder && index.column() == 0) { // Construct the string which will appear after the foldername (with the // unread count) QString unread; // qCDebug(AKONADIWIDGETS_LOG) << expanded << unreadCount << unreadRecursiveCount; if (expanded && unreadCount > 0) { unread = QStringLiteral(" (%1)").arg(unreadCount); } else if (!expanded) { if (unreadCount != unreadRecursiveCount) { unread = QStringLiteral(" (%1 + %2)").arg(unreadCount).arg(unreadRecursiveCount - unreadCount); } else if (unreadCount > 0) { unread = QStringLiteral(" (%1)").arg(unreadCount); } } PainterStateSaver stateSaver(painter); if (!unread.isEmpty()) { QFont font = painter->font(); font.setBold(true); painter->setFont(font); } const QColor unreadColor = (option.state & QStyle::State_Selected) ? d->mSelectedUnreadColor : d->mDeselectedUnreadColor; const QRect iconRect = s->subElementRect(QStyle::SE_ItemViewItemDecoration, &option4, widget); if (option.decorationPosition == QStyleOptionViewItem::Left || option.decorationPosition == QStyleOptionViewItem::Right) { // Squeeze the folder text if it is to big and calculate the rectangles // where the folder text and the unread count will be drawn to QString folderName = text; QFontMetrics fm(painter->fontMetrics()); #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) const int unreadWidth = fm.horizontalAdvance(unread); int folderWidth(fm.horizontalAdvance(folderName)); #else const int unreadWidth = fm.width(unread); int folderWidth(fm.width(folderName)); #endif const bool enoughPlaceForText = (option.rect.width() > (folderWidth + unreadWidth + iconRect.width())); if (!enoughPlaceForText && (folderWidth + unreadWidth > textRect.width())) { folderName = fm.elidedText(folderName, Qt::ElideRight, option.rect.width() - unreadWidth - iconRect.width()); #if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) folderWidth = fm.horizontalAdvance(folderName); #else folderWidth = fm.width(folderName); #endif } QRect folderRect = textRect; QRect unreadRect = textRect; folderRect.setRight(textRect.left() + folderWidth); unreadRect = QRect(folderRect.right(), folderRect.top(), unreadRect.width(), unreadRect.height()); // Draw folder name and unread count painter->drawText(folderRect, Qt::AlignLeft | Qt::AlignVCenter, folderName); painter->setPen(unreadColor); painter->drawText(unreadRect, Qt::AlignLeft | Qt::AlignVCenter, unread); } else if (option.decorationPosition == QStyleOptionViewItem::Top) { if (unreadCount > 0) { // draw over the icon // the iconRect is enlarged to the whole width of the item, in case the text is wider than the underlying icon painter->setPen(unreadColor); painter->drawText(QRect(option.rect.x(), iconRect.y(), option.rect.width(), iconRect.height()), Qt::AlignCenter, QString::number(unreadCount)); } } return; } // For the unread/total column, paint the summed up count if the item // is collapsed if ((index.column() == 1 || index.column() == 2)) { QFont savedFont = painter->font(); QString sumText; if (index.column() == 1 && ((!expanded && unreadRecursiveCount > 0) || (expanded && unreadCount > 0))) { QFont font = painter->font(); font.setBold(true); painter->setFont(font); sumText = QString::number(expanded ? unreadCount : unreadRecursiveCount); } else { qint64 totalCount = statistics.count(); if (index.column() == 2 && ((!expanded && totalRecursiveCount > 0) || (expanded && totalCount > 0))) { sumText = QString::number(expanded ? totalCount : totalRecursiveCount); } } painter->drawText(textRect, Qt::AlignRight | Qt::AlignVCenter, sumText); painter->setFont(savedFont); return; } //total size if (index.column() == 3 && !expanded) { painter->drawText(textRect, option4.displayAlignment | Qt::AlignVCenter, KFormat().formatByteSize(totalSize)); return; } painter->drawText(textRect, option4.displayAlignment | Qt::AlignVCenter, text); } void CollectionStatisticsDelegate::updatePalette() { Q_D(CollectionStatisticsDelegate); d->updateColor(); } diff --git a/src/widgets/entitytreeview.cpp b/src/widgets/entitytreeview.cpp index 6f846e4de..1ec8316d1 100644 --- a/src/widgets/entitytreeview.cpp +++ b/src/widgets/entitytreeview.cpp @@ -1,339 +1,339 @@ /* Copyright (c) 2006 - 2007 Volker Krause Copyright (c) 2008 Stephen Kelly - Copyright (C) 2012-2018 Laurent Montel + Copyright (C) 2012-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "entitytreeview.h" #include "dragdropmanager_p.h" #include #include #include #include #include #include "collection.h" #include "controlgui.h" #include "item.h" #include "entitytreemodel.h" #include #include #include "progressspinnerdelegate_p.h" using namespace Akonadi; /** * @internal */ class Q_DECL_HIDDEN EntityTreeView::Private { public: Private(EntityTreeView *parent) : mParent(parent) #ifndef QT_NO_DRAGANDDROP , mDragDropManager(new DragDropManager(mParent)) #endif , mDefaultPopupMenu(QStringLiteral("akonadi_collectionview_contextmenu")) { } void init(); void itemClicked(const QModelIndex &index); void itemDoubleClicked(const QModelIndex &index); void itemCurrentChanged(const QModelIndex &index); void slotSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); EntityTreeView *mParent = nullptr; QBasicTimer mDragExpandTimer; DragDropManager *mDragDropManager = nullptr; KXMLGUIClient *mXmlGuiClient = nullptr; QString mDefaultPopupMenu; }; void EntityTreeView::Private::init() { Akonadi::DelegateAnimator *animator = new Akonadi::DelegateAnimator(mParent); Akonadi::ProgressSpinnerDelegate *customDelegate = new Akonadi::ProgressSpinnerDelegate(animator, mParent); mParent->setItemDelegate(customDelegate); mParent->header()->setSectionsClickable(true); mParent->header()->setStretchLastSection(false); // mParent->setRootIsDecorated( false ); // QTreeView::autoExpandDelay has very strange behaviour. It toggles the collapse/expand state // of the item the cursor is currently over when a timer event fires. // The behaviour we want is to expand a collapsed row on drag-over, but not collapse it. // mDragExpandTimer is used to achieve this. // mParent->setAutoExpandDelay ( QApplication::startDragTime() ); mParent->setSortingEnabled(true); mParent->sortByColumn(0, Qt::AscendingOrder); mParent->setEditTriggers(QAbstractItemView::EditKeyPressed); mParent->setAcceptDrops(true); #ifndef QT_NO_DRAGANDDROP mParent->setDropIndicatorShown(true); mParent->setDragDropMode(DragDrop); mParent->setDragEnabled(true); #endif mParent->connect(mParent, SIGNAL(clicked(QModelIndex)), mParent, SLOT(itemClicked(QModelIndex))); mParent->connect(mParent, SIGNAL(doubleClicked(QModelIndex)), mParent, SLOT(itemDoubleClicked(QModelIndex))); ControlGui::widgetNeedsAkonadi(mParent); } void EntityTreeView::Private::slotSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected) { Q_UNUSED(deselected) const int column = 0; for (const QItemSelectionRange &range : selected) { const QModelIndex index = range.topLeft(); if (index.column() > 0) { continue; } for (int row = index.row(); row <= range.bottomRight().row(); ++row) { // Don't use canFetchMore here. We need to bypass the check in // the EntityFilterModel when it shows only collections. mParent->model()->fetchMore(index.sibling(row, column)); } } if (selected.size() == 1) { const QItemSelectionRange &range = selected.first(); if (range.topLeft().row() == range.bottomRight().row()) { mParent->scrollTo(range.topLeft(), QTreeView::EnsureVisible); } } } void EntityTreeView::Private::itemClicked(const QModelIndex &index) { if (!index.isValid()) { return; } QModelIndex idx = index.sibling(index.row(), 0); const Collection collection = idx.model()->data(idx, EntityTreeModel::CollectionRole).value(); if (collection.isValid()) { emit mParent->clicked(collection); } else { const Item item = idx.model()->data(idx, EntityTreeModel::ItemRole).value(); if (item.isValid()) { emit mParent->clicked(item); } } } void EntityTreeView::Private::itemDoubleClicked(const QModelIndex &index) { if (!index.isValid()) { return; } QModelIndex idx = index.sibling(index.row(), 0); const Collection collection = idx.model()->data(idx, EntityTreeModel::CollectionRole).value(); if (collection.isValid()) { emit mParent->doubleClicked(collection); } else { const Item item = idx.model()->data(idx, EntityTreeModel::ItemRole).value(); if (item.isValid()) { emit mParent->doubleClicked(item); } } } void EntityTreeView::Private::itemCurrentChanged(const QModelIndex &index) { if (!index.isValid()) { return; } QModelIndex idx = index.sibling(index.row(), 0); const Collection collection = idx.model()->data(idx, EntityTreeModel::CollectionRole).value(); if (collection.isValid()) { emit mParent->currentChanged(collection); } else { const Item item = idx.model()->data(idx, EntityTreeModel::ItemRole).value(); if (item.isValid()) { emit mParent->currentChanged(item); } } } EntityTreeView::EntityTreeView(QWidget *parent) : QTreeView(parent) , d(new Private(this)) { setSelectionMode(QAbstractItemView::SingleSelection); d->init(); } EntityTreeView::EntityTreeView(KXMLGUIClient *xmlGuiClient, QWidget *parent) : QTreeView(parent) , d(new Private(this)) { d->mXmlGuiClient = xmlGuiClient; d->init(); } EntityTreeView::~EntityTreeView() { delete d->mDragDropManager; delete d; } void EntityTreeView::setModel(QAbstractItemModel *model) { if (selectionModel()) { disconnect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(itemCurrentChanged(QModelIndex))); disconnect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(slotSelectionChanged(QItemSelection,QItemSelection))); } QTreeView::setModel(model); header()->setStretchLastSection(true); connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(itemCurrentChanged(QModelIndex))); connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(slotSelectionChanged(QItemSelection,QItemSelection))); } void EntityTreeView::timerEvent(QTimerEvent *event) { if (event->timerId() == d->mDragExpandTimer.timerId()) { const QPoint pos = viewport()->mapFromGlobal(QCursor::pos()); if (state() == QAbstractItemView::DraggingState && viewport()->rect().contains(pos)) { setExpanded(indexAt(pos), true); } } QTreeView::timerEvent(event); } #ifndef QT_NO_DRAGANDDROP void EntityTreeView::dragMoveEvent(QDragMoveEvent *event) { d->mDragExpandTimer.start(QApplication::startDragTime(), this); if (d->mDragDropManager->dropAllowed(event)) { // All urls are supported. process the event. QTreeView::dragMoveEvent(event); return; } event->setDropAction(Qt::IgnoreAction); } void EntityTreeView::dropEvent(QDropEvent *event) { d->mDragExpandTimer.stop(); bool menuCanceled = false; if (d->mDragDropManager->processDropEvent(event, menuCanceled, (dropIndicatorPosition() == QAbstractItemView::OnItem))) { QTreeView::dropEvent(event); } } #endif #ifndef QT_NO_CONTEXTMENU void EntityTreeView::contextMenuEvent(QContextMenuEvent *event) { if (!d->mXmlGuiClient || !model()) { return; } const QModelIndex index = indexAt(event->pos()); QString popupName = d->mDefaultPopupMenu; if (index.isValid()) { // popup not over empty space // check whether the index under the cursor is a collection or item const Item item = model()->data(index, EntityTreeModel::ItemRole).value(); popupName = (item.isValid() ? QStringLiteral("akonadi_itemview_contextmenu") : QStringLiteral("akonadi_collectionview_contextmenu")); } QMenu *popup = static_cast(d->mXmlGuiClient->factory()->container(popupName, d->mXmlGuiClient)); if (popup) { popup->exec(event->globalPos()); } } #endif void EntityTreeView::setXmlGuiClient(KXMLGUIClient *xmlGuiClient) { d->mXmlGuiClient = xmlGuiClient; } KXMLGUIClient *EntityTreeView::xmlGuiClient() const { return d->mXmlGuiClient; } #ifndef QT_NO_DRAGANDDROP void EntityTreeView::startDrag(Qt::DropActions supportedActions) { d->mDragDropManager->startDrag(supportedActions); } #endif void EntityTreeView::setDropActionMenuEnabled(bool enabled) { #ifndef QT_NO_DRAGANDDROP d->mDragDropManager->setShowDropActionMenu(enabled); #endif } bool EntityTreeView::isDropActionMenuEnabled() const { #ifndef QT_NO_DRAGANDDROP return d->mDragDropManager->showDropActionMenu(); #else return false; #endif } void EntityTreeView::setManualSortingActive(bool active) { #ifndef QT_NO_DRAGANDDROP d->mDragDropManager->setManualSortingActive(active); #endif } bool EntityTreeView::isManualSortingActive() const { #ifndef QT_NO_DRAGANDDROP return d->mDragDropManager->isManualSortingActive(); #else return false; #endif } void EntityTreeView::setDefaultPopupMenu(const QString &name) { d->mDefaultPopupMenu = name; } #include "moc_entitytreeview.cpp" diff --git a/src/widgets/entitytreeview.h b/src/widgets/entitytreeview.h index d37cd3c89..1afb944ee 100644 --- a/src/widgets/entitytreeview.h +++ b/src/widgets/entitytreeview.h @@ -1,245 +1,245 @@ /* Copyright (c) 2006 - 2007 Volker Krause Copyright (c) 2008 Stephen Kelly - Copyright (C) 2012-2018 Laurent Montel + Copyright (C) 2012-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef AKONADI_ENTITYTREEVIEW_H #define AKONADI_ENTITYTREEVIEW_H #include "akonadiwidgets_export.h" #include class KXMLGUIClient; class QDragMoveEvent; namespace Akonadi { class Collection; class Item; /** * @short A view to show an item/collection tree provided by an EntityTreeModel. * * When a KXmlGuiWindow is passed to the constructor, the XMLGUI * defined context menu @c akonadi_collectionview_contextmenu or * @c akonadi_itemview_contextmenu is used if available. * * Example: * * @code * * using namespace Akonadi; * * class MyWindow : public KXmlGuiWindow * { * public: * MyWindow() * : KXmlGuiWindow() * { * EntityTreeView *view = new EntityTreeView( this, this ); * setCentralWidget( view ); * * EntityTreeModel *model = new EntityTreeModel( ... ); * view->setModel( model ); * } * } * * @endcode * * @author Volker Krause * @author Stephen Kelly * @since 4.4 */ class AKONADIWIDGETS_EXPORT EntityTreeView : public QTreeView { Q_OBJECT public: /** * Creates a new entity tree view. * * @param parent The parent widget. */ explicit EntityTreeView(QWidget *parent = nullptr); /** * Creates a new entity tree view. * * @param xmlGuiClient The KXMLGUIClient the view is used in. * This is needed for the XMLGUI based context menu. * Passing 0 is ok and will disable the builtin context menu. * @param parent The parent widget. */ explicit EntityTreeView(KXMLGUIClient *xmlGuiClient, QWidget *parent = nullptr); /** * Destroys the entity tree view. */ ~EntityTreeView() override; /** * Sets the XML GUI client which the view is used in. * * This is needed if you want to use the built-in context menu. * * @param xmlGuiClient The KXMLGUIClient the view is used in. */ void setXmlGuiClient(KXMLGUIClient *xmlGuiClient); /** * Return the XML GUI client which the view is used in. * @since 4.12 */ KXMLGUIClient *xmlGuiClient() const; /** * @reimp * @param model the model to set */ void setModel(QAbstractItemModel *model) override; /** * Sets whether the drop action menu is @p enabled and will * be shown on drop operation. * @param enabled enables drop action menu if set as @c true * @since 4.5 */ void setDropActionMenuEnabled(bool enabled); /** * Returns whether the drop action menu is enabled and will * be shown on drop operation. * * @since 4.5 */ Q_REQUIRED_RESULT bool isDropActionMenuEnabled() const; /** * Return true if we use an manual sorting * Necessary to fix dnd menu * We must show just move when we move item between two items * When automatic no show dnd menu between two items. * @since 4.8.1 */ Q_REQUIRED_RESULT bool isManualSortingActive() const; /** * Set true if we automatic sorting * @param active enables automatic sorting if set as @c true * @since 4.8.1 */ void setManualSortingActive(bool active); /** * Set the name of the default popup menu (retrieved from the * application's XMLGUI file). * * This menu is used as a fallback if the context of the menu request * is neither an item nor a collection, e.g. the click is on an empty * area inside the view. If the click is over an entry in the view, * the menu which is applicable to the clicked entry (either an Item * or a Collection) is used. * * @param name The name of the popup menu * * @since 4.9 * @note For backwards compatibility, the default is the standard * collection popup menu, "akonadi_collectionview_contextmenu". * @see KXMLGUIClient, KXMLGUIFactory::container() */ void setDefaultPopupMenu(const QString &name); Q_SIGNALS: /** * This signal is emitted whenever the user has clicked * a collection in the view. * * @param collection The clicked collection. */ void clicked(const Akonadi::Collection &collection); /** * This signal is emitted whenever the user has clicked * an item in the view. * * @param item The clicked item. */ void clicked(const Akonadi::Item &item); /** * This signal is emitted whenever the user has double clicked * a collection in the view. * * @param collection The double clicked collection. */ void doubleClicked(const Akonadi::Collection &collection); /** * This signal is emitted whenever the user has double clicked * an item in the view. * * @param item The double clicked item. */ void doubleClicked(const Akonadi::Item &item); /** * This signal is emitted whenever the current collection * in the view has changed. * * @param collection The new current collection. */ void currentChanged(const Akonadi::Collection &collection); /** * This signal is emitted whenever the current item * in the view has changed. * * @param item The new current item. */ void currentChanged(const Akonadi::Item &item); protected: using QTreeView::currentChanged; #ifndef QT_NO_DRAGANDDROP void startDrag(Qt::DropActions supportedActions) override; void dragMoveEvent(QDragMoveEvent *event) override; void dropEvent(QDropEvent *event) override; #endif void timerEvent(QTimerEvent *event) override; #ifndef QT_NO_CONTEXTMENU void contextMenuEvent(QContextMenuEvent *event) override; #endif private: //@cond PRIVATE class Private; Private *const d; Q_PRIVATE_SLOT(d, void itemClicked(const QModelIndex &)) Q_PRIVATE_SLOT(d, void itemDoubleClicked(const QModelIndex &)) Q_PRIVATE_SLOT(d, void itemCurrentChanged(const QModelIndex &)) Q_PRIVATE_SLOT(d, void slotSelectionChanged(const QItemSelection &, const QItemSelection &)) //@endcond }; } #endif diff --git a/src/widgets/manageaccountwidget.cpp b/src/widgets/manageaccountwidget.cpp index 313ba1595..4f2e7296c 100644 --- a/src/widgets/manageaccountwidget.cpp +++ b/src/widgets/manageaccountwidget.cpp @@ -1,243 +1,243 @@ /* - Copyright (c) 2014-2018 Montel Laurent + Copyright (c) 2014-2019 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "manageaccountwidget.h" #include "agentinstance.h" #include "agentinstancecreatejob.h" #include "agenttypedialog.h" #include "agentfilterproxymodel.h" #include "agentmanager.h" #include "ui_manageaccountwidget.h" #include #include #include #include #include #include using namespace Akonadi; class Akonadi::ManageAccountWidgetPrivate { public: ManageAccountWidgetPrivate() { } ~ManageAccountWidgetPrivate() { delete ui; } QString mSpecialCollectionIdentifier; QStringList mMimeTypeFilter; QStringList mCapabilityFilter; QStringList mExcludeCapabilities; Ui::ManageAccountWidget *ui = nullptr; }; ManageAccountWidget::ManageAccountWidget(QWidget *parent) : QWidget(parent), d(new Akonadi::ManageAccountWidgetPrivate) { d->ui = new Ui::ManageAccountWidget; d->ui->setupUi(this); connect(d->ui->mAddAccountButton, &QPushButton::clicked, this, &ManageAccountWidget::slotAddAccount); connect(d->ui->mModifyAccountButton, &QPushButton::clicked, this, &ManageAccountWidget::slotModifySelectedAccount); connect(d->ui->mRemoveAccountButton, &QPushButton::clicked, this, &ManageAccountWidget::slotRemoveSelectedAccount); connect(d->ui->mRestartAccountButton, &QPushButton::clicked, this, &ManageAccountWidget::slotRestartSelectedAccount); connect(d->ui->mAccountList, &Akonadi::AgentInstanceWidget::clicked, this, &ManageAccountWidget::slotAccountSelected); connect(d->ui->mAccountList, &Akonadi::AgentInstanceWidget::doubleClicked, this, &ManageAccountWidget::slotModifySelectedAccount); d->ui->mAccountList->view()->setSelectionMode(QAbstractItemView::SingleSelection); d->ui->mFilterAccount->setProxy(d->ui->mAccountList->agentFilterProxyModel()); d->ui->mFilterAccount->installEventFilter(this); slotAccountSelected(d->ui->mAccountList->currentAgentInstance()); } ManageAccountWidget::~ManageAccountWidget() { delete d; } void ManageAccountWidget::disconnectAddAccountButton() { disconnect(d->ui->mAddAccountButton, &QPushButton::clicked, this, &ManageAccountWidget::slotAddAccount); } QPushButton *ManageAccountWidget::addAccountButton() const { return d->ui->mAddAccountButton; } void ManageAccountWidget::setDescriptionLabelText(const QString &text) { d->ui->label->setText(text); } bool ManageAccountWidget::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::KeyPress && obj == d->ui->mFilterAccount) { QKeyEvent *key = static_cast(event); if ((key->key() == Qt::Key_Enter) || (key->key() == Qt::Key_Return)) { event->accept(); return true; } } return QWidget::eventFilter(obj, event); } QAbstractItemView *ManageAccountWidget::view() const { return d->ui->mAccountList->view(); } void ManageAccountWidget::setSpecialCollectionIdentifier(const QString &identifier) { d->mSpecialCollectionIdentifier = identifier; } void ManageAccountWidget::slotAddAccount() { Akonadi::AgentTypeDialog dlg(this); Akonadi::AgentFilterProxyModel *filter = dlg.agentFilterProxyModel(); for (const QString &filterStr : qAsConst(d->mMimeTypeFilter)) { filter->addMimeTypeFilter(filterStr); } for (const QString &capa : qAsConst(d->mCapabilityFilter)) { filter->addCapabilityFilter(capa); } for (const QString &capa : qAsConst(d->mExcludeCapabilities)) { filter->excludeCapabilities(capa); } if (dlg.exec()) { const Akonadi::AgentType agentType = dlg.agentType(); if (agentType.isValid()) { Akonadi::AgentInstanceCreateJob *job = new Akonadi::AgentInstanceCreateJob(agentType, this); job->configure(this); job->start(); } } } QStringList ManageAccountWidget::excludeCapabilities() const { return d->mExcludeCapabilities; } void ManageAccountWidget::setExcludeCapabilities(const QStringList &excludeCapabilities) { d->mExcludeCapabilities = excludeCapabilities; for (const QString &capability : qAsConst(d->mExcludeCapabilities)) { d->ui->mAccountList->agentFilterProxyModel()->excludeCapabilities(capability); } } void ManageAccountWidget::setItemDelegate(QAbstractItemDelegate *delegate) { d->ui->mAccountList->view()->setItemDelegate(delegate); } QStringList ManageAccountWidget::capabilityFilter() const { return d->mCapabilityFilter; } void ManageAccountWidget::setCapabilityFilter(const QStringList &capabilityFilter) { d->mCapabilityFilter = capabilityFilter; for (const QString &capability : qAsConst(d->mCapabilityFilter)) { d->ui->mAccountList->agentFilterProxyModel()->addCapabilityFilter(capability); } } QStringList ManageAccountWidget::mimeTypeFilter() const { return d->mMimeTypeFilter; } void ManageAccountWidget::setMimeTypeFilter(const QStringList &mimeTypeFilter) { d->mMimeTypeFilter = mimeTypeFilter; for (const QString &mimeType : qAsConst(d->mMimeTypeFilter)) { d->ui->mAccountList->agentFilterProxyModel()->addMimeTypeFilter(mimeType); } } void ManageAccountWidget::slotModifySelectedAccount() { Akonadi::AgentInstance instance = d->ui->mAccountList->currentAgentInstance(); if (instance.isValid()) { KWindowSystem::allowExternalProcessWindowActivation(); instance.configure(this); } } void ManageAccountWidget::slotRestartSelectedAccount() { const Akonadi::AgentInstance instance = d->ui->mAccountList->currentAgentInstance(); if (instance.isValid()) { instance.restart(); } } void ManageAccountWidget::slotRemoveSelectedAccount() { const Akonadi::AgentInstance instance = d->ui->mAccountList->currentAgentInstance(); const int rc = KMessageBox::questionYesNo(this, i18n("Do you want to remove account '%1'?", instance.name()), i18n("Remove account?")); if (rc == KMessageBox::No) { return; } if (instance.isValid()) { Akonadi::AgentManager::self()->removeInstance(instance); } slotAccountSelected(d->ui->mAccountList->currentAgentInstance()); } void ManageAccountWidget::slotAccountSelected(const Akonadi::AgentInstance ¤t) { if (current.isValid()) { d->ui->mModifyAccountButton->setEnabled(!current.type().capabilities().contains(QLatin1String("NoConfig"))); d->ui->mRemoveAccountButton->setEnabled(d->mSpecialCollectionIdentifier != current.identifier()); // Restarting an agent is not possible if it's in Running status... (see AgentProcessInstance::restartWhenIdle) d->ui->mRestartAccountButton->setEnabled((current.status() != 1)); } else { d->ui->mModifyAccountButton->setEnabled(false); d->ui->mRemoveAccountButton->setEnabled(false); d->ui->mRestartAccountButton->setEnabled(false); } } diff --git a/src/widgets/manageaccountwidget.h b/src/widgets/manageaccountwidget.h index 5da499e73..d9805457f 100644 --- a/src/widgets/manageaccountwidget.h +++ b/src/widgets/manageaccountwidget.h @@ -1,85 +1,85 @@ /* - Copyright (c) 2014-2018 Montel Laurent + Copyright (c) 2014-2019 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef MANAGEACCOUNTWIDGET_H #define MANAGEACCOUNTWIDGET_H #include #include "akonadiwidgets_export.h" namespace Ui { class ManageAccountWidget; } namespace Akonadi { class AgentInstance; } class QAbstractItemDelegate; class QAbstractItemView; class QPushButton; namespace Akonadi { class ManageAccountWidgetPrivate; class AKONADIWIDGETS_EXPORT ManageAccountWidget : public QWidget { Q_OBJECT public: explicit ManageAccountWidget(QWidget *parent); ~ManageAccountWidget() override; /** * Sets the text of the label above the list of accounts. * Example: "Incoming accounts:" in an email client, or "Calendars:" in an organizer. */ void setDescriptionLabelText(const QString &text); void setSpecialCollectionIdentifier(const QString &identifier); Q_REQUIRED_RESULT QStringList mimeTypeFilter() const; void setMimeTypeFilter(const QStringList &mimeTypeFilter); Q_REQUIRED_RESULT QStringList capabilityFilter() const; void setCapabilityFilter(const QStringList &capabilityFilter); Q_REQUIRED_RESULT QStringList excludeCapabilities() const; void setExcludeCapabilities(const QStringList &excludeCapabilities); void setItemDelegate(QAbstractItemDelegate *delegate); Q_REQUIRED_RESULT QAbstractItemView *view() const; Q_REQUIRED_RESULT QPushButton *addAccountButton() const; void disconnectAddAccountButton(); protected: bool eventFilter(QObject *obj, QEvent *event) override; public Q_SLOTS: void slotAddAccount(); private Q_SLOTS: void slotAccountSelected(const Akonadi::AgentInstance ¤t); void slotRemoveSelectedAccount(); void slotRestartSelectedAccount(); void slotModifySelectedAccount(); private: ManageAccountWidgetPrivate *const d; }; } #endif // MANAGEACCOUNTWIDGET_H diff --git a/src/widgets/recentcollectionaction.cpp b/src/widgets/recentcollectionaction.cpp index 95d98f9e0..66fbd18c3 100644 --- a/src/widgets/recentcollectionaction.cpp +++ b/src/widgets/recentcollectionaction.cpp @@ -1,138 +1,138 @@ /* - * Copyright (C) 2011-2018 Laurent Montel + * Copyright (C) 2011-2019 Laurent Montel * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 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 Library General Public * License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #include "recentcollectionaction_p.h" #include "metatypes.h" #include "entitytreemodel.h" #include "collectionmodel.h" #include #include #include #include #include using namespace Akonadi; static const int s_maximumRecentCollection = 10; RecentCollectionAction::RecentCollectionAction(Akonadi::StandardActionManager::Type type, const Akonadi::Collection::List &selectedCollectionsList, const QAbstractItemModel *model, QMenu *menu) : QObject(menu) , mMenu(menu) , mModel(model) , mRecentAction(nullptr) { mAkonadiConfig = KSharedConfig::openConfig(QStringLiteral("akonadikderc")); KConfigGroup group(mAkonadiConfig, QStringLiteral("Recent Collections")); mListRecentCollection = group.readEntry("Collections", QStringList()); mRecentAction = mMenu->addAction(i18n("Recent Folder")); mMenu->addSeparator(); fillRecentCollection(type, selectedCollectionsList); } RecentCollectionAction::~RecentCollectionAction() { } bool RecentCollectionAction::clear() { delete mRecentAction->menu(); if (mListRecentCollection.isEmpty()) { mRecentAction->setEnabled(false); return true; } return false; } void RecentCollectionAction::fillRecentCollection(Akonadi::StandardActionManager::Type type, const Akonadi::Collection::List &selectedCollectionsList) { if (clear()) { return; } QMenu *popup = new QMenu; mRecentAction->setMenu(popup); const int numberOfRecentCollection(mListRecentCollection.count()); for (int i = 0; i < numberOfRecentCollection; ++i) { const QModelIndex index = Akonadi::EntityTreeModel::modelIndexForCollection(mModel, Akonadi::Collection(mListRecentCollection.at(i).toLongLong())); const Akonadi::Collection collection = mModel->data(index, Akonadi::CollectionModel::CollectionRole).value(); if (index.isValid()) { const bool collectionIsSelected = selectedCollectionsList.contains(collection); if (type == Akonadi::StandardActionManager::MoveCollectionToMenu && collectionIsSelected) { continue; } const bool canCreateNewItems = (collection.rights() &Collection::CanCreateItem); QAction *action = popup->addAction(actionName(index)); const QIcon icon = mModel->data(index, Qt::DecorationRole).value(); action->setIcon(icon); action->setData(QVariant::fromValue(index)); action->setEnabled(canCreateNewItems); } } } QString RecentCollectionAction::actionName(QModelIndex index) { QString name = index.data().toString(); name.replace(QLatin1Char('&'), QStringLiteral("&&")); index = index.parent(); QString topLevelName; while (index != QModelIndex()) { topLevelName = index.data().toString(); index = index.parent(); } if (topLevelName.isEmpty()) { return name; } else { topLevelName.replace(QLatin1Char('&'), QStringLiteral("&&")); return QStringLiteral("%1 - %2").arg(name, topLevelName); } } void RecentCollectionAction::addRecentCollection(Akonadi::StandardActionManager::Type type, Akonadi::Collection::Id id) { const QString newCollectionID = QString::number(id); if (mListRecentCollection.isEmpty() || !mListRecentCollection.contains(newCollectionID)) { if (mListRecentCollection.count() == s_maximumRecentCollection) { mListRecentCollection.removeFirst(); } mListRecentCollection.append(newCollectionID); writeConfig(); fillRecentCollection(type, Akonadi::Collection::List()); } } void RecentCollectionAction::writeConfig() { KConfigGroup group(mAkonadiConfig, QStringLiteral("Recent Collections")); group.writeEntry("Collections", mListRecentCollection); group.sync(); } void RecentCollectionAction::cleanRecentCollection() { mListRecentCollection.clear(); writeConfig(); clear(); } #include "moc_recentcollectionaction_p.cpp" diff --git a/src/widgets/recentcollectionaction_p.h b/src/widgets/recentcollectionaction_p.h index 8b12eed68..c63acdbc2 100644 --- a/src/widgets/recentcollectionaction_p.h +++ b/src/widgets/recentcollectionaction_p.h @@ -1,74 +1,74 @@ /* - * Copyright (C) 2011-2018 Laurent Montel + * Copyright (C) 2011-2019 Laurent Montel * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Library General Public License as published by * the Free Software Foundation; either version 2 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 Library General Public * License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA. */ #ifndef RECENTCOLLECTIONACTION_P_H #define RECENTCOLLECTIONACTION_P_H #include #include #include "collection.h" #include #include class QMenu; class QAbstractItemModel; class QAction; /** * @short A class to manage recent selected folder. * * @author Montel Laurent * @since 4.8 */ namespace Akonadi { class RecentCollectionAction : public QObject { Q_OBJECT public: /** * Creates a new collection recent action */ explicit RecentCollectionAction(Akonadi::StandardActionManager::Type type, const Akonadi::Collection::List &selectedCollectionsList, const QAbstractItemModel *model, QMenu *menu); /** * Destroys the collection recent action. */ ~RecentCollectionAction(); /** * Add new collection. Will create a new item. */ void addRecentCollection(StandardActionManager::Type type, Akonadi::Collection::Id id); void cleanRecentCollection(); private: void writeConfig(); void fillRecentCollection(Akonadi::StandardActionManager::Type type, const Akonadi::Collection::List &selectedCollectionsList); QString actionName(QModelIndex index); bool clear(); private: QStringList mListRecentCollection; QMenu *mMenu = nullptr; const QAbstractItemModel *mModel = nullptr; QAction *mRecentAction = nullptr; KSharedConfig::Ptr mAkonadiConfig; }; } #endif /* RECENTCOLLECTIONACTION_P_H */ diff --git a/src/widgets/renamefavoritedialog.cpp b/src/widgets/renamefavoritedialog.cpp index cea8a7075..2d288636c 100644 --- a/src/widgets/renamefavoritedialog.cpp +++ b/src/widgets/renamefavoritedialog.cpp @@ -1,85 +1,85 @@ /* - Copyright (C) 2011-2018 Laurent Montel + Copyright (C) 2011-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "renamefavoritedialog.h" #include #include #include #include #include #include RenameFavoriteDialog::RenameFavoriteDialog(const QString &caption, const QString &text, const QString &value, const QString &defaultName, QWidget *parent) : QDialog(parent) , m_defaultName(defaultName) { setWindowTitle(caption); setModal(true); QVBoxLayout *mainLayout = new QVBoxLayout(this); m_label = new QLabel(text, this); m_label->setWordWrap(true); mainLayout->addWidget(m_label); m_lineEdit = new QLineEdit(value, this); m_lineEdit->setClearButtonEnabled(true); mainLayout->addWidget(m_lineEdit); m_lineEdit->setFocus(); m_label->setBuddy(m_lineEdit); mainLayout->addStretch(); connect(m_lineEdit, &QLineEdit::textChanged, this, &RenameFavoriteDialog::slotEditTextChanged); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); mOkButton = buttonBox->button(QDialogButtonBox::Ok); QPushButton *defaultButtonName = new QPushButton(i18n("Default Name"), this); buttonBox->addButton(defaultButtonName, QDialogButtonBox::ActionRole); connect(defaultButtonName, &QPushButton::clicked, this, &RenameFavoriteDialog::slotDefaultName); mOkButton->setDefault(true); mOkButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(buttonBox, &QDialogButtonBox::accepted, this, &RenameFavoriteDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &RenameFavoriteDialog::reject); mainLayout->addWidget(buttonBox); slotEditTextChanged(value); setMinimumWidth(350); } RenameFavoriteDialog::~RenameFavoriteDialog() { } void RenameFavoriteDialog::slotDefaultName() { m_lineEdit->setText(m_defaultName); } void RenameFavoriteDialog::slotEditTextChanged(const QString &text) { mOkButton->setEnabled(!text.trimmed().isEmpty()); } QString RenameFavoriteDialog::newName() const { return m_lineEdit->text(); } diff --git a/src/widgets/renamefavoritedialog.h b/src/widgets/renamefavoritedialog.h index 4de04632f..a3709bb0f 100644 --- a/src/widgets/renamefavoritedialog.h +++ b/src/widgets/renamefavoritedialog.h @@ -1,51 +1,51 @@ /* - Copyright (C) 2011-2018 Laurent Montel + Copyright (C) 2011-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef RENAMEFAVORITEDIALOG_H #define RENAMEFAVORITEDIALOG_H #include #include "collection.h" class QLabel; class QLineEdit; class QPushButton; class RenameFavoriteDialog : public QDialog { Q_OBJECT public: explicit RenameFavoriteDialog(const QString &caption, const QString &text, const QString &value, const QString &defaultName, QWidget *parent); ~RenameFavoriteDialog(); Q_REQUIRED_RESULT QString newName() const; protected: protected Q_SLOTS: void slotEditTextChanged(const QString &text); void slotDefaultName(); private: QString m_defaultName; QLabel *m_label = nullptr; QLineEdit *m_lineEdit = nullptr; QPushButton *mOkButton = nullptr; }; #endif /* RENAMEFAVORITEDIALOG_H */ diff --git a/src/widgets/tagselectwidget.cpp b/src/widgets/tagselectwidget.cpp index 08af2a07b..b3a3c2f8d 100644 --- a/src/widgets/tagselectwidget.cpp +++ b/src/widgets/tagselectwidget.cpp @@ -1,100 +1,100 @@ /* - Copyright (c) 2015-2018 Montel Laurent + Copyright (c) 2015-2019 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "tagselectwidget.h" #include "monitor.h" #include "tagmodel.h" #include "tageditwidget.h" #include using namespace Akonadi; class Q_DECL_HIDDEN TagSelectWidget::Private { public: Private(TagSelectWidget *parent) : mParent(parent) { init(); } void init(); TagSelectWidget *mParent = nullptr; Akonadi::TagEditWidget *mTagEditWidget = nullptr; }; void TagSelectWidget::Private::init() { QHBoxLayout *mainLayout = new QHBoxLayout(mParent); Monitor *monitor = new Monitor(mParent); monitor->setObjectName(QStringLiteral("TagSelectWidgetMonitor")); monitor->setTypeMonitored(Monitor::Tags); Akonadi::TagModel *model = new Akonadi::TagModel(monitor, mParent); mTagEditWidget = new Akonadi::TagEditWidget(model, mParent, true); mTagEditWidget->setObjectName(QStringLiteral("tageditwidget")); mainLayout->addWidget(mTagEditWidget); } TagSelectWidget::TagSelectWidget(QWidget *parent) : QWidget(parent), d(new Private(this)) { } TagSelectWidget::~TagSelectWidget() { delete d; } void TagSelectWidget::setSelection(const Tag::List &tags) { d->mTagEditWidget->setSelection(tags); } Tag::List TagSelectWidget::selection() const { return d->mTagEditWidget->selection(); } QStringList TagSelectWidget::tagToStringList() const { QStringList list; const Akonadi::Tag::List tags = selection(); list.reserve(tags.count()); for (const Akonadi::Tag &tag : tags) { list.append(tag.url().url()); } return list; } void TagSelectWidget::setSelectionFromStringList(const QStringList &lst) { Akonadi::Tag::List tags; tags.reserve(lst.count()); for (const QString &category : lst) { tags.append(Akonadi::Tag::fromUrl(QUrl(category))); } setSelection(tags); } diff --git a/src/widgets/tagselectwidget.h b/src/widgets/tagselectwidget.h index b6acd93c2..99bf6d541 100644 --- a/src/widgets/tagselectwidget.h +++ b/src/widgets/tagselectwidget.h @@ -1,61 +1,61 @@ /* - Copyright (c) 2015-2018 Montel Laurent + Copyright (c) 2015-2019 Montel Laurent This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef TAGSELECTWIDGET_H #define TAGSELECTWIDGET_H #include #include "tag.h" #include "akonadiwidgets_export.h" namespace Akonadi { /** * A widget that offers facilities to add/remove tags and provides a way to select tags. * * @since 4.14.6 */ class AKONADIWIDGETS_EXPORT TagSelectWidget : public QWidget { Q_OBJECT public: explicit TagSelectWidget(QWidget *parent = nullptr); ~TagSelectWidget(); void setSelection(const Akonadi::Tag::List &tags); Q_REQUIRED_RESULT Akonadi::Tag::List selection() const; /** * @brief tagToStringList * @return QStringList from selected tag (List of Url) */ Q_REQUIRED_RESULT QStringList tagToStringList() const; /** * @brief setSelectionFromStringList, convert a QStringList to Tag (converted from url) */ void setSelectionFromStringList(const QStringList &lst); private: //@cond PRIVATE class Private; Private *const d; }; } #endif // TAGSELECTWIDGET_H diff --git a/src/widgets/tagwidget.cpp b/src/widgets/tagwidget.cpp index 31ca7b65e..4d0c39e82 100644 --- a/src/widgets/tagwidget.cpp +++ b/src/widgets/tagwidget.cpp @@ -1,152 +1,152 @@ /* This file is part of Akonadi Copyright (c) 2010 Tobias Koenig Copyright (c) 2014 Christian Mollekopf - Copyright (C) 2016-2018 Laurent Montel + Copyright (C) 2016-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "tagwidget.h" #include "tagmodel.h" #include "changerecorder.h" #include "tagselectiondialog.h" #include #include #include #include #include using namespace Akonadi; class Q_DECL_HIDDEN TagWidget::Private { public: Private() { } Akonadi::Tag::List mTags; TagView *mTagView = nullptr; Akonadi::TagModel *mModel = nullptr; QToolButton *mEditButton = nullptr; }; TagView::TagView(QWidget *parent) : QLineEdit(parent) { setPlaceholderText(i18n("Click to add tags")); setReadOnly(true); } void TagView::contextMenuEvent(QContextMenuEvent *event) { if (text().isEmpty()) { return; } QMenu menu; menu.addAction(i18n("Clear"), this, SIGNAL(clearTags())); menu.exec(event->globalPos()); } TagWidget::TagWidget(QWidget *parent) : QWidget(parent) , d(new Private) { Monitor *monitor = new Monitor(this); monitor->setObjectName(QStringLiteral("TagWidgetMonitor")); monitor->setTypeMonitored(Monitor::Tags); d->mModel = new Akonadi::TagModel(monitor, this); connect(monitor, &Monitor::tagAdded, this, &TagWidget::updateView); QHBoxLayout *layout = new QHBoxLayout(this); layout->setMargin(0); d->mTagView = new TagView(this); connect(d->mTagView, &TagView::clearTags, this, &TagWidget::clearTags); layout->addWidget(d->mTagView); d->mEditButton = new QToolButton(this); d->mEditButton->setText(i18n("...")); layout->addWidget(d->mEditButton, Qt::AlignRight); layout->setStretch(0, 10); connect(d->mEditButton, &QToolButton::clicked, this, &TagWidget::editTags); connect(d->mModel, &Akonadi::TagModel::populated, this, &TagWidget::updateView); } TagWidget::~TagWidget() { } void TagWidget::clearTags() { if (!d->mTags.isEmpty()) { d->mTags.clear(); d->mTagView->clear(); emit selectionChanged(d->mTags); } } void TagWidget::setSelection(const Akonadi::Tag::List &tags) { if (d->mTags != tags) { d->mTags = tags; updateView(); } } Akonadi::Tag::List TagWidget::selection() const { return d->mTags; } void TagWidget::setReadOnly(bool readOnly) { d->mEditButton->setEnabled(!readOnly); //d->mTagView is always readOnly => not change it. } void TagWidget::editTags() { QScopedPointer dlg(new TagSelectionDialog(this)); dlg->setSelection(d->mTags); if (dlg->exec() == QDialog::Accepted) { d->mTags = dlg->selection(); updateView(); emit selectionChanged(d->mTags); } } void TagWidget::updateView() { QStringList tagsNames; // Load the real tag names from the model for (int i = 0; i < d->mModel->rowCount(); ++i) { const QModelIndex index = d->mModel->index(i, 0); const Akonadi::Tag tag = d->mModel->data(index, Akonadi::TagModel::TagRole).value(); if (d->mTags.contains(tag)) { tagsNames << tag.name(); } } d->mTagView->setText(tagsNames.join(QStringLiteral(", "))); } diff --git a/tests/libs/conflictresolvedialogtest_gui.cpp b/tests/libs/conflictresolvedialogtest_gui.cpp index 672af51c5..bae8ff795 100644 --- a/tests/libs/conflictresolvedialogtest_gui.cpp +++ b/tests/libs/conflictresolvedialogtest_gui.cpp @@ -1,45 +1,45 @@ /* - Copyright (C) 2017-2018 Laurent Montel + Copyright (C) 2017-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "../src/widgets/conflictresolvedialog_p.h" #include #include #include #include int main(int argc, char **argv) { QApplication app(argc, argv); KAboutData aboutData(QStringLiteral("conflictresolvedialogtest_gui"), QStringLiteral("conflictresolvedialogtest_gui"), QStringLiteral("0.10")); KAboutData::setApplicationData(aboutData); QCommandLineParser parser; aboutData.setupCommandLine(&parser); parser.process(app); aboutData.processCommandLine(&parser); QStandardPaths::setTestModeEnabled(true); Akonadi::ConflictResolveDialog dlg; dlg.exec(); return 0; }