Moved the fill function of the ForumsDialog to a QThread.

Fixed memory leak of the fill thread of the history browser.

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@4240 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
thunder2 2011-06-07 22:28:07 +00:00
parent f4635b92c3
commit 2efa6b5b06
7 changed files with 519 additions and 355 deletions

View File

@ -24,6 +24,7 @@
#include <QDateTime> #include <QDateTime>
#include <QMessageBox> #include <QMessageBox>
#include <QKeyEvent> #include <QKeyEvent>
#include <QProgressBar>
#include "ForumsDialog.h" #include "ForumsDialog.h"
#include "forums/CreateForum.h" #include "forums/CreateForum.h"
@ -89,6 +90,8 @@
#define ROLE_THREAD_COUNT 3 #define ROLE_THREAD_COUNT 3
#define IS_UNREAD(status) ((status & FORUM_MSG_STATUS_READ) == 0 || (status & FORUM_MSG_STATUS_UNREAD_BY_USER)) #define IS_UNREAD(status) ((status & FORUM_MSG_STATUS_READ) == 0 || (status & FORUM_MSG_STATUS_UNREAD_BY_USER))
#define IS_FORUM_ADMIN(subscribeFlags) (subscribeFlags & RS_DISTRIB_ADMIN)
#define IS_FORUM_SUBSCRIBED(subscribeFlags) (subscribeFlags & (RS_DISTRIB_ADMIN | RS_DISTRIB_SUBSCRIBED))
static int FilterColumnFromComboBox(int nIndex) static int FilterColumnFromComboBox(int nIndex)
{ {
@ -130,8 +133,7 @@ ForumsDialog::ForumsDialog(QWidget *parent)
ui.setupUi(this); ui.setupUi(this);
m_bProcessSettings = false; m_bProcessSettings = false;
isForumSubscribed = false; subscribeFlags = 0;
isForumAdmin = false;
connect( ui.forumTreeWidget, SIGNAL( treeCustomContextMenuRequested( QPoint ) ), this, SLOT( forumListCustomPopupMenu( QPoint ) ) ); connect( ui.forumTreeWidget, SIGNAL( treeCustomContextMenuRequested( QPoint ) ), this, SLOT( forumListCustomPopupMenu( QPoint ) ) );
connect( ui.threadTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( threadListCustomPopupMenu( QPoint ) ) ); connect( ui.threadTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( threadListCustomPopupMenu( QPoint ) ) );
@ -203,6 +205,9 @@ ForumsDialog::ForumsDialog(QWidget *parent)
ttheader->setResizeMode (COLUMN_THREAD_READ, QHeaderView::Fixed); ttheader->setResizeMode (COLUMN_THREAD_READ, QHeaderView::Fixed);
ttheader->hideSection (COLUMN_THREAD_CONTENT); ttheader->hideSection (COLUMN_THREAD_CONTENT);
ui.progressBar->hide();
fillThread = NULL;
insertThreads(); insertThreads();
ui.threadTreeWidget->installEventFilter(this); ui.threadTreeWidget->installEventFilter(this);
@ -215,6 +220,12 @@ ForumsDialog::ForumsDialog(QWidget *parent)
ForumsDialog::~ForumsDialog() ForumsDialog::~ForumsDialog()
{ {
if (fillThread) {
fillThread->stop();
delete(fillThread);
fillThread = NULL;
}
// save settings // save settings
processSettings(false); processSettings(false);
} }
@ -270,10 +281,10 @@ void ForumsDialog::forumListCustomPopupMenu( QPoint point )
QMenu contextMnu( this ); QMenu contextMnu( this );
QAction *action = contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Subscribe to Forum"), this, SLOT(subscribeToForum())); QAction *action = contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Subscribe to Forum"), this, SLOT(subscribeToForum()));
action->setDisabled (mCurrForumId.empty() || isForumSubscribed); action->setDisabled (mCurrForumId.empty() || IS_FORUM_SUBSCRIBED(subscribeFlags));
action = contextMnu.addAction(QIcon(IMAGE_UNSUBSCRIBE), tr("Unsubscribe to Forum"), this, SLOT(unsubscribeToForum())); action = contextMnu.addAction(QIcon(IMAGE_UNSUBSCRIBE), tr("Unsubscribe to Forum"), this, SLOT(unsubscribeToForum()));
action->setEnabled (!mCurrForumId.empty() && isForumSubscribed); action->setEnabled (!mCurrForumId.empty() && IS_FORUM_SUBSCRIBED(subscribeFlags));
contextMnu.addSeparator(); contextMnu.addSeparator();
@ -283,12 +294,12 @@ void ForumsDialog::forumListCustomPopupMenu( QPoint point )
action->setEnabled (!mCurrForumId.empty ()); action->setEnabled (!mCurrForumId.empty ());
action = contextMnu.addAction(QIcon(":/images/settings16.png"), tr("Edit Forum Details"), this, SLOT(editForumDetails())); action = contextMnu.addAction(QIcon(":/images/settings16.png"), tr("Edit Forum Details"), this, SLOT(editForumDetails()));
action->setEnabled (!mCurrForumId.empty () && isForumAdmin); action->setEnabled (!mCurrForumId.empty () && IS_FORUM_ADMIN(subscribeFlags));
QAction *restoreKeysAct = new QAction(QIcon(":/images/settings16.png"), tr("Restore Publish Rights for Forum" ), &contextMnu); QAction *restoreKeysAct = new QAction(QIcon(":/images/settings16.png"), tr("Restore Publish Rights for Forum" ), &contextMnu);
connect( restoreKeysAct , SIGNAL( triggered() ), this, SLOT( restoreForumKeys() ) ); connect( restoreKeysAct , SIGNAL( triggered() ), this, SLOT( restoreForumKeys() ) );
restoreKeysAct->setEnabled(!mCurrForumId.empty() && !isForumAdmin); restoreKeysAct->setEnabled(!mCurrForumId.empty() && !IS_FORUM_ADMIN(subscribeFlags));
contextMnu.addAction( restoreKeysAct); contextMnu.addAction( restoreKeysAct);
action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyForumLink())); action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyForumLink()));
@ -297,15 +308,15 @@ void ForumsDialog::forumListCustomPopupMenu( QPoint point )
contextMnu.addSeparator(); contextMnu.addSeparator();
action = contextMnu.addAction(QIcon(":/images/message-mail-read.png"), tr("Mark all as read"), this, SLOT(markMsgAsReadAll())); action = contextMnu.addAction(QIcon(":/images/message-mail-read.png"), tr("Mark all as read"), this, SLOT(markMsgAsReadAll()));
action->setEnabled (!mCurrForumId.empty () && isForumSubscribed); action->setEnabled (!mCurrForumId.empty () && IS_FORUM_SUBSCRIBED(subscribeFlags));
action = contextMnu.addAction(QIcon(":/images/message-mail.png"), tr("Mark all as unread"), this, SLOT(markMsgAsUnreadAll())); action = contextMnu.addAction(QIcon(":/images/message-mail.png"), tr("Mark all as unread"), this, SLOT(markMsgAsUnreadAll()));
action->setEnabled (!mCurrForumId.empty () && isForumSubscribed); action->setEnabled (!mCurrForumId.empty () && IS_FORUM_SUBSCRIBED(subscribeFlags));
#ifdef DEBUG_FORUMS #ifdef DEBUG_FORUMS
contextMnu.addSeparator(); contextMnu.addSeparator();
action = contextMnu.addAction("Generate mass data", this, SLOT(generateMassData())); action = contextMnu.addAction("Generate mass data", this, SLOT(generateMassData()));
action->setEnabled (!mCurrForumId.empty() && isForumSubscribed); action->setEnabled (!mCurrForumId.empty() && IS_FORUM_SUBSCRIBED(subscribeFlags));
#endif #endif
contextMnu.exec(QCursor::pos()); contextMnu.exec(QCursor::pos());
@ -313,13 +324,17 @@ void ForumsDialog::forumListCustomPopupMenu( QPoint point )
void ForumsDialog::threadListCustomPopupMenu( QPoint point ) void ForumsDialog::threadListCustomPopupMenu( QPoint point )
{ {
if (fillThread) {
return;
}
QMenu contextMnu( this ); QMenu contextMnu( this );
QAction *replyAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr( "Reply" ), &contextMnu ); QAction *replyAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr( "Reply" ), &contextMnu );
connect( replyAct , SIGNAL( triggered() ), this, SLOT( createmessage() ) ); connect( replyAct , SIGNAL( triggered() ), this, SLOT( createmessage() ) );
QAction *newthreadAct = new QAction(QIcon(IMAGE_DOWNLOADALL), tr( "Start New Thread" ), &contextMnu ); QAction *newthreadAct = new QAction(QIcon(IMAGE_DOWNLOADALL), tr( "Start New Thread" ), &contextMnu );
newthreadAct->setEnabled (isForumSubscribed); newthreadAct->setEnabled (IS_FORUM_SUBSCRIBED(subscribeFlags));
connect( newthreadAct , SIGNAL( triggered() ), this, SLOT( createthread() ) ); connect( newthreadAct , SIGNAL( triggered() ), this, SLOT( createthread() ) );
QAction *replyauthorAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr( "Reply to Author" ), &contextMnu ); QAction *replyauthorAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr( "Reply to Author" ), &contextMnu );
@ -343,7 +358,7 @@ void ForumsDialog::threadListCustomPopupMenu( QPoint point )
QAction *markMsgAsUnreadChildren = new QAction(QIcon(":/images/message-mail.png"), tr("Mark as unread") + " (" + tr ("with children") + ")", &contextMnu); QAction *markMsgAsUnreadChildren = new QAction(QIcon(":/images/message-mail.png"), tr("Mark as unread") + " (" + tr ("with children") + ")", &contextMnu);
connect(markMsgAsUnreadChildren , SIGNAL(triggered()), this, SLOT(markMsgAsUnreadChildren())); connect(markMsgAsUnreadChildren , SIGNAL(triggered()), this, SLOT(markMsgAsUnreadChildren()));
if (isForumSubscribed) { if (IS_FORUM_SUBSCRIBED(subscribeFlags)) {
QList<QTreeWidgetItem*> Rows; QList<QTreeWidgetItem*> Rows;
QList<QTreeWidgetItem*> RowsRead; QList<QTreeWidgetItem*> RowsRead;
QList<QTreeWidgetItem*> RowsUnread; QList<QTreeWidgetItem*> RowsUnread;
@ -583,7 +598,7 @@ void ForumsDialog::changedThread ()
void ForumsDialog::clickedThread (QTreeWidgetItem *item, int column) void ForumsDialog::clickedThread (QTreeWidgetItem *item, int column)
{ {
if (mCurrForumId.empty() || isForumSubscribed == false) { if (mCurrForumId.empty() || !IS_FORUM_SUBSCRIBED(subscribeFlags)) {
return; return;
} }
@ -638,7 +653,7 @@ void ForumsDialog::CalculateIconsAndFonts(QTreeWidgetItem *pItem, bool &bHasRead
for (int i = 0; i < COLUMN_THREAD_COUNT; i++) { for (int i = 0; i < COLUMN_THREAD_COUNT; i++) {
QFont qf = pItem->font(i); QFont qf = pItem->font(i);
if (isForumSubscribed == false) { if (!IS_FORUM_SUBSCRIBED(subscribeFlags)) {
qf.setBold(false); qf.setBold(false);
pItem->setTextColor(i, Qt::black); pItem->setTextColor(i, Qt::black);
} else if (bUnread) { } else if (bUnread) {
@ -685,6 +700,64 @@ void ForumsDialog::CalculateIconsAndFonts(QTreeWidgetItem *pItem /*= NULL*/)
} }
} }
void ForumsDialog::fillThreadFinished()
{
// thread has finished
if (fillThread == sender()) {
ui.progressBar->hide();
if (fillThread->wasStopped()) {
// thread was stopped
} else {
/* add all messages in! */
if (lastViewType != fillThread->viewType || lastForumID != mCurrForumId) {
ui.threadTreeWidget->clear();
lastViewType = fillThread->viewType;
lastForumID = mCurrForumId;
ui.threadTreeWidget->insertTopLevelItems(0, fillThread->items);
// clear list
fillThread->items.clear();
QList<QTreeWidgetItem*>::iterator Item;
for (Item = fillThread->itemToExpand.begin(); Item != fillThread->itemToExpand.end(); Item++) {
if ((*Item)->isHidden() == false) {
(*Item)->setExpanded(true);
}
}
} else {
FillThreads (fillThread->items, fillThread->expandNewMessages, fillThread->itemToExpand);
// cleanup list
CleanupItems (fillThread->items);
}
fillThread->itemToExpand.clear();
if (ui.filterPatternLineEdit->text().isEmpty() == false) {
FilterItems();
}
insertPost ();
CalculateIconsAndFonts();
ui.newmessageButton->setEnabled (IS_FORUM_SUBSCRIBED(subscribeFlags));
ui.newthreadButton->setEnabled (IS_FORUM_SUBSCRIBED(subscribeFlags));
}
fillThread->deleteLater();
fillThread = NULL;
}
}
void ForumsDialog::fillThreadProgress(int current, int count)
{
// show fill progress
if (count) {
ui.progressBar->setValue(current * ui.progressBar->maximum() / count);
}
}
void ForumsDialog::insertThreads() void ForumsDialog::insertThreads()
{ {
#ifdef DEBUG_FORUMS #ifdef DEBUG_FORUMS
@ -692,8 +765,22 @@ void ForumsDialog::insertThreads()
std::cerr << "ForumsDialog::insertThreads()" << std::endl; std::cerr << "ForumsDialog::insertThreads()" << std::endl;
#endif #endif
isForumSubscribed = false; if (fillThread) {
isForumAdmin = false; // delete fill thread
fillThread->stop();
delete(fillThread);
fillThread = NULL;
ui.progressBar->hide();
}
subscribeFlags = 0;
ui.newmessageButton->setEnabled (false);
ui.newthreadButton->setEnabled (false);
ui.postText->clear();
ui.threadTitle->clear();
if (mCurrForumId.empty()) if (mCurrForumId.empty())
{ {
@ -701,330 +788,55 @@ void ForumsDialog::insertThreads()
ui.threadTreeWidget->clear(); ui.threadTreeWidget->clear();
/* when no Thread selected - clear */ /* when no Thread selected - clear */
ui.forumName->clear(); ui.forumName->clear();
ui.threadTitle->clear();
ui.postText->clear();
/* clear last stored forumID */ /* clear last stored forumID */
mCurrForumId.erase(); mCurrForumId.erase();
lastForumID.erase(); lastForumID.erase();
#ifdef DEBUG_FORUMS #ifdef DEBUG_FORUMS
std::cerr << "ForumsDialog::insertThreads() Current Thread Invalid" << std::endl; std::cerr << "ForumsDialog::insertThreads() Current Thread Invalid" << std::endl;
#endif #endif
ui.newmessageButton->setEnabled (false);
ui.newthreadButton->setEnabled (false);
return; return;
} }
ForumInfo fi; ForumInfo fi;
if (rsForums->getForumInfo (mCurrForumId, fi)) { if (!rsForums->getForumInfo(mCurrForumId, fi)) {
if (fi.subscribeFlags & RS_DISTRIB_ADMIN) {
isForumAdmin = true;
}
if (fi.subscribeFlags & (RS_DISTRIB_ADMIN | RS_DISTRIB_SUBSCRIBED)) {
isForumSubscribed = true;
}
} else {
return; return;
} }
subscribeFlags = fi.subscribeFlags;
ui.forumName->setText(QString::fromStdWString(fi.forumName)); ui.forumName->setText(QString::fromStdWString(fi.forumName));
ui.newmessageButton->setEnabled (isForumSubscribed); ui.progressBar->show();
ui.newthreadButton->setEnabled (isForumSubscribed); ui.threadTreeWidget->clear();
bool flatView = false; // create fill thread
bool useChildTS = false; fillThread = new ForumsFillThread(this);
int viewType = ui.viewBox->currentIndex();
switch(viewType) // set data
{ fillThread->forumId = mCurrForumId;
case VIEW_LAST_POST: fillThread->filterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex());
useChildTS = true; fillThread->subscribeFlags = subscribeFlags;
break; fillThread->viewType = ui.viewBox->currentIndex();
case VIEW_FLAT: if (lastViewType != fillThread->viewType || lastForumID != mCurrForumId) {
flatView = true; fillThread->fillComplete = true;
break;
default:
case VIEW_THREADED:
break;
} }
if (flatView) { if (fillThread->viewType == VIEW_FLAT) {
ui.threadTreeWidget->setRootIsDecorated(false); ui.threadTreeWidget->setRootIsDecorated(false);
} else { } else {
ui.threadTreeWidget->setRootIsDecorated(true); ui.threadTreeWidget->setRootIsDecorated(true);
} }
bool expandNewMessages = Settings->getExpandNewMessages(); // connect thread
std::list<QTreeWidgetItem*> itemToExpand; connect(fillThread, SIGNAL(finished()), this, SLOT(fillThreadFinished()));
connect(fillThread, SIGNAL(progress(int,int)), this, SLOT(fillThreadProgress(int,int)));
bool fillComplete = false; // start thread
if (lastViewType != viewType || lastForumID != mCurrForumId) { fillThread->start();
fillComplete = true;
}
int filterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex());
uint32_t status;
std::list<ThreadInfoSummary> threads;
std::list<ThreadInfoSummary>::iterator tit;
rsForums->getForumThreadList(mCurrForumId, threads);
QList<QTreeWidgetItem *> items;
for(tit = threads.begin(); tit != threads.end(); tit++)
{
#ifdef DEBUG_FORUMS
std::cerr << "ForumsDialog::insertThreads() Adding TopLevel Thread: mId: ";
std::cerr << tit->msgId << std::endl;
#endif
ForumMsgInfo msginfo;
if (rsForums->getForumMessage(mCurrForumId, tit->msgId, msginfo) == false) {
#ifdef DEBUG_FORUMS
std::cerr << "ForumsDialog::insertThreads() Failed to Get Msg";
std::cerr << std::endl;
#endif
continue;
}
/* add Msg */
/* setup
*
*/
QTreeWidgetItem *item = new QTreeWidgetItem();
QString text;
{
QDateTime qtime;
if (useChildTS)
qtime.setTime_t(tit->childTS);
else
qtime.setTime_t(tit->ts);
text = qtime.toString("yyyy-MM-dd hh:mm:ss");
if (useChildTS)
{
QDateTime qtime2;
qtime2.setTime_t(tit->ts);
QString timestamp2 = qtime2.toString("yyyy-MM-dd hh:mm:ss");
text += " / ";
text += timestamp2;
}
item->setText(COLUMN_THREAD_DATE, text);
}
item->setText(COLUMN_THREAD_TITLE, QString::fromStdWString(tit->title));
text = QString::fromStdString(rsPeers->getPeerName(msginfo.srcId));
if (text.isEmpty())
{
item->setText(COLUMN_THREAD_AUTHOR, tr("Anonymous"));
}
else
{
item->setText(COLUMN_THREAD_AUTHOR, text);
}
if (msginfo.msgflags & RS_DISTRIB_AUTHEN_REQ)
{
item->setText(COLUMN_THREAD_SIGNED, tr("signed"));
item->setIcon(COLUMN_THREAD_SIGNED, QIcon(":/images/mail-signed.png"));
}
else
{
item->setText(COLUMN_THREAD_SIGNED, tr("none"));
item->setIcon(COLUMN_THREAD_SIGNED, QIcon(":/images/mail-signature-unknown.png"));
}
if (filterColumn == COLUMN_THREAD_CONTENT) {
// need content for filter
QTextDocument doc;
doc.setHtml(QString::fromStdWString(msginfo.msg));
item->setText(COLUMN_THREAD_CONTENT, doc.toPlainText().replace(QString("\n"), QString(" ")));
}
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(tit->msgId));
if (isForumSubscribed && !(msginfo.msgflags & RS_DISTRIB_MISSING_MSG)) {
rsForums->getMessageStatus(msginfo.forumId, msginfo.msgId, status);
} else {
// show message as read
status = FORUM_MSG_STATUS_READ;
}
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, status);
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING, (msginfo.msgflags & RS_DISTRIB_MISSING_MSG) ? true : false);
std::list<QTreeWidgetItem *> threadlist;
threadlist.push_back(item);
while (threadlist.size() > 0)
{
/* get children */
QTreeWidgetItem *parent = threadlist.front();
threadlist.pop_front();
std::string pId = parent->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString();
std::list<ThreadInfoSummary> msgs;
std::list<ThreadInfoSummary>::iterator mit;
#ifdef DEBUG_FORUMS
std::cerr << "ForumsDialog::insertThreads() Getting Children of : " << pId;
std::cerr << std::endl;
#endif
if (rsForums->getForumThreadMsgList(mCurrForumId, pId, msgs))
{
#ifdef DEBUG_FORUMS
std::cerr << "ForumsDialog::insertThreads() #Children " << msgs.size();
std::cerr << std::endl;
#endif
/* iterate through child */
for(mit = msgs.begin(); mit != msgs.end(); mit++)
{
#ifdef DEBUG_FORUMS
std::cerr << "ForumsDialog::insertThreads() adding " << mit->msgId;
std::cerr << std::endl;
#endif
ForumMsgInfo msginfo;
if (rsForums->getForumMessage(mCurrForumId, mit->msgId, msginfo) == false) {
#ifdef DEBUG_FORUMS
std::cerr << "ForumsDialog::insertThreads() Failed to Get Msg";
std::cerr << std::endl;
#endif
continue;
}
QTreeWidgetItem *child = NULL;
if (flatView)
{
child = new QTreeWidgetItem();
}
else
{
child = new QTreeWidgetItem(parent);
}
{
QDateTime qtime;
if (useChildTS)
qtime.setTime_t(mit->childTS);
else
qtime.setTime_t(mit->ts);
text = qtime.toString("yyyy-MM-dd hh:mm:ss");
if (useChildTS)
{
QDateTime qtime2;
qtime2.setTime_t(mit->ts);
QString timestamp2 = qtime2.toString("yyyy-MM-dd hh:mm:ss");
text += " / ";
text += timestamp2;
}
child->setText(COLUMN_THREAD_DATE, text);
}
child->setText(COLUMN_THREAD_TITLE, QString::fromStdWString(mit->title));
text = QString::fromStdString(rsPeers->getPeerName(msginfo.srcId));
if (text.isEmpty())
{
child->setText(COLUMN_THREAD_AUTHOR, tr("Anonymous"));
}
else
{
child->setText(COLUMN_THREAD_AUTHOR, text);
}
if (msginfo.msgflags & RS_DISTRIB_AUTHEN_REQ)
{
child->setText(COLUMN_THREAD_SIGNED, tr("signed"));
child->setIcon(COLUMN_THREAD_SIGNED,(QIcon(":/images/mail-signed.png")));
}
else
{
child->setText(COLUMN_THREAD_SIGNED, tr("none"));
child->setIcon(COLUMN_THREAD_SIGNED,(QIcon(":/images/mail-signature-unknown.png")));
}
if (filterColumn == COLUMN_THREAD_CONTENT) {
// need content for filter
QTextDocument doc;
doc.setHtml(QString::fromStdWString(msginfo.msg));
child->setText(COLUMN_THREAD_CONTENT, doc.toPlainText().replace(QString("\n"), QString(" ")));
}
child->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(mit->msgId));
if (isForumSubscribed && !(msginfo.msgflags & RS_DISTRIB_MISSING_MSG)) {
rsForums->getMessageStatus(msginfo.forumId, msginfo.msgId, status);
} else {
// show message as read
status = FORUM_MSG_STATUS_READ;
}
child->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, status);
child->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING, (msginfo.msgflags & RS_DISTRIB_MISSING_MSG) ? true : false);
if (fillComplete && expandNewMessages && IS_UNREAD(status)) {
QTreeWidgetItem *pParent = child;
while ((pParent = pParent->parent()) != NULL) {
if (std::find(itemToExpand.begin(), itemToExpand.end(), pParent) == itemToExpand.end()) {
itemToExpand.push_back(pParent);
}
}
}
/* setup child */
threadlist.push_back(child);
if (flatView)
{
items.append(child);
}
}
}
}
/* add to list */
items.append(item);
}
ui.postText->clear();
ui.threadTitle->clear();
/* add all messages in! */
if (lastViewType != viewType || lastForumID != mCurrForumId) {
ui.threadTreeWidget->clear();
lastViewType = viewType;
lastForumID = mCurrForumId;
ui.threadTreeWidget->insertTopLevelItems(0, items);
} else {
FillThreads (items, expandNewMessages, itemToExpand);
CleanupItems (items);
}
if (ui.filterPatternLineEdit->text().isEmpty() == false) {
FilterItems();
}
std::list<QTreeWidgetItem*>::iterator Item;
for (Item = itemToExpand.begin(); Item != itemToExpand.end(); Item++) {
if ((*Item)->isHidden() == false) {
(*Item)->setExpanded(true);
}
}
insertPost ();
CalculateIconsAndFonts();
} }
void ForumsDialog::FillThreads(QList<QTreeWidgetItem *> &ThreadList, bool expandNewMessages, std::list<QTreeWidgetItem*> &itemToExpand) void ForumsDialog::FillThreads(QList<QTreeWidgetItem *> &ThreadList, bool expandNewMessages, QList<QTreeWidgetItem*> &itemToExpand)
{ {
int Index = 0; int Index = 0;
QTreeWidgetItem *Thread; QTreeWidgetItem *Thread;
@ -1095,7 +907,7 @@ void ForumsDialog::FillThreads(QList<QTreeWidgetItem *> &ThreadList, bool expand
} }
} }
void ForumsDialog::FillChildren(QTreeWidgetItem *Parent, QTreeWidgetItem *NewParent, bool expandNewMessages, std::list<QTreeWidgetItem*> &itemToExpand) void ForumsDialog::FillChildren(QTreeWidgetItem *Parent, QTreeWidgetItem *NewParent, bool expandNewMessages, QList<QTreeWidgetItem*> &itemToExpand)
{ {
int Index = 0; int Index = 0;
int NewIndex; int NewIndex;
@ -1199,7 +1011,7 @@ void ForumsDialog::insertPost()
ui.nextButton->setEnabled(false); ui.nextButton->setEnabled(false);
} }
ui.newmessageButton->setEnabled (isForumSubscribed && mCurrThreadId.empty() == false); ui.newmessageButton->setEnabled (IS_FORUM_SUBSCRIBED(subscribeFlags) && mCurrThreadId.empty() == false);
/* get the Post */ /* get the Post */
ForumMsgInfo msg; ForumMsgInfo msg;
@ -1372,7 +1184,7 @@ void ForumsDialog::setMsgAsReadUnread(QList<QTreeWidgetItem*> &Rows, bool bRead)
void ForumsDialog::markMsgAsReadUnread (bool bRead, bool bChildren, bool bForum) void ForumsDialog::markMsgAsReadUnread (bool bRead, bool bChildren, bool bForum)
{ {
if (mCurrForumId.empty() || isForumSubscribed == false) { if (mCurrForumId.empty() || !IS_FORUM_SUBSCRIBED(subscribeFlags)) {
return; return;
} }
@ -1491,7 +1303,7 @@ void ForumsDialog::newforum()
void ForumsDialog::createmessage() void ForumsDialog::createmessage()
{ {
if (mCurrForumId.empty () || isForumSubscribed == false) { if (mCurrForumId.empty () || !IS_FORUM_SUBSCRIBED(subscribeFlags)) {
return; return;
} }
@ -1782,3 +1594,291 @@ void ForumsDialog::generateMassData()
} }
#endif #endif
} }
// ForumsFillThread
ForumsFillThread::ForumsFillThread(ForumsDialog *parent)
: QThread(parent)
{
stopped = false;
expandNewMessages = Settings->getExpandNewMessages();
fillComplete = false;
filterColumn = 0;
subscribeFlags = 0;
viewType = 0;
}
ForumsFillThread::~ForumsFillThread()
{
// remove all items (when items are available, the thread was terminated)
CleanupItems (items);
itemToExpand.clear();
}
void ForumsFillThread::stop()
{
disconnect();
stopped = true;
wait();
}
void ForumsFillThread::run()
{
uint32_t status;
std::list<ThreadInfoSummary> threads;
std::list<ThreadInfoSummary>::iterator tit;
rsForums->getForumThreadList(forumId, threads);
bool flatView = false;
bool useChildTS = false;
switch(viewType)
{
case VIEW_LAST_POST:
useChildTS = true;
break;
case VIEW_FLAT:
flatView = true;
break;
case VIEW_THREADED:
break;
}
int count = threads.size();
int pos = 0;
for (tit = threads.begin(); tit != threads.end(); tit++)
{
if (stopped) {
break;
}
#ifdef DEBUG_FORUMS
std::cerr << "FForumsFillThread::run() Adding TopLevel Thread: mId: ";
std::cerr << tit->msgId << std::endl;
#endif
ForumMsgInfo msginfo;
if (rsForums->getForumMessage(forumId, tit->msgId, msginfo) == false) {
#ifdef DEBUG_FORUMS
std::cerr << "ForumsFillThread::run() Failed to Get Msg";
std::cerr << std::endl;
#endif
continue;
}
/* add Msg */
/* setup
*
*/
QTreeWidgetItem *item = new QTreeWidgetItem();
QString text;
{
QDateTime qtime;
if (useChildTS)
qtime.setTime_t(tit->childTS);
else
qtime.setTime_t(tit->ts);
text = qtime.toString("yyyy-MM-dd hh:mm:ss");
if (useChildTS)
{
QDateTime qtime2;
qtime2.setTime_t(tit->ts);
QString timestamp2 = qtime2.toString("yyyy-MM-dd hh:mm:ss");
text += " / ";
text += timestamp2;
}
item->setText(COLUMN_THREAD_DATE, text);
}
item->setText(COLUMN_THREAD_TITLE, QString::fromStdWString(tit->title));
text = QString::fromStdString(rsPeers->getPeerName(msginfo.srcId));
if (text.isEmpty())
{
item->setText(COLUMN_THREAD_AUTHOR, tr("Anonymous"));
}
else
{
item->setText(COLUMN_THREAD_AUTHOR, text);
}
if (msginfo.msgflags & RS_DISTRIB_AUTHEN_REQ)
{
item->setText(COLUMN_THREAD_SIGNED, tr("signed"));
item->setIcon(COLUMN_THREAD_SIGNED, QIcon(":/images/mail-signed.png"));
}
else
{
item->setText(COLUMN_THREAD_SIGNED, tr("none"));
item->setIcon(COLUMN_THREAD_SIGNED, QIcon(":/images/mail-signature-unknown.png"));
}
if (filterColumn == COLUMN_THREAD_CONTENT) {
// need content for filter
QTextDocument doc;
doc.setHtml(QString::fromStdWString(msginfo.msg));
item->setText(COLUMN_THREAD_CONTENT, doc.toPlainText().replace(QString("\n"), QString(" ")));
}
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(tit->msgId));
if (IS_FORUM_SUBSCRIBED(subscribeFlags) && !(msginfo.msgflags & RS_DISTRIB_MISSING_MSG)) {
rsForums->getMessageStatus(msginfo.forumId, msginfo.msgId, status);
} else {
// show message as read
status = FORUM_MSG_STATUS_READ;
}
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, status);
item->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING, (msginfo.msgflags & RS_DISTRIB_MISSING_MSG) ? true : false);
std::list<QTreeWidgetItem*> threadlist;
threadlist.push_back(item);
while (threadlist.size() > 0)
{
if (stopped) {
break;
}
/* get children */
QTreeWidgetItem *parent = threadlist.front();
threadlist.pop_front();
std::string pId = parent->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString();
std::list<ThreadInfoSummary> msgs;
std::list<ThreadInfoSummary>::iterator mit;
#ifdef DEBUG_FORUMS
std::cerr << "ForumsFillThread::run() Getting Children of : " << pId;
std::cerr << std::endl;
#endif
if (rsForums->getForumThreadMsgList(forumId, pId, msgs))
{
#ifdef DEBUG_FORUMS
std::cerr << "ForumsFillThread::run() #Children " << msgs.size();
std::cerr << std::endl;
#endif
/* iterate through child */
for(mit = msgs.begin(); mit != msgs.end(); mit++)
{
#ifdef DEBUG_FORUMS
std::cerr << "ForumsFillThread::run() adding " << mit->msgId;
std::cerr << std::endl;
#endif
ForumMsgInfo msginfo;
if (rsForums->getForumMessage(forumId, mit->msgId, msginfo) == false) {
#ifdef DEBUG_FORUMS
std::cerr << "ForumsFillThread::run() Failed to Get Msg";
std::cerr << std::endl;
#endif
continue;
}
QTreeWidgetItem *child = NULL;
if (flatView)
{
child = new QTreeWidgetItem();
}
else
{
child = new QTreeWidgetItem(parent);
}
{
QDateTime qtime;
if (useChildTS)
qtime.setTime_t(mit->childTS);
else
qtime.setTime_t(mit->ts);
text = qtime.toString("yyyy-MM-dd hh:mm:ss");
if (useChildTS)
{
QDateTime qtime2;
qtime2.setTime_t(mit->ts);
QString timestamp2 = qtime2.toString("yyyy-MM-dd hh:mm:ss");
text += " / ";
text += timestamp2;
}
child->setText(COLUMN_THREAD_DATE, text);
}
child->setText(COLUMN_THREAD_TITLE, QString::fromStdWString(mit->title));
text = QString::fromStdString(rsPeers->getPeerName(msginfo.srcId));
if (text.isEmpty())
{
child->setText(COLUMN_THREAD_AUTHOR, tr("Anonymous"));
}
else
{
child->setText(COLUMN_THREAD_AUTHOR, text);
}
if (msginfo.msgflags & RS_DISTRIB_AUTHEN_REQ)
{
child->setText(COLUMN_THREAD_SIGNED, tr("signed"));
child->setIcon(COLUMN_THREAD_SIGNED,(QIcon(":/images/mail-signed.png")));
}
else
{
child->setText(COLUMN_THREAD_SIGNED, tr("none"));
child->setIcon(COLUMN_THREAD_SIGNED,(QIcon(":/images/mail-signature-unknown.png")));
}
if (filterColumn == COLUMN_THREAD_CONTENT) {
// need content for filter
QTextDocument doc;
doc.setHtml(QString::fromStdWString(msginfo.msg));
child->setText(COLUMN_THREAD_CONTENT, doc.toPlainText().replace(QString("\n"), QString(" ")));
}
child->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID, QString::fromStdString(mit->msgId));
if (IS_FORUM_SUBSCRIBED(subscribeFlags) && !(msginfo.msgflags & RS_DISTRIB_MISSING_MSG)) {
rsForums->getMessageStatus(msginfo.forumId, msginfo.msgId, status);
} else {
// show message as read
status = FORUM_MSG_STATUS_READ;
}
child->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, status);
child->setData(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING, (msginfo.msgflags & RS_DISTRIB_MISSING_MSG) ? true : false);
if (fillComplete && expandNewMessages && IS_UNREAD(status)) {
QTreeWidgetItem *pParent = child;
while ((pParent = pParent->parent()) != NULL) {
if (std::find(itemToExpand.begin(), itemToExpand.end(), pParent) == itemToExpand.end()) {
itemToExpand.push_back(pParent);
}
}
}
/* setup child */
threadlist.push_back(child);
if (flatView)
{
items.append(child);
}
}
}
}
/* add to list */
items.append(item);
emit progress(++pos, count);
}
}

