This commit is contained in:
jolavillette 2026-08-29 15:51:37 +05:30 committed by GitHub
commit 9b226ec7ca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 150 additions and 6 deletions

View File

@ -43,7 +43,7 @@ std::ostream& operator<<(std::ostream& o, const QModelIndex& i);// defined elsew
const QString RsGxsForumModel::FilterString("filtered");
RsGxsForumModel::RsGxsForumModel(QObject *parent)
: QAbstractItemModel(parent), mUseChildTS(false),mFilteringEnabled(false),mTreeMode(TREE_MODE_TREE)
: QAbstractItemModel(parent), mUseChildTS(false),mFilteringEnabled(false),mContentFilteringEnabled(false),mTreeMode(TREE_MODE_TREE)
{
initEmptyHierarchy(mPosts);
mFont = QApplication::font();
@ -484,7 +484,22 @@ uint32_t RsGxsForumModel::recursUpdateFilterStatus(ForumModelIndex i,int column,
break;
}
if(!strings.empty())
if(mContentFilteringEnabled)
{
bool found = (mContentFilterIds.find(mPosts[i].mMsgId) != mContentFilterIds.end());
if (mPosts[i].mMsgId.isNull()) found = false; // dummy root
if(found)
{
mPosts[i].mPostFlags |= ForumModelPostEntry::FLAG_POST_PASSES_FILTER | ForumModelPostEntry::FLAG_POST_CHILDREN_PASSES_FILTER;
count++;
}
else
{
mPosts[i].mPostFlags &= ~(ForumModelPostEntry::FLAG_POST_PASSES_FILTER | ForumModelPostEntry::FLAG_POST_CHILDREN_PASSES_FILTER);
}
}
else if(!strings.empty())
{
mPosts[i].mPostFlags &= ~(ForumModelPostEntry::FLAG_POST_PASSES_FILTER | ForumModelPostEntry::FLAG_POST_CHILDREN_PASSES_FILTER);
@ -520,6 +535,10 @@ void RsGxsForumModel::setFilter(int column,const QStringList& strings,uint32_t&
{
preMods();
if (column != COLUMN_THREAD_CONTENT) {
mContentFilteringEnabled = false;
}
if(!strings.empty())
{
count = recursUpdateFilterStatus(ForumModelIndex(0),column,strings);
@ -1104,3 +1123,9 @@ void RsGxsForumModel::setAuthorOpinion(const QModelIndex& indx, RsOpinion op)
emit dataChanged(createIndex(0,0,(void*)NULL), createIndex(0,COLUMN_THREAD_NB_COLUMNS-1,(void*)NULL));
}
}
void RsGxsForumModel::setContentFilter(const std::set<RsGxsMessageId>& ids, const QStringList& filterStrings, uint32_t& count)
{
mContentFilteringEnabled = true;
mContentFilterIds = ids;
setFilter(COLUMN_THREAD_CONTENT, filterStrings, count);
}

View File

@ -99,7 +99,9 @@ public:
void setBackgroundColorFiltered (QColor color) { mBackgroundColorFiltered = color;}
void setMsgReadStatus(const QModelIndex &i, bool read_status, bool with_children);
// Filter methods
void setFilter(int column, const QStringList &strings, uint32_t &count) ;
void setContentFilter(const std::set<RsGxsMessageId>& ids, const QStringList& filterStrings, uint32_t& count);
void setAuthorOpinion(const QModelIndex& indx,RsOpinion op);
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
@ -146,6 +148,8 @@ private:
bool mUseChildTS;
bool mFilteringEnabled;
bool mContentFilteringEnabled;
std::set<RsGxsMessageId> mContentFilterIds;
TreeMode mTreeMode;
SortMode mSortMode;

View File

@ -47,6 +47,7 @@
#include "gui/common/UIStateHelper.h"
#include "util/RsQtVersion.h"
#include "util/imageutil.h"
#include "util/rsdebug.h"
#include <retroshare/rsgxsforums.h>
#include <retroshare/rsgxscircles.h>
@ -253,6 +254,12 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
ui(new Ui::GxsForumThreadWidget)
{
ui->setupUi(this);
RsDbg() << "DEEPSEARCH: GxsForumThreadWidget created for forumId=" << forumId.toStdString();
#ifdef RS_DEEP_FORUMS_INDEX
RsDbg() << "DEEPSEARCH: RS_DEEP_FORUMS_INDEX IS defined in GxsForumThreadWidget";
#else
RsDbg() << "DEEPSEARCH: RS_DEEP_FORUMS_INDEX IS NOT defined in GxsForumThreadWidget !!!";
#endif
// Single-shot timer used to coalesce the full-forum reloads requested by
// incoming GXS events (see scheduleForumReload()). Created first thing:
@ -264,6 +271,7 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
//setUpdateWhenInvisible(true);
//mUpdating = false;
mForceSearch = false;
mUnreadCount = 0;
mNewCount = 0;
@ -312,6 +320,7 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
connect(ui->downloadButton, SIGNAL(clicked()), this, SLOT(downloadAllFiles()));
connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString)));
connect(ui->filterLineEdit, SIGNAL(returnPressed()), this, SLOT(triggerSearch()));
connect(ui->filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterColumnChanged(int)));
connect(ui->threadedView_TB, SIGNAL(toggled(bool)), this, SLOT(toggleThreadedView(bool)));
@ -328,6 +337,9 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget
ui->filterLineEdit->addFilter(QIcon(), tr("Title"), RsGxsForumModel::COLUMN_THREAD_TITLE, tr("Search Title"));
ui->filterLineEdit->addFilter(QIcon(), tr("Date"), RsGxsForumModel::COLUMN_THREAD_DATE, tr("Search Date"));
ui->filterLineEdit->addFilter(QIcon(), tr("Author"), RsGxsForumModel::COLUMN_THREAD_AUTHOR, tr("Search Author"));
#ifdef RS_DEEP_FORUMS_INDEX
ui->filterLineEdit->addFilter(QIcon(), tr("Content"), RsGxsForumModel::COLUMN_THREAD_CONTENT, tr("Search Content"));
#endif
mLastViewType = -1;
@ -1852,7 +1864,9 @@ void GxsForumThreadWidget::changedViewBox(int view_mode)
void GxsForumThreadWidget::filterColumnChanged(int column)
{
filterItems(ui->filterLineEdit->text());
// Search is NEVER auto-triggered on column change.
// User must explicitly press 'Enter' or search button.
RsDbg() << "DEEPSEARCH: Filter column changed to " << column << ". Waiting for 'Enter'.";
// save index
Settings->setValueToGroup("ForumThreadWidget", "filterColumn", column);
@ -1860,12 +1874,49 @@ void GxsForumThreadWidget::filterColumnChanged(int column)
void GxsForumThreadWidget::filterItems(const QString& text)
{
QStringList lst = text.split(" ",QtSkipEmptyParts) ;
// ALL searches (Title, Author, Content) now require 'Enter' to avoid UI freeze/flicker
if (!text.isEmpty() && !mForceSearch)
{
// STRICT BLOCK: No logs, no processing during typing for ALL columns.
return;
}
int filterColumn = ui->filterLineEdit->currentFilter();
RsDbg() << "DEEPSEARCH: executing filterItems('" << text.toStdString() << "') column=" << filterColumn << " force=" << (mForceSearch?"YES":"NO");
QStringList lst = text.split(" ",QtSkipEmptyParts) ;
uint32_t count;
mThreadModel->setFilter(filterColumn,lst,count) ;
if(filterColumn == RsGxsForumModel::COLUMN_THREAD_CONTENT && !lst.empty())
{
RsDbg() << "DEEPSEARCH: executing Content Search for '" << text.toStdString() << "'";
// Clear current selection to avoid "lag" when clicking results
mThreadId = RsGxsMessageId();
blankPost();
insertMessage(); // Will display forum description if mThreadId is null
std::set<RsGxsMessageId> ids;
std::vector<RsGxsSearchResult> results;
#ifdef RS_DEEP_FORUMS_INDEX
rsGxsForums->localSearch(text.toStdString(), results);
RsDbg() << "DEEPSEARCH: Content Search returned " << results.size() << " results.";
for(const auto& res : results) {
if(res.mGroupId == groupId() && !res.mMsgId.isNull()) {
ids.insert(res.mMsgId);
}
}
RsDbg() << "DEEPSEARCH: Content Search matched " << ids.size() << " messages in current group (" << groupId().toStdString() << ")";
#endif
mThreadModel->setContentFilter(ids, lst, count);
}
else
{
RsDbg() << "DEEPSEARCH: executing Regular Search/Clear in column " << filterColumn;
// Regular search or cleared search: use standard setFilter which disables content mode
mThreadModel->setFilter(filterColumn, lst, count);
}
// We do this in order to trigger a new filtering action in the proxy model.
QSortFilterProxyModel_setFilterRegularExpression(mThreadProxyModel, QString(RsGxsForumModel::FilterString)) ;
@ -1912,7 +1963,7 @@ void GxsForumThreadWidget::filterItems(const QString& text)
}
}
if(count > 0)
if(count == 0 && !text.isEmpty())
ui->filterLineEdit->setToolTip(tr("No result.")) ;
else
ui->filterLineEdit->setToolTip(tr("Found %1 results.").arg(count)) ;
@ -2155,3 +2206,12 @@ void GxsForumThreadWidget::showAuthorInPeople(const RsGxsForumMsg& msg)
MainWindow::showWindow(MainWindow::People);
idDialog->navigate(RsGxsId(msg.mMeta.mAuthorId));
}
void GxsForumThreadWidget::triggerSearch()
{
RsDbg() << "DEEPSEARCH: triggerSearch() called. Text='" << ui->filterLineEdit->text().toStdString() << "'";
mForceSearch = true;
filterItems(ui->filterLineEdit->text());
mForceSearch = false;
RsDbg() << "DEEPSEARCH: triggerSearch() finished.";
}

