Added threaded loading of channel posts.

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@7480 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
thunder2 2014-08-01 18:54:55 +00:00
parent 2d2e3881cf
commit 7a65ad1a14
9 changed files with 277 additions and 63 deletions

View File

@ -49,6 +49,10 @@ PostedListWidget::PostedListWidget(const RsGxsGroupId &postedId, QWidget *parent
mStateHelper->addWidget(mTokenTypePosts, ui->newSortButton);
mStateHelper->addWidget(mTokenTypePosts, ui->topSortButton);
mStateHelper->addWidget(mTokenTypeRelatedPosts, ui->hotSortButton);
mStateHelper->addWidget(mTokenTypeRelatedPosts, ui->newSortButton);
mStateHelper->addWidget(mTokenTypeRelatedPosts, ui->topSortButton);
mStateHelper->addWidget(mTokenTypeGroupData, ui->submitPostButton);
mStateHelper->addWidget(mTokenTypeGroupData, ui->subscribeToolButton);
@ -532,7 +536,7 @@ bool PostedListWidget::insertGroupData(const uint32_t &token, RsGroupMetaData &m
return false;
}
void PostedListWidget::insertPosts(const uint32_t &token)
void PostedListWidget::insertPosts(const uint32_t &token, GxsMessageFramePostThread */*thread*/)
{
std::vector<RsPostedPost> posts;
rsPosted->getPostData(token, posts);

View File

@ -61,7 +61,7 @@ public:
protected:
/* GxsMessageFramePostWidget */
virtual bool insertGroupData(const uint32_t &token, RsGroupMetaData &metaData);
virtual void insertPosts(const uint32_t &token);
virtual void insertPosts(const uint32_t &token, GxsMessageFramePostThread *thread);
virtual void insertRelatedPosts(const uint32_t &token);
virtual void clearPosts();

View File

@ -22,6 +22,7 @@
#include <QLabel>
#include <QWidget>
#include <QLineEdit>
#include <QProgressBar>
#include "UIStateHelper.h"
#include "RSTreeWidget.h"
@ -441,7 +442,16 @@ void UIStateHelper::updateData(UIStateHelperData *data)
UIStates states = it.value();
if (states & (UISTATE_LOADING_VISIBLE | UISTATE_LOADING_INVISIBLE | UISTATE_ACTIVE_VISIBLE | UISTATE_ACTIVE_INVISIBLE)) {
widget->setVisible(isWidgetVisible(widget));
bool visible = isWidgetVisible(widget);
widget->setVisible(visible);
if (!visible) {
/* Reset progressbar */
QProgressBar *progressBar = dynamic_cast<QProgressBar*>(widget);
if (progressBar) {
progressBar->setValue(0);
}
}
}
if (states & (UISTATE_LOADING_ENABLED | UISTATE_LOADING_DISABLED | UISTATE_ACTIVE_ENABLED | UISTATE_ACTIVE_DISABLED)) {

View File

@ -19,6 +19,8 @@
* Boston, MA 02110-1301, USA.
****************************************************************/
#include <QApplication>
#include "GxsMessageFramePostWidget.h"
#include "GxsFeedItem.h"
#include "gui/common/UIStateHelper.h"
@ -34,6 +36,7 @@ GxsMessageFramePostWidget::GxsMessageFramePostWidget(RsGxsIfaceHelper *ifaceImpl
mSubscribeFlags = 0;
mNextTokenType = 0;
mFillThread = NULL;
mTokenTypeGroupData = nextTokenType();
mTokenTypePosts = nextTokenType();
@ -43,6 +46,15 @@ GxsMessageFramePostWidget::GxsMessageFramePostWidget(RsGxsIfaceHelper *ifaceImpl
mStateHelper = new UIStateHelper(this);
}
GxsMessageFramePostWidget::~GxsMessageFramePostWidget()
{
if (mFillThread) {
mFillThread->stop(true);
delete(mFillThread);
mFillThread = NULL;
}
}
void GxsMessageFramePostWidget::setGroupId(const RsGxsGroupId &groupId)
{
if (mGroupId == groupId) {
@ -116,6 +128,50 @@ void GxsMessageFramePostWidget::updateDisplay(bool complete)
}
}
void GxsMessageFramePostWidget::fillThreadAddPost(const QVariant &post, bool related, int current, int count)
{
if (sender() == mFillThread) {
fillThreadCreatePost(post, related, current, count);
}
}
void GxsMessageFramePostWidget::fillThreadFinished()
{
#ifdef ENABLE_DEBUG
std::cerr << "GxsMessageFramePostWidget::fillThreadFinished()" << std::endl;
#endif
/* Thread has finished */
GxsMessageFramePostThread *thread = dynamic_cast<GxsMessageFramePostThread*>(sender());
if (thread) {
if (thread == mFillThread) {
/* Current thread has finished */
mFillThread = NULL;
mStateHelper->setLoading(mTokenTypePosts, false);
emit groupChanged(this);
}
#ifdef ENABLE_DEBUG
if (thread->stopped()) {
// thread was stopped
std::cerr << "GxsMessageFramePostWidget::fillThreadFinished() Thread was stopped" << std::endl;
}
#endif
#ifdef ENABLE_DEBUG
std::cerr << "GxsMessageFramePostWidget::fillThreadFinished() Delete thread" << std::endl;
#endif
thread->deleteLater();
thread = NULL;
}
#ifdef ENABLE_DEBUG
std::cerr << "GxsMessageFramePostWidget::fillThreadFinished done()" << std::endl;
#endif
}
/**************************************************************/
/** Request / Response of Data ********************************/
/**************************************************************/
@ -197,10 +253,20 @@ void GxsMessageFramePostWidget::requestPosts()
#endif
/* Request all posts */
clearPosts();
mTokenQueue->cancelActiveRequestTokens(mTokenTypePosts);
if (mFillThread) {
/* Stop current fill thread */
GxsMessageFramePostThread *thread = mFillThread;
mFillThread = NULL;
thread->stop(false);
mStateHelper->setLoading(mTokenTypePosts, false);
}
clearPosts();
if (mGroupId.isNull()) {
mStateHelper->setActive(mTokenTypePosts, false);
mStateHelper->setLoading(mTokenTypePosts, false);
@ -231,9 +297,26 @@ void GxsMessageFramePostWidget::loadPosts(const uint32_t &token)
mStateHelper->setActive(mTokenTypePosts, true);
insertPosts(token);
if (useThread()) {
/* Create fill thread */
mFillThread = new GxsMessageFramePostThread(token, this);
// connect thread
connect(mFillThread, SIGNAL(finished()), this, SLOT(fillThreadFinished()), Qt::BlockingQueuedConnection);
connect(mFillThread, SIGNAL(addPost(QVariant,bool,int,int)), this, SLOT(fillThreadAddPost(QVariant,bool,int,int)), Qt::BlockingQueuedConnection);
#ifdef ENABLE_DEBUG
std::cerr << "GxsMessageFramePostWidget::loadPosts() Start fill thread" << std::endl;
#endif
/* Start thread */
mFillThread->start();
} else {
insertPosts(token, NULL);
mStateHelper->setLoading(mTokenTypePosts, false);
}
mStateHelper->setLoading(mTokenTypePosts, false);
emit groupChanged(this);
}
@ -247,9 +330,9 @@ void GxsMessageFramePostWidget::requestRelatedPosts(const std::vector<RsGxsMessa
mTokenQueue->cancelActiveRequestTokens(mTokenTypeRelatedPosts);
if (mGroupId.isNull()) {
mStateHelper->setActive(mTokenTypePosts, false);
mStateHelper->setLoading(mTokenTypePosts, false);
mStateHelper->clear(mTokenTypePosts);
mStateHelper->setActive(mTokenTypeRelatedPosts, false);
mStateHelper->setLoading(mTokenTypeRelatedPosts, false);
mStateHelper->clear(mTokenTypeRelatedPosts);
emit groupChanged(this);
return;
}
@ -258,7 +341,7 @@ void GxsMessageFramePostWidget::requestRelatedPosts(const std::vector<RsGxsMessa
return;
}
mStateHelper->setLoading(mTokenTypePosts, true);
mStateHelper->setLoading(mTokenTypeRelatedPosts, true);
emit groupChanged(this);
RsTokReqOptions opts;
@ -280,11 +363,11 @@ void GxsMessageFramePostWidget::loadRelatedPosts(const uint32_t &token)
std::cerr << std::endl;
#endif
mStateHelper->setActive(mTokenTypePosts, true);
mStateHelper->setActive(mTokenTypeRelatedPosts, true);
insertRelatedPosts(token);
mStateHelper->setLoading(mTokenTypePosts, false);
mStateHelper->setLoading(mTokenTypeRelatedPosts, false);
emit groupChanged(this);
}
@ -309,3 +392,52 @@ void GxsMessageFramePostWidget::loadRequest(const TokenQueue *queue, const Token
}
}
}
/**************************************************************/
/** GxsMessageFramePostThread *********************************/
/**************************************************************/
GxsMessageFramePostThread::GxsMessageFramePostThread(uint32_t token, GxsMessageFramePostWidget *parent)
: QThread(parent), mToken(token), mParent(parent)
{
mStopped = false;
}
GxsMessageFramePostThread::~GxsMessageFramePostThread()
{
#ifdef ENABLE_DEBUG
std::cerr << "GxsMessageFramePostThread::~GxsMessageFramePostThread" << std::endl;
#endif
}
void GxsMessageFramePostThread::stop(bool waitForStop)
{
if (waitForStop) {
disconnect();
}
mStopped = true;
QApplication::processEvents();
if (waitForStop) {
wait();
}
}
void GxsMessageFramePostThread::run()
{
#ifdef ENABLE_DEBUG
std::cerr << "GxsMessageFramePostThread::run()" << std::endl;
#endif
mParent->insertPosts(mToken, this);
#ifdef ENABLE_DEBUG
std::cerr << "GxsMessageFramePostThread::run() stopped: " << (stopped() ? "yes" : "no") << std::endl;
#endif
}
void GxsMessageFramePostThread::emitAddPost(const QVariant &post, bool related, int current, int count)
{
emit addPost(post, related, current, count);
}

View File

@ -22,18 +22,24 @@
#ifndef GXSMESSAGEFRAMEPOSTWIDGET_H
#define GXSMESSAGEFRAMEPOSTWIDGET_H
#include <QThread>
#include "GxsMessageFrameWidget.h"
#include "util/TokenQueue.h"
class GxsFeedItem;
class UIStateHelper;
class GxsMessageFramePostThread;
class GxsMessageFramePostWidget : public GxsMessageFrameWidget, public TokenResponse
{
Q_OBJECT
friend class GxsMessageFramePostThread;
public:
explicit GxsMessageFramePostWidget(RsGxsIfaceHelper *ifaceImpl, QWidget *parent = NULL);
virtual ~GxsMessageFramePostWidget();
/* GxsMessageFrameWidget */
virtual RsGxsGroupId groupId();
@ -53,6 +59,10 @@ protected:
virtual void clearPosts() = 0;
/* Thread functions */
virtual bool useThread() { return false; }
virtual void fillThreadCreatePost(const QVariant &/*post*/, bool /*related*/, int /*current*/, int /*count*/) {}
/* GXS functions */
void requestGroupData();
void loadGroupData(const uint32_t &token);
@ -60,12 +70,16 @@ protected:
void requestPosts();
void loadPosts(const uint32_t &token);
virtual void insertPosts(const uint32_t &token) = 0;
virtual void insertPosts(const uint32_t &token, GxsMessageFramePostThread *thread) = 0;
void requestRelatedPosts(const std::vector<RsGxsMessageId> &msgIds);
void loadRelatedPosts(const uint32_t &token);
virtual void insertRelatedPosts(const uint32_t &token) = 0;
private slots:
void fillThreadFinished();
void fillThreadAddPost(const QVariant &post, bool related, int current, int count);
protected:
TokenQueue *mTokenQueue;
uint32_t mTokenTypeGroupData;
@ -78,6 +92,30 @@ private:
QString mGroupName;
int mSubscribeFlags;
uint32_t mNextTokenType;
GxsMessageFramePostThread *mFillThread;
};
class GxsMessageFramePostThread : public QThread
{
Q_OBJECT
public:
GxsMessageFramePostThread(uint32_t token, GxsMessageFramePostWidget *parent);
~GxsMessageFramePostThread();
void run();
void stop(bool waitForStop);
bool stopped() { return mStopped; }
void emitAddPost(const QVariant &post, bool related, int current, int count);
signals:
void addPost(const QVariant &post, bool related, int current, int count);
private:
uint32_t mToken;
GxsMessageFramePostWidget *mParent;
volatile bool mStopped;
};
#endif // GXSMESSAGEFRAMEPOSTWIDGET_H

View File

@ -52,7 +52,6 @@ QString GxsChannelDialog::text(TextType type)
return tr("Create Channel");
case TEXT_TODO:
return "<b>Open points:</b><ul>"
"<li>Threaded load of messages"
"<li>Share key"
"<li>Restore channel keys"
"<li>Navigate channel link"

View File

@ -57,10 +57,10 @@ GxsChannelPostsWidget::GxsChannelPostsWidget(const RsGxsGroupId &channelId, QWid
/* Setup UI helper */
// No progress yet
mStateHelper->addWidget(mTokenTypePosts, ui->loadingLabel, UISTATE_LOADING_VISIBLE);
// mStateHelper->addWidget(mTokenTypePosts, ui->progressBar, UISTATE_LOADING_VISIBLE);
// mStateHelper->addWidget(mTokenTypePosts, ui->progressLabel, UISTATE_LOADING_VISIBLE);
mStateHelper->addWidget(mTokenTypePosts, ui->progressBar, UISTATE_LOADING_VISIBLE);
mStateHelper->addWidget(mTokenTypePosts, ui->filterLineEdit);
mStateHelper->addWidget(mTokenTypeRelatedPosts, ui->loadingLabel, UISTATE_LOADING_VISIBLE);
mStateHelper->addLoadPlaceholder(mTokenTypeGroupData, ui->nameLabel);
@ -81,7 +81,6 @@ GxsChannelPostsWidget::GxsChannelPostsWidget(const RsGxsGroupId &channelId, QWid
/*************** Setup Left Hand Side (List of Channels) ****************/
ui->loadingLabel->hide();
ui->progressLabel->hide();
ui->progressBar->hide();
ui->nameLabel->setMinimumWidth(20);
@ -271,33 +270,69 @@ void GxsChannelPostsWidget::filterChanged(int filter)
return bVisible;
}
void GxsChannelPostsWidget::insertChannelPosts(std::vector<RsGxsChannelPost> &posts, bool related)
void GxsChannelPostsWidget::createPostItem(const RsGxsChannelPost &post, bool related)
{
GxsChannelPostItem *item = NULL;
if (related) {
FeedItem *feedItem = ui->feedWidget->findGxsFeedItem(post.mMeta.mGroupId, post.mMeta.mMsgId);
item = dynamic_cast<GxsChannelPostItem*>(feedItem);
}
if (item) {
item->setContent(post);
ui->feedWidget->setSort(item, ROLE_PUBLISH, QDateTime::fromTime_t(post.mMeta.mPublishTs));
} else {
uint32_t subscribeFlags = 0xffffffff;
GxsChannelPostItem *item = new GxsChannelPostItem(this, 0, post, subscribeFlags, true, false);
ui->feedWidget->addFeedItem(item, ROLE_PUBLISH, QDateTime::fromTime_t(post.mMeta.mPublishTs));
}
}
void GxsChannelPostsWidget::fillThreadCreatePost(const QVariant &post, bool related, int current, int count)
{
/* show fill progress */
if (count) {
ui->progressBar->setValue(current * ui->progressBar->maximum() / count);
}
if (!post.canConvert<RsGxsChannelPost>()) {
return;
}
createPostItem(post.value<RsGxsChannelPost>(), related);
}
void GxsChannelPostsWidget::insertChannelPosts(std::vector<RsGxsChannelPost> &posts, GxsMessageFramePostThread *thread, bool related)
{
if (related && thread) {
std::cerr << "GxsChannelPostsWidget::insertChannelPosts fill only related posts as thread is not possible" << std::endl;
return;
}
std::vector<RsGxsChannelPost>::const_iterator it;
uint32_t subscribeFlags = 0xffffffff;
int count = posts.size();
int pos = 0;
ui->feedWidget->setSortingEnabled(false);
if (!thread) {
ui->feedWidget->setSortingEnabled(false);
}
for (it = posts.begin(); it != posts.end(); it++)
{
const RsGxsChannelPost &msg = *it;
GxsChannelPostItem *item = NULL;
if (related) {
FeedItem *feedItem = ui->feedWidget->findGxsFeedItem(msg.mMeta.mGroupId, msg.mMeta.mMsgId);
item = dynamic_cast<GxsChannelPostItem*>(feedItem);
if (thread && thread->stopped()) {
break;
}
if (item) {
item->setContent(*it);
//TODO: Sort timestamp
if (thread) {
thread->emitAddPost(qVariantFromValue(*it), related, ++pos, count);
} else {
item = new GxsChannelPostItem(this, 0, *it, subscribeFlags, true, false);
ui->feedWidget->addFeedItem(item, ROLE_PUBLISH, QDateTime::fromTime_t(msg.mMeta.mPublishTs));
createPostItem(*it, related);
}
}
ui->feedWidget->setSortingEnabled(true);
if (!thread) {
ui->feedWidget->setSortingEnabled(true);
}
}
void GxsChannelPostsWidget::clearPosts()
@ -352,12 +387,12 @@ bool GxsChannelPostsWidget::insertGroupData(const uint32_t &token, RsGroupMetaDa
return false;
}
void GxsChannelPostsWidget::insertPosts(const uint32_t &token)
void GxsChannelPostsWidget::insertPosts(const uint32_t &token, GxsMessageFramePostThread *thread)
{
std::vector<RsGxsChannelPost> posts;
rsGxsChannels->getPostData(token, posts);
insertChannelPosts(posts, false);
insertChannelPosts(posts, thread, false);
}
void GxsChannelPostsWidget::insertRelatedPosts(const uint32_t &token)
@ -365,7 +400,7 @@ void GxsChannelPostsWidget::insertRelatedPosts(const uint32_t &token)
std::vector<RsGxsChannelPost> posts;
rsGxsChannels->getRelatedPosts(token, posts);
insertChannelPosts(posts, true);
insertChannelPosts(posts, NULL, true);
}
static void setAllMessagesReadCallback(FeedItem *feedItem, const QVariant &data)

View File

@ -60,9 +60,11 @@ protected:
/* GxsMessageFramePostWidget */
virtual void groupNameChanged(const QString &name);
virtual bool insertGroupData(const uint32_t &token, RsGroupMetaData &metaData);
virtual void insertPosts(const uint32_t &token);
virtual void insertPosts(const uint32_t &token, GxsMessageFramePostThread *thread);
virtual void insertRelatedPosts(const uint32_t &token);
virtual void clearPosts();
virtual bool useThread() { return true; }
virtual void fillThreadCreatePost(const QVariant &post, bool related, int current, int count);
private slots:
void createMsg();
@ -70,9 +72,6 @@ private slots:
void subscribeGroup(bool subscribe);
void filterChanged(int filter);
//void fillThreadFinished();
//void fillThreadAddMsg(const QString &channelId, const QString &channelMsgId, int current, int count);
private:
void processSettings(bool load);
@ -80,7 +79,9 @@ private:
static bool filterItem(FeedItem *feedItem, const QString &text, int filter);
void insertChannelDetails(const RsGxsChannelGroup &group);
void insertChannelPosts(std::vector<RsGxsChannelPost> &posts, bool related);
void insertChannelPosts(std::vector<RsGxsChannelPost> &posts, GxsMessageFramePostThread *thread, bool related);
void createPostItem(const RsGxsChannelPost &post, bool related);
private:
QAction *mAutoDownloadAction;

View File

@ -177,6 +177,22 @@
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>10</height>
</size>
</property>
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="LineEditClear" name="filterLineEdit">
<property name="sizePolicy">
@ -208,27 +224,6 @@
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="progressLayout">
<item>
<widget class="QLabel" name="progressLabel">
<property name="text">
<string>Loading</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="progressBar">
<property name="maximum">
<number>1000</number>
</property>
<property name="value">
<number>24</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="RSFeedWidget" name="feedWidget" native="true">
<property name="sizePolicy">