View File

@ -22,11 +22,14 @@
#ifndef _FORUMSDIALOG_H #ifndef _FORUMSDIALOG_H
#define _FORUMSDIALOG_H #define _FORUMSDIALOG_H
#include <QThread>
#include "mainpage.h" #include "mainpage.h"
#include "RsAutoUpdatePage.h" #include "RsAutoUpdatePage.h"
#include "ui_ForumsDialog.h" #include "ui_ForumsDialog.h"
class ForumInfo; class ForumInfo;
class ForumsFillThread;
class ForumsDialog : public RsAutoUpdatePage class ForumsDialog : public RsAutoUpdatePage
{ {
@ -93,6 +96,9 @@ private slots:
void generateMassData(); void generateMassData();
void fillThreadFinished();
void fillThreadProgress(int current, int count);
private: private:
void insertForums(); void insertForums();
void insertThreads(); void insertThreads();
@ -101,8 +107,8 @@ private:
void forumInfoToGroupItemInfo(const ForumInfo &forumInfo, GroupItemInfo &groupItemInfo); void forumInfoToGroupItemInfo(const ForumInfo &forumInfo, GroupItemInfo &groupItemInfo);
void forumSubscribe(bool subscribe); void forumSubscribe(bool subscribe);
void FillThreads(QList<QTreeWidgetItem *> &ThreadList, bool bExpandNewMessages, std::list<QTreeWidgetItem*> &itemToExpand); void FillThreads(QList<QTreeWidgetItem *> &ThreadList, bool bExpandNewMessages, QList<QTreeWidgetItem*> &itemToExpand);
void FillChildren(QTreeWidgetItem *Parent, QTreeWidgetItem *NewParent, bool bExpandNewMessages, std::list<QTreeWidgetItem*> &itemToExpand); void FillChildren(QTreeWidgetItem *Parent, QTreeWidgetItem *NewParent, bool bExpandNewMessages, QList<QTreeWidgetItem*> &itemToExpand);
int getSelectedMsgCount(QList<QTreeWidgetItem*> *pRows, QList<QTreeWidgetItem*> *pRowsRead, QList<QTreeWidgetItem*> *pRowsUnread); int getSelectedMsgCount(QList<QTreeWidgetItem*> *pRows, QList<QTreeWidgetItem*> *pRowsRead, QList<QTreeWidgetItem*> *pRowsUnread);
void setMsgAsReadUnread(QList<QTreeWidgetItem*> &Rows, bool bRead); void setMsgAsReadUnread(QList<QTreeWidgetItem*> &Rows, bool bRead);
@ -125,16 +131,47 @@ private:
std::string mCurrForumId; std::string mCurrForumId;
std::string mCurrThreadId; std::string mCurrThreadId;
bool isForumSubscribed; int subscribeFlags;
bool isForumAdmin;
QFont m_ForumNameFont; QFont m_ForumNameFont;
int lastViewType; int lastViewType;
std::string lastForumID; std::string lastForumID;
ForumsFillThread *fillThread;
/** Qt Designer generated object */ /** Qt Designer generated object */
Ui::ForumsDialog ui; Ui::ForumsDialog ui;
}; };
class ForumsFillThread : public QThread
{
Q_OBJECT
public:
ForumsFillThread(ForumsDialog *parent);
~ForumsFillThread();
void run();
void stop();
bool wasStopped() { return stopped; }
signals:
void progress(int current, int count);
public:
std::string forumId;
int filterColumn;
int subscribeFlags;
bool fillComplete;
int viewType;
bool expandNewMessages;
QList<QTreeWidgetItem*> items;
QList<QTreeWidgetItem*> itemToExpand;
private:
volatile bool stopped;
};
#endif #endif

