From a4481b80f29e7f3e174b6b215d89a224408c4e62 Mon Sep 17 00:00:00 2001 From: csoler Date: Tue, 6 Aug 2019 22:52:07 +0200 Subject: [PATCH] added sorting/filtering to FriendListModel --- .../src/gui/common/FriendListModel.cpp | 107 ++++++++--------- .../src/gui/common/NewFriendList.cpp | 108 ++++++++++++------ retroshare-gui/src/gui/common/NewFriendList.h | 17 +-- 3 files changed, 127 insertions(+), 105 deletions(-) diff --git a/retroshare-gui/src/gui/common/FriendListModel.cpp b/retroshare-gui/src/gui/common/FriendListModel.cpp index 465c9e9b0..e9052e245 100644 --- a/retroshare-gui/src/gui/common/FriendListModel.cpp +++ b/retroshare-gui/src/gui/common/FriendListModel.cpp @@ -367,30 +367,16 @@ QVariant RsFriendListModel::data(const QModelIndex &index, int role) const case Qt::DisplayRole: return displayRole(entry,index.column()) ; case Qt::FontRole: return fontRole(entry,index.column()) ; case Qt::TextColorRole: return textColorRole(entry,index.column()) ; + case FilterRole: return filterRole(entry,index.column()) ; default: return QVariant(); } -// if(role == Qt::FontRole) -// { -// QFont font ; -// font.setBold(fmpe.msgflags & (RS_MSG_NEW | RS_MSG_UNREAD_BY_USER)); -// -// return QVariant(font); -// } - // case Qt::DecorationRole: return decorationRole(fmpe,index.column()) ; // case Qt::ToolTipRole: return toolTipRole (fmpe,index.column()) ; // case Qt::UserRole: return userRole (fmpe,index.column()) ; -// case Qt::BackgroundRole: return backgroundRole(fmpe,index.column()) ; // -// case FilterRole: return filterRole (fmpe,index.column()) ; -// case StatusRole: return statusRole (fmpe,index.column()) ; // case SortRole: return sortRole (fmpe,index.column()) ; -// case MsgFlagsRole: return fmpe.msgflags ; -// case UnreadRole: return fmpe.msgflags & (RS_MSG_NEW | RS_MSG_UNREAD_BY_USER); -// case MsgIdRole: return QString::fromStdString(fmpe.msgId) ; -// case SrcIdRole: return QString::fromStdString(fmpe.srcId.toStdString()) ; } QVariant RsFriendListModel::textColorRole(const EntryIndex& fmpe,int column) const @@ -415,39 +401,37 @@ QVariant RsFriendListModel::statusRole(const EntryIndex& fmpe,int column) const bool RsFriendListModel::passesFilter(const EntryIndex& e,int column) const { -// QString s ; -// bool passes_strings = true ; + QString s ; + bool passes_strings = true ; + + if(!mFilterStrings.empty()) + { + switch(mFilterType) + { + case FILTER_TYPE_ID: s = displayRole(e,COLUMN_THREAD_ID).toString(); + break; + + case FILTER_TYPE_NAME: s = displayRole(e,COLUMN_THREAD_NAME).toString(); + //case FILTER_TYPE_NAME: s = sortRole(fmpe,COLUMN_THREAD_AUTHOR).toString(); + if(s.isNull()) + passes_strings = false; + break; + }; + } + + if(!s.isNull()) + for(auto iter(mFilterStrings.begin()); iter != mFilterStrings.end(); ++iter) + passes_strings = passes_strings && s.contains(*iter,Qt::CaseInsensitive); + +// bool passes_quick_view = +// (mQuickViewFilter==QUICK_VIEW_ALL) +// || (std::find(fmpe.msgtags.begin(),fmpe.msgtags.end(),mQuickViewFilter) != fmpe.msgtags.end()) +// || (mQuickViewFilter==QUICK_VIEW_STARRED && (fmpe.msgflags & RS_MSG_STAR)) +// || (mQuickViewFilter==QUICK_VIEW_SYSTEM && (fmpe.msgflags & RS_MSG_SYSTEM)); // -// if(!mFilterStrings.empty()) -// { -// switch(mFilterType) -// { -// case FILTER_TYPE_ID: s = displayRole(fmpe,COLUMN_THREAD_SUBJECT).toString(); -// break; -// -// case FILTER_TYPE_NAME: s = sortRole(fmpe,COLUMN_THREAD_AUTHOR).toString(); -// if(s.isNull()) -// passes_strings = false; -// break; -// }; -// } -// -// if(!s.isNull()) -// for(auto iter(mFilterStrings.begin()); iter != mFilterStrings.end(); ++iter) -// passes_strings = passes_strings && s.contains(*iter,Qt::CaseInsensitive); -// -// bool passes_quick_view = -// (mQuickViewFilter==QUICK_VIEW_ALL) -// || (std::find(fmpe.msgtags.begin(),fmpe.msgtags.end(),mQuickViewFilter) != fmpe.msgtags.end()) -// || (mQuickViewFilter==QUICK_VIEW_STARRED && (fmpe.msgflags & RS_MSG_STAR)) -// || (mQuickViewFilter==QUICK_VIEW_SYSTEM && (fmpe.msgflags & RS_MSG_SYSTEM)); -// #ifdef DEBUG_MESSAGE_MODEL -// std::cerr << "Passes filter: type=" << mFilterType << " s=\"" << s.toStdString() << "MsgFlags=" << fmpe.msgflags << " msgtags=" ; -// foreach(uint32_t i,fmpe.msgtags) std::cerr << i << " " ; -// std::cerr << "\" strings:" << passes_strings << " quick_view:" << passes_quick_view << std::endl; -// #endif -// -// return passes_quick_view && passes_strings; +// return passes_quick_view && passes_strings; + + return passes_strings; } QVariant RsFriendListModel::filterRole(const EntryIndex& e,int column) const @@ -521,24 +505,25 @@ QVariant RsFriendListModel::sizeHintRole(int col) const QVariant RsFriendListModel::sortRole(const EntryIndex& fmpe,int column) const { -// switch(column) -// { -// case COLUMN_THREAD_DATE: return QVariant(QString::number(fmpe.ts)); // we should probably have leading zeroes here + return displayRole(fmpe,column); + +// switch(column) +// { +// case COLUMN_THREAD_NAME: return QVariant(QString::number(fmpe.ts)); // we should probably have leading zeroes here // -// case COLUMN_THREAD_READ: return QVariant((bool)IS_MESSAGE_UNREAD(fmpe.msgflags)); +// case COLUMN_THREAD_ID: return QVariant((bool)IS_MESSAGE_UNREAD(fmpe.msgflags)); // -// case COLUMN_THREAD_STAR: return QVariant((fmpe.msgflags & RS_MSG_STAR)? 1:0); +// case COLUMN_THREAD_IP: return QVariant((fmpe.msgflags & RS_MSG_STAR)? 1:0); // -// case COLUMN_THREAD_AUTHOR:{ -// QString name; +// case COLUMN_THREAD_LAST_CONTACT: +// QString name; // -// if(GxsIdTreeItemDelegate::computeName(RsGxsId(fmpe.srcId.toStdString()),name)) -// return name; -// } -// default: -// return displayRole(fmpe,column); -// } - return QVariant(); +// if(GxsIdTreeItemDelegate::computeName(RsGxsId(fmpe.srcId.toStdString()),name)) +// return name; +// } +// default: +// } +// return QVariant(); } QVariant RsFriendListModel::fontRole(const EntryIndex& e, int col) const diff --git a/retroshare-gui/src/gui/common/NewFriendList.cpp b/retroshare-gui/src/gui/common/NewFriendList.cpp index 7c3a445a2..ca4c2d1bf 100644 --- a/retroshare-gui/src/gui/common/NewFriendList.cpp +++ b/retroshare-gui/src/gui/common/NewFriendList.cpp @@ -107,6 +107,36 @@ Q_DECLARE_METATYPE(ElidedLabel*) +class FriendListSortFilterProxyModel: public QSortFilterProxyModel +{ +public: + FriendListSortFilterProxyModel(const QHeaderView *header,QObject *parent = NULL): QSortFilterProxyModel(parent),m_header(header) , m_sortingEnabled(false) {} + + bool lessThan(const QModelIndex& left, const QModelIndex& right) const override + { + return left.data(RsFriendListModel::SortRole) < right.data(RsFriendListModel::SortRole) ; + } + + bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override + { + return sourceModel()->index(source_row,0,source_parent).data(RsFriendListModel::FilterRole).toString() == RsFriendListModel::FilterString ; + } + + void sort( int column, Qt::SortOrder order = Qt::AscendingOrder ) override + { + if(m_sortingEnabled) + return QSortFilterProxyModel::sort(column,order) ; + } + + void setSortingEnabled(bool b) { m_sortingEnabled = b ; } + void setSortByState(bool b) { m_sortByState = b ; } + +private: + const QHeaderView *m_header ; + bool m_sortingEnabled; + bool m_sortByState; +}; + NewFriendList::NewFriendList(QWidget *parent) : QWidget(parent), ui(new Ui::NewFriendList()), @@ -135,24 +165,36 @@ NewFriendList::NewFriendList(QWidget *parent) : ui->filterLineEdit->showFilterIcon(); mModel = new RsFriendListModel(); - ui->peerTreeWidget->setModel(mModel); + mProxyModel = new FriendListSortFilterProxyModel(ui->peerTreeWidget->header(),this); + + mProxyModel->setSourceModel(mModel); + mProxyModel->setSortRole(RsFriendListModel::SortRole); + mProxyModel->setDynamicSortFilter(false); + mProxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); + mProxyModel->setFilterRole(RsFriendListModel::FilterRole); + mProxyModel->setFilterRegExp(QRegExp(RsFriendListModel::FilterString)); + + ui->peerTreeWidget->setModel(mProxyModel); connect(NotifyQt::getInstance(), SIGNAL(friendsChanged()), mModel, SLOT(updateInternalData())); /* Add filter actions */ - // QTreeWidgetItem *headerItem = ui->peerTreeWidget->headerItem(); - // QString headerText = headerItem->text(COLUMN_NAME); - // ui->filterLineEdit->addFilter(QIcon(), headerText, COLUMN_NAME, QString("%1 %2").arg(tr("Search"), headerText)); - // ui->filterLineEdit->addFilter(QIcon(), tr("ID"), COLUMN_ID, tr("Search ID")); + QString headerText = mModel->headerData(RsFriendListModel::COLUMN_THREAD_NAME,Qt::Horizontal,Qt::DisplayRole).toString(); + ui->filterLineEdit->addFilter(QIcon(), headerText, RsFriendListModel::COLUMN_THREAD_NAME, QString("%1 %2").arg(tr("Search"), headerText)); + ui->filterLineEdit->addFilter(QIcon(), tr("ID"), RsFriendListModel::COLUMN_THREAD_ID, tr("Search ID")); - mActionSortByState = new QAction(tr("Sort by state"), this); + mActionSortByState = new QAction(tr("Display online friends on top"), this); mActionSortByState->setCheckable(true); - connect(mActionSortByState, SIGNAL(toggled(bool)), this, SLOT(sortByState(bool))); - // ui->peerTreeWidget->addContextMenuAction(mActionSortByState); + connect(mActionSortByState, SIGNAL(toggled(bool)), this, SLOT(toggleSortByState(bool))); + + //setting default filter by column as subject + ui->filterLineEdit->setCurrentFilter(RsFriendListModel::COLUMN_THREAD_NAME); + ui->peerTreeWidget->setSortingEnabled(true); /* Set sort */ sortByColumn(RsFriendListModel::COLUMN_THREAD_NAME, Qt::AscendingOrder); - sortByState(false); + toggleSortByState(false); + connect(ui->peerTreeWidget->header(),SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(sortColumn(int,Qt::SortOrder))); // workaround for Qt bug, should be solved in next Qt release 4.7.0 // http://bugreports.qt.nokia.com/browse/QTBUG-8270 @@ -194,6 +236,13 @@ NewFriendList::~NewFriendList() delete ui; } +void NewFriendList::sortColumn(int col,Qt::SortOrder so) +{ + mProxyModel->setSortingEnabled(true); + mProxyModel->sort(col,so); + mProxyModel->setSortingEnabled(false); +} + void NewFriendList::headerContextMenuRequested(QPoint p) { QMenu displayMenu(tr("Show Items"), this); @@ -268,7 +317,7 @@ void NewFriendList::processSettings(bool load) setShowGroups(Settings->value("showGroups", mShowGroups).toBool()); // sort - sortByState(Settings->value("sortByState", isSortByState()).toBool()); + toggleSortByState(Settings->value("sortByState", isSortByState()).toBool()); // open groups int arrayIndex = Settings->beginReadArray("Groups"); @@ -311,6 +360,11 @@ void NewFriendList::processSettings(bool load) } } +void NewFriendList::toggleSortByState(bool sort) +{ + mProxyModel->setSortByState(sort); +} + void NewFriendList::changeEvent(QEvent *e) { QWidget::changeEvent(e); @@ -329,7 +383,7 @@ void NewFriendList::changeEvent(QEvent *e) */ void NewFriendList::peerTreeWidgetCustomPopupMenu() { - QModelIndex index = getCurrentIndex(); + QModelIndex index = getCurrentSourceIndex(); RsFriendListModel::EntryType type = mModel->getType(index); QMenu contextMenu(this); @@ -359,6 +413,7 @@ void NewFriendList::peerTreeWidgetCustomPopupMenu() QWidgetAction *widgetAction = new QWidgetAction(this); widgetAction->setDefaultWidget(widget); contextMenu.addAction(widgetAction); + contextMenu.addAction(mActionSortByState); // create menu entries if(index.isValid()) @@ -739,20 +794,20 @@ std::string NewFriendList::getSelectedGroupId() const return ginfo.id.toStdString(); } -QModelIndex NewFriendList::getCurrentIndex() const +QModelIndex NewFriendList::getCurrentSourceIndex() const { QModelIndexList selectedIndexes = ui->peerTreeWidget->selectionModel()->selectedIndexes(); if(selectedIndexes.size() != RsFriendListModel::COLUMN_THREAD_NB_COLUMNS) // check that a single row is selected return QModelIndex(); - return *selectedIndexes.begin(); + return mProxyModel->mapToSource(*selectedIndexes.begin()); } bool NewFriendList::getCurrentGroup(RsGroupInfo& info) const { /* get the current, and extract the Id */ - QModelIndex index = getCurrentIndex(); + QModelIndex index = getCurrentSourceIndex(); if(!index.isValid()) return false; @@ -763,7 +818,7 @@ bool NewFriendList::getCurrentNode(RsFriendListModel::RsNodeDetails& prof) const { /* get the current, and extract the Id */ - QModelIndex index = getCurrentIndex(); + QModelIndex index = getCurrentSourceIndex(); if(!index.isValid()) return false; @@ -774,7 +829,7 @@ bool NewFriendList::getCurrentProfile(RsFriendListModel::RsProfileDetails& prof) { /* get the current, and extract the Id */ - QModelIndex index = getCurrentIndex(); + QModelIndex index = getCurrentSourceIndex(); if(!index.isValid()) return false; @@ -1367,27 +1422,6 @@ void NewFriendList::setShowState(bool show) } } -void NewFriendList::sortByState(bool sort) -{ -// int columnCount = ui->peerTreeWidget->columnCount(); -// for (int i = 0; i < columnCount; ++i) { -// mCompareRole->setRole(i, ROLE_SORT_GROUP); -// mCompareRole->addRole(i, ROLE_SORT_STANDARD_GROUP); -// -// if (sort) { -// mCompareRole->addRole(i, ROLE_SORT_STATE); -// mCompareRole->addRole(i, ROLE_SORT_NAME); -// } else { -// mCompareRole->addRole(i, ROLE_SORT_NAME); -// mCompareRole->addRole(i, ROLE_SORT_STATE); -// } -// } -// -// mActionSortByState->setChecked(sort); -// -// ui->peerTreeWidget->resort(); -} - bool NewFriendList::isSortByState() { return mActionSortByState->isChecked(); diff --git a/retroshare-gui/src/gui/common/NewFriendList.h b/retroshare-gui/src/gui/common/NewFriendList.h index 185882d34..e3811f7d5 100644 --- a/retroshare-gui/src/gui/common/NewFriendList.h +++ b/retroshare-gui/src/gui/common/NewFriendList.h @@ -35,16 +35,17 @@ namespace Ui { class RSTreeWidgetItemCompareRole; class QTreeWidgetItem; class QToolButton; +class FriendListSortFilterProxyModel; class NewFriendList: public QWidget { Q_OBJECT - Q_PROPERTY(QColor textColorGroup READ textColorGroup WRITE setTextColorGroup) - Q_PROPERTY(QColor textColorStatusOffline READ textColorStatusOffline WRITE setTextColorStatusOffline) - Q_PROPERTY(QColor textColorStatusAway READ textColorStatusAway WRITE setTextColorStatusAway) - Q_PROPERTY(QColor textColorStatusBusy READ textColorStatusBusy WRITE setTextColorStatusBusy) - Q_PROPERTY(QColor textColorStatusOnline READ textColorStatusOnline WRITE setTextColorStatusOnline) + Q_PROPERTY(QColor textColorGroup READ textColorGroup WRITE setTextColorGroup) + Q_PROPERTY(QColor textColorStatusOffline READ textColorStatusOffline WRITE setTextColorStatusOffline) + Q_PROPERTY(QColor textColorStatusAway READ textColorStatusAway WRITE setTextColorStatusAway) + Q_PROPERTY(QColor textColorStatusBusy READ textColorStatusBusy WRITE setTextColorStatusBusy) + Q_PROPERTY(QColor textColorStatusOnline READ textColorStatusOnline WRITE setTextColorStatusOnline) Q_PROPERTY(QColor textColorStatusInactive READ textColorStatusInactive WRITE setTextColorStatusInactive) public: @@ -80,7 +81,7 @@ public: public slots: void filterItems(const QString &text); - void sortByState(bool sort); + void toggleSortByState(bool sort); void toggleColumnVisible(); void setShowGroups(bool show); @@ -89,6 +90,7 @@ public slots: void headerContextMenuRequested(QPoint); private slots: + void sortColumn(int col,Qt::SortOrder so); protected: void changeEvent(QEvent *e); @@ -99,7 +101,7 @@ private: RsFriendListModel *mModel; QAction *mActionSortByState; - QModelIndex getCurrentIndex() const; + QModelIndex getCurrentSourceIndex() const; bool getCurrentNode(RsFriendListModel::RsNodeDetails& prof) const; bool getCurrentGroup(RsGroupInfo& prof) const; @@ -123,6 +125,7 @@ private: bool exportFriendlist(QString &fileName); bool importFriendlist(QString &fileName, bool &errorPeers, bool &errorGroups); + FriendListSortFilterProxyModel *mProxyModel ; private slots: void groupsChanged(); void peerTreeWidgetCustomPopupMenu();