diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp index f55bbb0c0..a7de911c9 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "util/qtthreadsutils.h" #include "util/misc.h" @@ -374,6 +375,12 @@ GxsForumThreadWidget::GxsForumThreadWidget(const RsGxsGroupId &forumId, QWidget ui->threadTreeWidget->enableColumnCustomize(true); #endif + // Single-shot timer used to coalesce the full-forum reloads requested by + // incoming GXS events (see scheduleForumReload()). + mDeferredReloadTimer = new QTimer(this); + mDeferredReloadTimer->setSingleShot(true); + connect(mDeferredReloadTimer, &QTimer::timeout, this, [this]() { updateDisplay(true); }); + mEventHandlerId = 0; // Needs to be asynced because this function is called by another thread! rsEvents->registerEventsHandler( @@ -402,7 +409,7 @@ void GxsForumThreadWidget::handleEvent_main_thread(std::shared_ptrmForumGroupId == mForumGroup.mMeta.mGroupId) - updateDisplay(true); + scheduleForumReload(); break; case RsForumEventCode::SUBSCRIBE_STATUS_CHANGED: @@ -424,6 +431,16 @@ void GxsForumThreadWidget::handleEvent_main_thread(std::shared_ptrstart(300); +} + void GxsForumThreadWidget::showForumInfo() { mThreadId.clear(); @@ -596,6 +613,10 @@ void GxsForumThreadWidget::updateDisplay(bool complete) } if(complete) // need to update the group data, reload the messages etc. { + // We are reloading now, so drop any reload still pending in the coalescing + // timer (e.g. queued by events for a forum we just switched away from). + mDeferredReloadTimer->stop(); + saveExpandedItems(mSavedExpandedMessages); if(groupId() != mThreadModel->currentGroupId()) diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h index 8e6b1c01b..130f70bd0 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h +++ b/retroshare-gui/src/gui/gxsforums/GxsForumThreadWidget.h @@ -29,6 +29,7 @@ #include "util/FontSizeHandler.h" class QSortFilterProxyModel; +class QTimer; class QTreeWidgetItem; class RSTreeWidgetItemCompareRole; class GxsForumsFillThread; @@ -197,6 +198,13 @@ private: void handleEvent_main_thread(std::shared_ptr event); + // Coalesce the full-forum reloads triggered by incoming GXS events: a sync + // burst delivers many NEW_MESSAGE events in a row, and reloading the whole + // forum for each one froze the UI for seconds and reset the model out from + // under the user's selection. Restart a single-shot timer instead so a burst + // results in one reload once the events settle. + void scheduleForumReload(); + private: void setForumDescriptionLoading(); void clearForumDescription(); @@ -239,6 +247,8 @@ private: Ui::GxsForumThreadWidget *ui; RsEventsHandlerId_t mEventHandlerId; + + QTimer *mDeferredReloadTimer; }; #endif // GXSFORUMTHREADWIDGET_H