RetroShare/retroshare-gui/src/gui/gxsforums/GxsForumsFillThread.cpp
2014-11-29 18:45:01 +00:00

293 lines
7.5 KiB
C++

/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2012, RetroShare Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#include <QApplication>
#include <QTreeWidgetItem>
#include "GxsForumsFillThread.h"
#include "GxsForumThreadWidget.h"
#include "retroshare/rsgxsflags.h"
#include <retroshare/rsgxsforums.h>
#include <iostream>
#include <algorithm>
//#define DEBUG_FORUMS
#define PROGRESSBAR_MAX 100
GxsForumsFillThread::GxsForumsFillThread(GxsForumThreadWidget *parent)
: QThread(parent), mParent(parent)
{
mStopped = false;
mCompareRole = NULL;
mExpandNewMessages = true;
mFillComplete = false;
mFilterColumn = 0;
mFilterString = QString();
mViewType = 0;
mFlatView = false;
mUseChildTS = false;
}
GxsForumsFillThread::~GxsForumsFillThread()
{
#ifdef DEBUG_FORUMS
std::cerr << "GxsForumsFillThread::~GxsForumsFillThread" << std::endl;
#endif
// remove all items (when items are available, the thread was terminated)
QList<QTreeWidgetItem *>::iterator item;
for (item = mItems.begin (); item != mItems.end (); ++item) {
if (*item) {
delete (*item);
}
}
mItems.clear();
mItemToExpand.clear();
}
void GxsForumsFillThread::stop()
{
disconnect();
mStopped = true;
QApplication::processEvents();
wait();
}
void GxsForumsFillThread::calculateExpand(const RsGxsForumMsg &msg, QTreeWidgetItem *item)
{
if (mFillComplete && mExpandNewMessages && IS_MSG_UNREAD(msg.mMeta.mMsgStatus)) {
QTreeWidgetItem *parentItem = item;
while ((parentItem = parentItem->parent()) != NULL) {
if (std::find(mItemToExpand.begin(), mItemToExpand.end(), parentItem) == mItemToExpand.end()) {
mItemToExpand.push_back(parentItem);
}
}
}
}
void GxsForumsFillThread::run()
{
RsTokenService *service = rsGxsForums->getTokenService();
emit status(tr("Waiting"));
/* get all messages of the forum */
RsTokReqOptions opts;
opts.mReqType = GXS_REQUEST_TYPE_MSG_DATA;
std::list<RsGxsGroupId> grpIds;
grpIds.push_back(mForumId);
#ifdef DEBUG_FORUMS
std::cerr << "GxsForumsFillThread::run() forum id " << mForumId << std::endl;
#endif
uint32_t token;
service->requestMsgInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, grpIds);
/* wait for the answer */
uint32_t requestStatus = RsTokenService::GXS_REQUEST_V2_STATUS_PENDING;
while (!wasStopped()) {
requestStatus = service->requestStatus(token);
if (requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED ||
requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_COMPLETE) {
break;
}
msleep(100);
}
if (wasStopped()) {
#ifdef DEBUG_FORUMS
std::cerr << "GxsForumsFillThread::run() thread stopped, cancel request" << std::endl;
#endif
/* cancel request */
service->cancelRequest(token);
return;
}
if (requestStatus == RsTokenService::GXS_REQUEST_V2_STATUS_FAILED) {
//#TODO
return;
}
//#TODO
// if (failed) {
// mService->cancelRequest(token);
// return;
// }
emit status(tr("Retrieving"));
/* get messages */
std::vector<RsGxsForumMsg> msgs;
if (!rsGxsForums->getMsgData(token, msgs)) {
return;
}
emit status(tr("Loading"));
int count = msgs.size();
int pos = 0;
int steps = count / PROGRESSBAR_MAX;
int step = 0;
QList<QPair<std::string, QTreeWidgetItem*> > threadList;
QPair<std::string, QTreeWidgetItem*> threadPair;
/* add all threads */
std::vector<RsGxsForumMsg>::iterator msgIt;
for (msgIt = msgs.begin(); msgIt != msgs.end(); ) {
if (wasStopped()) {
break;
}
const RsGxsForumMsg &msg = *msgIt;
if (!mFlatView && !msg.mMeta.mParentId.isNull()) {
++msgIt;
continue;
}
#ifdef DEBUG_FORUMS
std::cerr << "GxsForumsFillThread::run() Adding TopLevel Thread: mId: " << msg.mMeta.mMsgId << std::endl;
#endif
QTreeWidgetItem *item = mParent->convertMsgToThreadWidget(msg, mUseChildTS, mFilterColumn, mFilterString);
if (!mFlatView) {
threadList.push_back(QPair<std::string, QTreeWidgetItem*>(msg.mMeta.mMsgId.toStdString(), item));
}
calculateExpand(msg, item);
mItems.append(item);
if (++step >= steps) {
step = 0;
emit progress(++pos, PROGRESSBAR_MAX);
}
msgIt = msgs.erase(msgIt);
}
/* process messages */
while (msgs.size()) {
while (threadList.size() > 0) {
if (wasStopped()) {
break;
}
threadPair = threadList.front();
threadList.pop_front();
#ifdef DEBUG_FORUMS
std::cerr << "GxsForumsFillThread::run() Getting Children of : " << threadPair.first << std::endl;
#endif
/* iterate through child */
for (msgIt = msgs.begin(); msgIt != msgs.end(); ) {
const RsGxsForumMsg &msg = *msgIt;
if (msg.mMeta.mParentId.toStdString() != threadPair.first) {
++msgIt;
continue;
}
#ifdef DEBUG_FORUMS
std::cerr << "GxsForumsFillThread::run() adding " << msg.mMeta.mMsgId << std::endl;
#endif
QTreeWidgetItem *item = mParent->convertMsgToThreadWidget(msg, mUseChildTS, mFilterColumn, mFilterString);
threadPair.second->addChild(item);
if ( !item->isHidden() && threadPair.second->isHidden() ){
threadPair.second->setHidden(false);
for (QTreeWidgetItem *cursIt = threadPair.second->parent(); cursIt; cursIt = cursIt->parent()){
cursIt->setHidden(false);
}
}
calculateExpand(msg, item);
/* add item to process list */
threadList.push_back(QPair<std::string, QTreeWidgetItem*>(msg.mMeta.mMsgId.toStdString(), item));
if (++step >= steps) {
step = 0;
emit progress(++pos, PROGRESSBAR_MAX);
}
msgIt = msgs.erase(msgIt);
}
}
if (wasStopped()) {
break;
}
/* process missing messages */
/* search for a message with missing parent */
for (msgIt = msgs.begin(); msgIt != msgs.end(); ++msgIt) {
const RsGxsForumMsg &msg = *msgIt;
/* search for parent */
std::vector<RsGxsForumMsg>::iterator msgIt1;
for (msgIt1 = msgs.begin(); msgIt1 != msgs.end(); ++msgIt1) {
if (wasStopped()) {
break;
}
const RsGxsForumMsg &msg1 = *msgIt1;
if (msg.mMeta.mParentId == msg1.mMeta.mMsgId) {
/* found parent */
break;
}
}
if (wasStopped()) {
break;
}
if (msgIt1 != msgs.end()) {
/* parant found */
continue;
}
/* add dummy item */
QTreeWidgetItem *item = mParent->generateMissingItem(msg.mMeta.mParentId);
threadList.push_back(QPair<std::string, QTreeWidgetItem*>(msg.mMeta.mParentId.toStdString(), item));
mItems.append(item);
break;
}
}
#ifdef DEBUG_FORUMS
std::cerr << "GxsForumsFillThread::run() stopped: " << (wasStopped() ? "yes" : "no") << std::endl;
#endif
}