added filtering mechanism in ForumModel

This commit is contained in:
csoler 2018-12-01 16:09:35 +01:00
parent b7b9f335f9
commit a51eba1db2
No known key found for this signature in database
GPG Key ID: 7BCA522266C0804C
3 changed files with 91 additions and 34 deletions

View File

@ -10,6 +10,7 @@
#include "GxsForumModel.h" #include "GxsForumModel.h"
#include "retroshare/rsgxsflags.h" #include "retroshare/rsgxsflags.h"
#include "retroshare/rsgxsforums.h" #include "retroshare/rsgxsforums.h"
#include "retroshare/rsexpr.h"
//#define DEBUG_FORUMMODEL //#define DEBUG_FORUMMODEL
@ -17,6 +18,8 @@ Q_DECLARE_METATYPE(RsMsgMetaData);
std::ostream& operator<<(std::ostream& o, const QModelIndex& i);// defined elsewhere std::ostream& operator<<(std::ostream& o, const QModelIndex& i);// defined elsewhere
const QString RsGxsForumModel::FilterString("filtered");
RsGxsForumModel::RsGxsForumModel(QObject *parent) RsGxsForumModel::RsGxsForumModel(QObject *parent)
: QAbstractItemModel(parent) : QAbstractItemModel(parent)
{ {
@ -307,6 +310,7 @@ QVariant RsGxsForumModel::data(const QModelIndex &index, int role) const
case Qt::TextColorRole: return textColorRole (fmpe,index.column()) ; case Qt::TextColorRole: return textColorRole (fmpe,index.column()) ;
case Qt::BackgroundRole: return backgroundRole(fmpe,index.column()) ; case Qt::BackgroundRole: return backgroundRole(fmpe,index.column()) ;
case FilterRole: return filterRole (fmpe,index.column()) ;
case ThreadPinnedRole: return pinnedRole (fmpe,index.column()) ; case ThreadPinnedRole: return pinnedRole (fmpe,index.column()) ;
case MissingRole: return missingRole (fmpe,index.column()) ; case MissingRole: return missingRole (fmpe,index.column()) ;
case StatusRole: return statusRole (fmpe,index.column()) ; case StatusRole: return statusRole (fmpe,index.column()) ;
@ -337,10 +341,41 @@ QVariant RsGxsForumModel::statusRole(const ForumModelPostEntry& fmpe,int column)
return QVariant(fmpe.mMsgStatus); return QVariant(fmpe.mMsgStatus);
} }
QVariant RsGxsForumModel::filterRole(const ForumModelPostEntry& fmpe,int column) const
{
if(mFilterColumn < 0)
return QVariant(QString());
switch(mFilterColumn)
{
case COLUMN_THREAD_TITLE:
{
for(auto iter(mFilterStrings.begin()); iter != mFilterStrings.end(); ++iter)
if(fmpe.mTitle.end() != std::search( fmpe.mTitle.begin(), fmpe.mTitle.end(), (*iter).begin(), (*iter).end(), RsRegularExpression::CompareCharIC() ))
return QVariant(FilterString);
return QVariant(QString());
}
default:
return QVariant(FilterString);
}
}
void RsGxsForumModel::setFilter(int column,const std::list<std::string>& strings)
{
mFilterColumn = column;
mFilterStrings = strings;
emit layoutAboutToBeChanged();
emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(0,COLUMN_THREAD_NB_COLUMNS-1,(void*)NULL));
emit layoutChanged();
}
QVariant RsGxsForumModel::missingRole(const ForumModelPostEntry& fmpe,int column) const QVariant RsGxsForumModel::missingRole(const ForumModelPostEntry& fmpe,int column) const
{ {
if(column != COLUMN_THREAD_DATA) // if(column != COLUMN_THREAD_DATA)
return QVariant(); // return QVariant();
if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_MISSING) if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_MISSING)
return QVariant(true); return QVariant(true);
@ -456,6 +491,9 @@ QVariant RsGxsForumModel::displayRole(const ForumModelPostEntry& fmpe,int col) c
case COLUMN_THREAD_READ:return QVariant(); case COLUMN_THREAD_READ:return QVariant();
case COLUMN_THREAD_DATE:{ case COLUMN_THREAD_DATE:{
if(fmpe.mPostFlags & ForumModelPostEntry::FLAG_POST_IS_MISSING)
return QVariant(QString());
QDateTime qtime; QDateTime qtime;
qtime.setTime_t(fmpe.mPublishTs); qtime.setTime_t(fmpe.mPublishTs);

View File

@ -78,11 +78,14 @@ public:
MissingRole = Qt::UserRole+3, MissingRole = Qt::UserRole+3,
StatusRole = Qt::UserRole+4, StatusRole = Qt::UserRole+4,
UnreadChildrenRole = Qt::UserRole+5, UnreadChildrenRole = Qt::UserRole+5,
FilterRole = Qt::UserRole+6,
}; };
QModelIndex root() const{ return createIndex(0,0,(void*)NULL) ;} QModelIndex root() const{ return createIndex(0,0,(void*)NULL) ;}
QModelIndex getIndexOfMessage(const RsGxsMessageId& mid) const; QModelIndex getIndexOfMessage(const RsGxsMessageId& mid) const;
static const QString FilterString ;
std::vector<std::pair<time_t,RsGxsMessageId> > getPostVersions(const RsGxsMessageId& mid) const; std::vector<std::pair<time_t,RsGxsMessageId> > getPostVersions(const RsGxsMessageId& mid) const;
#ifdef TO_REMOVE #ifdef TO_REMOVE
@ -117,6 +120,7 @@ public:
void setTextColorMissing (QColor color) { mTextColorMissing = color;} void setTextColorMissing (QColor color) { mTextColorMissing = color;}
void setMsgReadStatus(const QModelIndex &i, bool read_status, bool with_children); void setMsgReadStatus(const QModelIndex &i, bool read_status, bool with_children);
void setFilter(int column,const std::list<std::string>& strings) ;
int rowCount(const QModelIndex& parent = QModelIndex()) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override;
@ -142,6 +146,7 @@ public:
QVariant authorRole (const ForumModelPostEntry& fmpe, int col) const; QVariant authorRole (const ForumModelPostEntry& fmpe, int col) const;
QVariant sortRole (const ForumModelPostEntry& fmpe, int col) const; QVariant sortRole (const ForumModelPostEntry& fmpe, int col) const;
QVariant fontRole (const ForumModelPostEntry& fmpe, int col) const; QVariant fontRole (const ForumModelPostEntry& fmpe, int col) const;
QVariant filterRole (const ForumModelPostEntry& fmpe, int col) const;
QVariant textColorRole (const ForumModelPostEntry& fmpe, int col) const; QVariant textColorRole (const ForumModelPostEntry& fmpe, int col) const;
QVariant backgroundRole(const ForumModelPostEntry& fmpe, int col) const; QVariant backgroundRole(const ForumModelPostEntry& fmpe, int col) const;
@ -160,6 +165,7 @@ private:
bool mUseChildTS; bool mUseChildTS;
bool mFlatView; bool mFlatView;
int mFilterColumn; int mFilterColumn;
std::list<std::string> mFilterStrings;
void *getParentRef(void *ref,int& row) const; void *getParentRef(void *ref,int& row) const;
void *getChildRef(void *ref,int row) const; void *getChildRef(void *ref,int row) const;

