diff --git a/retroshare-gui/src/gui/Posted/PostedListWidget.cpp b/retroshare-gui/src/gui/Posted/PostedListWidget.cpp index 4e1ee6116..34141cc7e 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidget.cpp +++ b/retroshare-gui/src/gui/Posted/PostedListWidget.cpp @@ -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 posts; rsPosted->getPostData(token, posts); diff --git a/retroshare-gui/src/gui/Posted/PostedListWidget.h b/retroshare-gui/src/gui/Posted/PostedListWidget.h index af848a0d9..6de6db548 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidget.h +++ b/retroshare-gui/src/gui/Posted/PostedListWidget.h @@ -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(); diff --git a/retroshare-gui/src/gui/common/UIStateHelper.cpp b/retroshare-gui/src/gui/common/UIStateHelper.cpp index 0e2226dc7..d27b21fae 100644 --- a/retroshare-gui/src/gui/common/UIStateHelper.cpp +++ b/retroshare-gui/src/gui/common/UIStateHelper.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #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(widget); + if (progressBar) { + progressBar->setValue(0); + } + } } if (states & (UISTATE_LOADING_ENABLED | UISTATE_LOADING_DISABLED | UISTATE_ACTIVE_ENABLED | UISTATE_ACTIVE_DISABLED)) { diff --git a/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.cpp b/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.cpp index 7a4ebc35b..4e42cb907 100644 --- a/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.cpp +++ b/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.cpp @@ -19,6 +19,8 @@ * Boston, MA 02110-1301, USA. ****************************************************************/ +#include + #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(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::vectorcancelActiveRequestTokens(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::vectorsetLoading(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); +} diff --git a/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.h b/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.h index 9f4c19016..3938a5538 100644 --- a/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.h +++ b/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.h @@ -22,18 +22,24 @@ #ifndef GXSMESSAGEFRAMEPOSTWIDGET_H #define GXSMESSAGEFRAMEPOSTWIDGET_H +#include + #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 &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 diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp index 4b7189b6d..ce85c8650 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp @@ -52,7 +52,6 @@ QString GxsChannelDialog::text(TextType type) return tr("Create Channel"); case TEXT_TODO: return "Open points:
    " - "
  • Threaded load of messages" "
  • Share key" "
  • Restore channel keys" "
  • Navigate channel link" diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.cpp index b5b1ca80d..ba00b8784 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.cpp @@ -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 &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(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()) { + return; + } + + createPostItem(post.value(), related); +} + +void GxsChannelPostsWidget::insertChannelPosts(std::vector &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::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(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 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 posts; rsGxsChannels->getRelatedPosts(token, posts); - insertChannelPosts(posts, true); + insertChannelPosts(posts, NULL, true); } static void setAllMessagesReadCallback(FeedItem *feedItem, const QVariant &data) diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.h b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.h index a14caa8cf..193deff19 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.h +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.h @@ -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 &posts, bool related); + void insertChannelPosts(std::vector &posts, GxsMessageFramePostThread *thread, bool related); + + void createPostItem(const RsGxsChannelPost &post, bool related); private: QAction *mAutoDownloadAction; diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.ui b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.ui index 9dee95082..ab1aafd6b 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.ui +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.ui @@ -177,6 +177,22 @@ + + + + + 16777215 + 10 + + + + 1000 + + + 0 + + + @@ -208,27 +224,6 @@ - - - - - - Loading - - - - - - - 1000 - - - 24 - - - - -