View File

@ -792,7 +792,7 @@ background: white;
</item> </item>
</layout> </layout>
</item> </item>
<item row="2" column="0"> <item row="3" column="0">
<widget class="QTreeWidget" name="threadTreeWidget"> <widget class="QTreeWidget" name="threadTreeWidget">
<property name="font"> <property name="font">
<font> <font>
@ -836,7 +836,7 @@ background: white;
</column> </column>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="5" column="0">
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLabel" name="threadlabel"> <widget class="QLabel" name="threadlabel">
@ -1196,6 +1196,25 @@ border-image: url(:/images/closepressed.png)
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<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>
<property name="textVisible">
<bool>false</bool>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QTextBrowser" name="postText"> <widget class="QTextBrowser" name="postText">

View File

@ -149,7 +149,7 @@ static void embedHtml(QDomDocument& doc, QDomElement& currentElement, EmbedInHtm
QString formatText(const QString &text, unsigned int flag) QString formatText(const QString &text, unsigned int flag)
{ {
if (flag == 0) { if (flag == 0 || text.isEmpty()) {
// nothing to do // nothing to do
return text; return text;
} }

View File

@ -45,6 +45,7 @@ ImHistoryBrowserCreateItemsThread::ImHistoryBrowserCreateItemsThread(ImHistoryBr
: QThread(parent), m_historyKeeper(histKeeper) : QThread(parent), m_historyKeeper(histKeeper)
{ {
m_historyBrowser = parent; m_historyBrowser = parent;
stopped = false;
} }
ImHistoryBrowserCreateItemsThread::~ImHistoryBrowserCreateItemsThread() ImHistoryBrowserCreateItemsThread::~ImHistoryBrowserCreateItemsThread()
@ -58,6 +59,13 @@ ImHistoryBrowserCreateItemsThread::~ImHistoryBrowserCreateItemsThread()
m_items.clear(); m_items.clear();
} }
void ImHistoryBrowserCreateItemsThread::stop()
{
disconnect();
stopped = true;
wait();
}
void ImHistoryBrowserCreateItemsThread::run() void ImHistoryBrowserCreateItemsThread::run()
{ {
QList<IMHistoryItem> historyItems; QList<IMHistoryItem> historyItems;
@ -67,6 +75,9 @@ void ImHistoryBrowserCreateItemsThread::run()
int current = 0; int current = 0;
foreach(IMHistoryItem item, historyItems) { foreach(IMHistoryItem item, historyItems) {
if (stopped) {
break;
}
QListWidgetItem *itemWidget = m_historyBrowser->createItem(item); QListWidgetItem *itemWidget = m_historyBrowser->createItem(item);
if (itemWidget) { if (itemWidget) {
m_items.push_back(itemWidget); m_items.push_back(itemWidget);
@ -129,7 +140,6 @@ ImHistoryBrowser::ImHistoryBrowser(const std::string &peerId, IMHistoryKeeper &h
m_createThread = new ImHistoryBrowserCreateItemsThread(this, historyKeeper); m_createThread = new ImHistoryBrowserCreateItemsThread(this, historyKeeper);
connect(m_createThread, SIGNAL(finished()), this, SLOT(createThreadFinished())); connect(m_createThread, SIGNAL(finished()), this, SLOT(createThreadFinished()));
connect(m_createThread, SIGNAL(terminated()), this, SLOT(createThreadTerminated()));
connect(m_createThread, SIGNAL(progress(int,int)), this, SLOT(createThreadProgress(int,int))); connect(m_createThread, SIGNAL(progress(int,int)), this, SLOT(createThreadProgress(int,int)));
m_createThread->start(); m_createThread->start();
} }
@ -139,14 +149,8 @@ ImHistoryBrowser::~ImHistoryBrowser()
Settings->setValueToGroup("HistorieBrowser", "Geometry", saveGeometry()); Settings->setValueToGroup("HistorieBrowser", "Geometry", saveGeometry());
if (m_createThread) { if (m_createThread) {
m_createThread->terminate(); m_createThread->stop();
} delete(m_createThread);
}
void ImHistoryBrowser::createThreadTerminated()
{
if (m_createThread == sender()) {
ui.progressBar->setVisible(false);
m_createThread = NULL; m_createThread = NULL;
} }
} }
@ -156,28 +160,30 @@ void ImHistoryBrowser::createThreadFinished()
if (m_createThread == sender()) { if (m_createThread == sender()) {
ui.progressBar->setVisible(false); ui.progressBar->setVisible(false);
// append created items if (!m_createThread->wasStopped()) {
QList<QListWidgetItem*>::iterator it; // append created items
for (it = m_createThread->m_items.begin(); it != m_createThread->m_items.end(); it++) { QList<QListWidgetItem*>::iterator it;
ui.listWidget->addItem(*it); for (it = m_createThread->m_items.begin(); it != m_createThread->m_items.end(); it++) {
ui.listWidget->addItem(*it);
}
// clear list
m_createThread->m_items.clear();
filterRegExpChanged();
// dummy call for set buttons
itemSelectionChanged();
m_createThread->deleteLater();
m_createThread = NULL;
QList<IMHistoryItem>::iterator histIt;
for (histIt = m_itemsAddedOnLoad.begin(); histIt != m_itemsAddedOnLoad.end(); histIt++) {
historyAdd(*histIt);
}
m_itemsAddedOnLoad.clear();
} }
// clear list
m_createThread->m_items.clear();
filterRegExpChanged();
// dummy call for set buttons
itemSelectionChanged();
delete(m_createThread);
m_createThread = NULL;
QList<IMHistoryItem>::iterator histIt;
for (histIt = m_itemsAddedOnLoad.begin(); histIt != m_itemsAddedOnLoad.end(); histIt++) {
historyAdd(*histIt);
}
m_itemsAddedOnLoad.clear();
} }
} }

View File

@ -51,7 +51,6 @@ protected:
bool eventFilter(QObject *obj, QEvent *ev); bool eventFilter(QObject *obj, QEvent *ev);
private slots: private slots:
void createThreadTerminated();
void createThreadFinished(); void createThreadFinished();
void createThreadProgress(int current, int count); void createThreadProgress(int current, int count);
@ -104,6 +103,8 @@ public:
~ImHistoryBrowserCreateItemsThread(); ~ImHistoryBrowserCreateItemsThread();
void run(); void run();
void stop();
bool wasStopped() { return stopped; }
signals: signals:
void progress(int current, int count); void progress(int current, int count);
@ -114,6 +115,7 @@ public:
private: private:
IMHistoryKeeper &m_historyKeeper; IMHistoryKeeper &m_historyKeeper;
ImHistoryBrowser *m_historyBrowser; ImHistoryBrowser *m_historyBrowser;
volatile bool stopped;
}; };
#endif #endif

View File

@ -289,7 +289,7 @@ border-image: url(:/images/closepressed.png)
<number>1000</number> <number>1000</number>
</property> </property>
<property name="value"> <property name="value">
<number>24</number> <number>0</number>
</property> </property>
<property name="textVisible"> <property name="textVisible">
<bool>false</bool> <bool>false</bool>