View File

@ -100,12 +100,6 @@ class DistributionItemDelegate: public QStyledItemDelegate
public: public:
DistributionItemDelegate() {} DistributionItemDelegate() {}
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
{
const QRect r = option.rect;
return QSize(r.height(),r.height());
}
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{ {
if(!index.isValid()) if(!index.isValid())
@ -130,11 +124,11 @@ public:
switch(warning_level) switch(warning_level)
{ {
default:
case 3:
case 0: icon = QIcon(IMAGE_VOID); break; case 0: icon = QIcon(IMAGE_VOID); break;
case 1: icon = QIcon(IMAGE_WARNING_YELLOW); break; case 1: icon = QIcon(IMAGE_WARNING_YELLOW); break;
case 2: icon = QIcon(IMAGE_WARNING_RED); break; case 2: icon = QIcon(IMAGE_WARNING_RED); break;
default:
case 3: icon = QIcon(IMAGE_WARNING_UNKNOWN); break;
} }
QPixmap pix = icon.pixmap(r.size()); QPixmap pix = icon.pixmap(r.size());
@ -225,7 +219,7 @@ public:
QPixmap pix = icon.pixmap(r.size()); QPixmap pix = icon.pixmap(r.size());
return QSize(pix.width() + fm.width(str),std::max(1.1*pix.height(),1.4*fm.height())); return QSize(1.2*(pix.width() + fm.width(str)),std::max(1.1*pix.height(),1.4*fm.height()));
} }
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex& index) const override virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex& index) const override
@ -261,12 +255,17 @@ public:
else else
icon = *icons.begin(); icon = *icons.begin();
if(index.data(RsGxsForumModel::MissingRole).toBool())
painter->drawText(r.topLeft() + QPoint(f/2.0,f*1.0), tr("[None]"));
else
{
QPixmap pix = icon.pixmap(r.size()); QPixmap pix = icon.pixmap(r.size());
const QPoint p = QPoint(pix.width()/2.0, (r.height() - pix.height())/2);
// draw pixmap at center of item // draw pixmap at center of item
const QPoint p = QPoint(pix.width()/2.0, (r.height() - pix.height())/2);
painter->drawPixmap(r.topLeft() + p, pix); painter->drawPixmap(r.topLeft() + p, pix);
painter->drawText(r.topLeft() + p + QPoint(pix.width()+f/2.0,f*0.8), str); painter->drawText(r.topLeft() + p + QPoint(pix.width()+f/2.0,f*1.0), str);
}
} }
}; };
@ -375,6 +374,9 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
mThreadProxyModel->setSortRole(RsGxsForumModel::SortRole); mThreadProxyModel->setSortRole(RsGxsForumModel::SortRole);
ui->threadTreeWidget->setModel(mThreadProxyModel); ui->threadTreeWidget->setModel(mThreadProxyModel);
mThreadProxyModel->setFilterRole(RsGxsForumModel::FilterRole);
mThreadProxyModel->setFilterRegExp(QRegExp(QString(RsGxsForumModel::FilterString))) ;
ui->threadTreeWidget->setSortingEnabled(true); ui->threadTreeWidget->setSortingEnabled(true);
//ui->threadTreeWidget->setDynamicSortFilter(true);// is that useful?? //ui->threadTreeWidget->setDynamicSortFilter(true);// is that useful??
@ -419,14 +421,6 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
itemDelegate->setOnlyPlainText(true); itemDelegate->setOnlyPlainText(true);
ui->threadTreeWidget->setItemDelegate(itemDelegate); ui->threadTreeWidget->setItemDelegate(itemDelegate);
float f = QFontMetricsF(font()).height()/14.0f ;
QHeaderView * ttheader = ui->threadTreeWidget->header () ;
ttheader->resizeSection (RsGxsForumModel::COLUMN_THREAD_DATE, 140*f);
ttheader->resizeSection (RsGxsForumModel::COLUMN_THREAD_TITLE, 440*f);
ttheader->resizeSection (RsGxsForumModel::COLUMN_THREAD_DISTRIBUTION, 24*f);
ttheader->resizeSection (RsGxsForumModel::COLUMN_THREAD_AUTHOR, 150*f);
#ifdef SUSPENDED_CODE #ifdef SUSPENDED_CODE
/* Set text of column "Read" to empty - without this the column has a number as header text */ /* Set text of column "Read" to empty - without this the column has a number as header text */
QTreeWidgetItem *headerItem = ui->threadTreeWidget->headerItem(); QTreeWidgetItem *headerItem = ui->threadTreeWidget->headerItem();
@ -449,16 +443,25 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
// load settings // load settings
processSettings(true); processSettings(true);
float f = QFontMetricsF(font()).height()/14.0f ;
/* Set header resize modes and initial section sizes */ /* Set header resize modes and initial section sizes */
QHeaderView * ttheader = ui->threadTreeWidget->header () ;
ttheader->resizeSection (RsGxsForumModel::COLUMN_THREAD_DATE, 140*f);
ttheader->resizeSection (RsGxsForumModel::COLUMN_THREAD_TITLE, 440*f);
ttheader->resizeSection (RsGxsForumModel::COLUMN_THREAD_DISTRIBUTION, 24*f);
ttheader->resizeSection (RsGxsForumModel::COLUMN_THREAD_AUTHOR, 150*f);
ttheader->resizeSection (RsGxsForumModel::COLUMN_THREAD_READ, 24*f);
QHeaderView_setSectionResizeModeColumn(ttheader, RsGxsForumModel::COLUMN_THREAD_TITLE, QHeaderView::Interactive); QHeaderView_setSectionResizeModeColumn(ttheader, RsGxsForumModel::COLUMN_THREAD_TITLE, QHeaderView::Interactive);
QHeaderView_setSectionResizeModeColumn(ttheader, RsGxsForumModel::COLUMN_THREAD_READ, QHeaderView::Fixed);
QHeaderView_setSectionResizeModeColumn(ttheader, RsGxsForumModel::COLUMN_THREAD_DATE, QHeaderView::Interactive); QHeaderView_setSectionResizeModeColumn(ttheader, RsGxsForumModel::COLUMN_THREAD_DATE, QHeaderView::Interactive);
QHeaderView_setSectionResizeModeColumn(ttheader, RsGxsForumModel::COLUMN_THREAD_DISTRIBUTION, QHeaderView::ResizeToContents);
QHeaderView_setSectionResizeModeColumn(ttheader, RsGxsForumModel::COLUMN_THREAD_AUTHOR, QHeaderView::Interactive); QHeaderView_setSectionResizeModeColumn(ttheader, RsGxsForumModel::COLUMN_THREAD_AUTHOR, QHeaderView::Interactive);
QHeaderView_setSectionResizeModeColumn(ttheader, RsGxsForumModel::COLUMN_THREAD_READ, QHeaderView::Fixed);
QHeaderView_setSectionResizeModeColumn(ttheader, RsGxsForumModel::COLUMN_THREAD_DISTRIBUTION, QHeaderView::Fixed);
ui->threadTreeWidget->header()->setCascadingSectionResizes(true); ui->threadTreeWidget->header()->setCascadingSectionResizes(true);
/* Set header sizes for the fixed columns and resize modes, must be set after processSettings */ /* Set header sizes for the fixed columns and resize modes, must be set after processSettings */
ttheader->resizeSection (RsGxsForumModel::COLUMN_THREAD_READ, 24*f);
ttheader->hideSection (RsGxsForumModel::COLUMN_THREAD_CONTENT); ttheader->hideSection (RsGxsForumModel::COLUMN_THREAD_CONTENT);
ttheader->hideSection (RsGxsForumModel::COLUMN_THREAD_MSGID); ttheader->hideSection (RsGxsForumModel::COLUMN_THREAD_MSGID);
ttheader->hideSection (RsGxsForumModel::COLUMN_THREAD_DATA); ttheader->hideSection (RsGxsForumModel::COLUMN_THREAD_DATA);
@ -2685,14 +2688,24 @@ void GxsForumThreadWidget::filterColumnChanged(int column)
void GxsForumThreadWidget::filterItems(const QString& text) void GxsForumThreadWidget::filterItems(const QString& text)
{ {
#ifdef TODO //FileSearchFlags flags = isRemote()?RS_FILE_HINTS_REMOTE:RS_FILE_HINTS_LOCAL;
QStringList lst = text.split(" ",QString::SkipEmptyParts) ;
std::list<std::string> keywords ;
for(auto it(lst.begin());it!=lst.end();++it)
keywords.push_back((*it).toStdString());
int filterColumn = ui->filterLineEdit->currentFilter(); int filterColumn = ui->filterLineEdit->currentFilter();
int count = ui->threadTreeWidget->topLevelItemCount(); mThreadModel->setFilter(filterColumn,keywords) ;
for (int index = 0; index < count; ++index) {
filterItem(ui->threadTreeWidget->topLevelItem(index), text, filterColumn); //if(found > 0)
} // expandAll();
#endif
//if(found == 0)
// ui.filterLineEdit->setToolTip(tr("No result.")) ;
//else
// ui.filterLineEdit->setToolTip(tr("Found %1 results.").arg(found)) ;
} }
bool GxsForumThreadWidget::filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn) bool GxsForumThreadWidget::filterItem(QTreeWidgetItem *item, const QString &text, int filterColumn)