diff --git a/src/core/commentsmodel.cpp b/src/core/commentsmodel.cpp --- a/src/core/commentsmodel.cpp +++ b/src/core/commentsmodel.cpp @@ -163,7 +163,7 @@ { int idx{-1}; if (comment->parent) { - d->comments.indexOf(std::shared_ptr(comment->parent)); + idx = d->comments.indexOf(comment->parent); } value.setValue(idx); } diff --git a/src/qtquick/commentsmodel.h b/src/qtquick/commentsmodel.h --- a/src/qtquick/commentsmodel.h +++ b/src/qtquick/commentsmodel.h @@ -22,7 +22,7 @@ #ifndef KNSQUICK_COMMENTSMODEL_H #define KNSQUICK_COMMENTSMODEL_H -#include +#include #include #include @@ -36,7 +36,7 @@ * and updated for display * @since 5.63 */ -class CommentsModel : public QIdentityProxyModel, public QQmlParserStatus +class CommentsModel : public QSortFilterProxyModel, public QQmlParserStatus { Q_OBJECT Q_INTERFACES(QQmlParserStatus) @@ -48,7 +48,24 @@ * The index in the model of the entry to fetch comments for */ Q_PROPERTY(int entryIndex READ entryIndex WRITE setEntryIndex NOTIFY entryIndexChanged) + /** + * Which types of comments should be included + * @default AllComments + * @since 5.65 + */ + Q_PROPERTY(KNewStuffQuick::CommentsModel::IncludedComments includedComments READ includedComments WRITE setIncludedComments NOTIFY includedCommentsChanged) public: + /** + * The options which can be set for which comments to include + * @since 5.65 + */ + enum IncludedComments { + IncludeAllComments = 0, //< All comments should be included + IncludeOnlyReviews = 1, //< Only comments which have a rating (and thus is considered a review) should be included + IncludeReviewsAndReplies = 2 //< Reviews (as OnlyReviews), except child comments are also included + }; + Q_ENUM(IncludedComments) + explicit CommentsModel(QObject *parent = nullptr); ~CommentsModel() override; void classBegin() override; @@ -62,11 +79,28 @@ void setEntryIndex(int entryIndex); Q_SIGNAL void entryIndexChanged(); + /** + * Which comments should be included + * @since 5.65 + */ + CommentsModel::IncludedComments includedComments() const; + /** + * Set which comments should be included + * @since 5.65 + */ + void setIncludedComments(CommentsModel::IncludedComments includedComments); + /** + * Fired when the value of includedComments changes + * @since 5.65 + */ + Q_SIGNAL void includedCommentsChanged(); + + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; private: class Private; Private *d; }; } - +Q_DECLARE_METATYPE(KNewStuffQuick::CommentsModel::IncludedComments) #endif//KNSQUICK_COMMENTSMODEL_H diff --git a/src/qtquick/commentsmodel.cpp b/src/qtquick/commentsmodel.cpp --- a/src/qtquick/commentsmodel.cpp +++ b/src/qtquick/commentsmodel.cpp @@ -40,20 +40,37 @@ ItemsModel *itemsModel{nullptr}; int entryIndex{-1}; bool componentCompleted{false}; + CommentsModel::IncludedComments includedComments{CommentsModel::IncludeAllComments}; QSharedPointer provider; void resetConnections() { if (componentCompleted && itemsModel) { q->setSourceModel(qobject_cast(itemsModel->data(itemsModel->index(entryIndex), ItemsModel::CommentsModelRole).value())); } } + + bool hasReview(const QModelIndex& index, bool checkParents = false) { + bool result{false}; + if (q->sourceModel()) { + if (q->sourceModel()->data(index, KNSCore::CommentsModel::ScoreRole).toInt() > 0) { + result = true; + } + if (result == false && checkParents) { + QModelIndex parentIndex = q->sourceModel()->index(q->sourceModel()->data(index, KNSCore::CommentsModel::ParentIndexRole).toInt(), 0); + if (parentIndex.isValid()) { + result = hasReview(parentIndex, true); + } + } + } + return result; + } }; } using namespace KNewStuffQuick; CommentsModel::CommentsModel(QObject *parent) - : QIdentityProxyModel(parent) + : QSortFilterProxyModel(parent) , d(new Private(this)) { } @@ -99,3 +116,35 @@ emit entryIndexChanged(); } } + +CommentsModel::IncludedComments KNewStuffQuick::CommentsModel::includedComments() const +{ + return d->includedComments; +} + +void KNewStuffQuick::CommentsModel::setIncludedComments(CommentsModel::IncludedComments includedComments) +{ + if (d->includedComments != includedComments) { + d->includedComments = includedComments; + invalidateFilter(); + emit includedCommentsChanged(); + } +} + +bool KNewStuffQuick::CommentsModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const +{ + bool result{false}; + switch (d->includedComments) { + case IncludeOnlyReviews: + result = d->hasReview(sourceModel()->index(sourceRow, 0, sourceParent)); + break; + case IncludeReviewsAndReplies: + result = d->hasReview(sourceModel()->index(sourceRow, 0, sourceParent), true); + break; + case IncludeAllComments: + default: + result = true; + break; + } + return result; +} diff --git a/src/qtquick/qml/EntryDetails.qml b/src/qtquick/qml/EntryDetails.qml --- a/src/qtquick/qml/EntryDetails.qml +++ b/src/qtquick/qml/EntryDetails.qml @@ -175,7 +175,7 @@ Kirigami.LinkButton { Kirigami.FormData.label: i18n("Comments and Reviews:") enabled: component.commentsCount > 0 - text: i18nc("A link which, when clicked, opens a new sub page with reviews (comments) for this entry", "%1 Reviews").arg(component.commentsCount) + text: i18nc("A link which, when clicked, opens a new sub page with comments (comments with or without ratings) for this entry", "%1 Reviews and Comments").arg(component.commentsCount) onClicked: pageStack.push(commentsPage) } Private.Rating { diff --git a/src/qtquick/qml/private/EntryCommentsPage.qml b/src/qtquick/qml/private/EntryCommentsPage.qml --- a/src/qtquick/qml/private/EntryCommentsPage.qml +++ b/src/qtquick/qml/private/EntryCommentsPage.qml @@ -39,6 +39,28 @@ property alias entryIndex: commentsModel.entryIndex property alias itemsModel: commentsModel.itemsModel title: i18nc("Title for the page containing a view of the comments for the entry", "Comments and Reviews for %1").arg(component.entryName) + actions { + contextualActions: [ + Kirigami.Action { + text: i18nc("Title for the item which is checked when all comments should be shown", "Show All Comments") + checked: commentsModel.includedComments == NewStuff.CommentsModel.IncludeAllComments + checkable: true + onTriggered: commentsModel.includedComments = NewStuff.CommentsModel.IncludeAllComments + }, + Kirigami.Action { + text: i18nc("Title for the item which is checked when only comments which are reviews should be shown", "Show Reviews Only") + checked: commentsModel.includedComments == NewStuff.CommentsModel.IncludeOnlyReviews + checkable: true + onTriggered: commentsModel.includedComments = NewStuff.CommentsModel.IncludeOnlyReviews + }, + Kirigami.Action { + text: i18nc("Title for the item which is checked when comments which are reviews, and their children should be shown", "Show Reviews and Replies") + checked: commentsModel.includedComments == NewStuff.CommentsModel.IncludeReviewsAndReplies + checkable: true + onTriggered: commentsModel.includedComments = NewStuff.CommentsModel.IncludeReviewsAndReplies + } + ] + } ListView { id: commentsView model: NewStuff.CommentsModel {