View File

@ -161,6 +161,7 @@ private slots:
void filterColumnChanged(int column);
void filterItems(const QString &text);
void triggerSearch();
#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
void expandSubtree();
@ -223,6 +224,7 @@ private:
unsigned int mUnreadCount;
unsigned int mNewCount;
bool mDisplayBannedText;
bool mForceSearch;
/* Color definitions (for standard see default.qss) */
QColor mTextColorRead;

View File

@ -18,6 +18,9 @@
* *
*******************************************************************************/
#include <QToolButton>
#include <QMessageBox>
#include "ui_GxsGroupFrameDialog.h"
#include "GxsForumsDialog.h"
#include "GxsForumGroupDialog.h"
#include "GxsForumThreadWidget.h"

View File

@ -18,6 +18,10 @@
* *
*******************************************************************************/
#include <iostream>
#include <QPushButton>
#include <QMessageBox>
#include "retroshare/rsgxsforums.h"
#include "ForumPage.h"
#include "util/misc.h"
#include "rsharesettings.h"
@ -39,6 +43,49 @@ ForumPage::ForumPage(QWidget * parent, Qt::WindowFlags flags)
connect(ui.minimumContrast , SIGNAL(valueChanged(int)), this, SLOT(updateFonts()));
ui.groupFrameSettingsWidget->setType(GroupFrameSettings::Forum) ;
#ifdef RS_DEEP_FORUMS_INDEX
// Add Re-index button
QPushButton *reindexBtn = new QPushButton(tr("Re-index Content"), this);
reindexBtn->setToolTip(tr("Re-index all forums content for search. This may take a while."));
connect(reindexBtn, SIGNAL(clicked()), this, SLOT(reindexAll()));
// Add to the layout. The UI is widget based.
// Let's add it to the vertical layout of the page.
if(layout()) {
layout()->addWidget(reindexBtn);
} else {
// Fallback if no main layout (should exist from setupUi)
// ui.verticalLayout seems to be the main layout usually.
// Checking ForumPage.ui would be best but let's assume verticalLayout exists or try to add to 'this' layout.
// Actually, setupUi usually creates a layout on the widget.
// Let's check if we can access the layout via QWidget::layout()
if(!layout()) {
QVBoxLayout *l = new QVBoxLayout(this);
l->addWidget(reindexBtn);
} else {
// If it's a grid or something else, addWidget might fail if signatures differ, but usually OK for VBox/HBox/Grid.
// Safer to put it in a specific container if possible.
// ui.scrollAreaWidgetContents is common.
// For now, let's append to the main layout.
qobject_cast<QBoxLayout*>(layout())->addWidget(reindexBtn);
}
}
#endif
}
void ForumPage::reindexAll()
{
#ifdef RS_DEEP_FORUMS_INDEX
if(QMessageBox::question(this, tr("Re-index Forums"),
tr("Are you sure you want to re-index all forum content?\nThis may take some time depending on the number of messages."),
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
{
RsDbg() << "DEEPSEARCH: Requesting full re-indexing from GUI Preferences.";
rsGxsForums->reindexAll();
QMessageBox::information(this, tr("Re-index Forums"), tr("Re-indexing Completed Successfully!"));
}
#endif
}
ForumPage::~ForumPage()

View File

@ -48,6 +48,8 @@ protected slots:
private slots:
void updateFonts();
void reindexAll();
private:
Ui::ForumPage ui;

View File

@ -36,6 +36,7 @@ no_retroshare_gui:CONFIG -= retroshare_gui
#CONFIG *= gxsthewire
# Enable GXS distant syncronization
CONFIG += rs_deep_forums_index
CONFIG *= gxsdistsync
# To enable cmark append the following