mirror of
				https://github.com/RetroShare/RetroShare.git
				synced 2025-10-31 14:49:14 -04:00 
			
		
		
		
	 8d4a4db027
			
		
	
	
		8d4a4db027
		
	
	
	
	
		
			
			The existing gpg keys and locations with umlauts are now shown wrong. The changes are not backward compatible. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@4460 b45a01b8-16f6-495d-af2f-9b41ad6348cc
		
			
				
	
	
		
			1930 lines
		
	
	
	
		
			61 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1930 lines
		
	
	
	
		
			61 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /****************************************************************
 | |
|  *  RetroShare is distributed under the following license:
 | |
|  *
 | |
|  *  Copyright (C) 2008 Robert Fernie
 | |
|  *
 | |
|  *  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 <QMenu>
 | |
| #include <QFile>
 | |
| #include <QDateTime>
 | |
| #include <QMessageBox>
 | |
| #include <QKeyEvent>
 | |
| #include <QProgressBar>
 | |
| 
 | |
| #include "ForumsDialog.h"
 | |
| #include "forums/CreateForum.h"
 | |
| #include "forums/CreateForumMsg.h"
 | |
| #include "forums/ForumDetails.h"
 | |
| #include "forums/EditForumDetails.h"
 | |
| #include "msgs/MessageComposer.h"
 | |
| #include "settings/rsharesettings.h"
 | |
| #include "common/Emoticons.h"
 | |
| #include "common/RSItemDelegate.h"
 | |
| #include "common/PopularityDefs.h"
 | |
| #include "RetroShareLink.h"
 | |
| 
 | |
| #include <retroshare/rspeers.h>
 | |
| #include <retroshare/rsforums.h>
 | |
| 
 | |
| #include <algorithm>
 | |
| 
 | |
| //#define DEBUG_FORUMS
 | |
| 
 | |
| /* Images for context menu icons */
 | |
| #define IMAGE_MESSAGE        ":/images/folder-draft.png"
 | |
| #define IMAGE_MESSAGEREPLY   ":/images/mail_reply.png"
 | |
| #define IMAGE_MESSAGEREMOVE  ":/images/mail_delete.png"
 | |
| #define IMAGE_DOWNLOAD       ":/images/start.png"
 | |
| #define IMAGE_DOWNLOADALL    ":/images/startall.png"
 | |
| 
 | |
| /* Images for TreeWidget */
 | |
| #define IMAGE_FOLDER         ":/images/folder16.png"
 | |
| #define IMAGE_FOLDERGREEN    ":/images/folder_green.png"
 | |
| #define IMAGE_FOLDERRED      ":/images/folder_red.png"
 | |
| #define IMAGE_FOLDERYELLOW   ":/images/folder_yellow.png"
 | |
| #define IMAGE_FORUM          ":/images/konversation16.png"
 | |
| #define IMAGE_SUBSCRIBE      ":/images/edit_add24.png"
 | |
| #define IMAGE_UNSUBSCRIBE    ":/images/cancel.png"
 | |
| #define IMAGE_INFO           ":/images/info16.png"
 | |
| #define IMAGE_NEWFORUM       ":/images/new_forum16.png"
 | |
| #define IMAGE_FORUMAUTHD     ":/images/konv_message2.png"
 | |
| #define IMAGE_COPYLINK       ":/images/copyrslink.png"
 | |
| 
 | |
| #define VIEW_LAST_POST	0
 | |
| #define VIEW_THREADED	1
 | |
| #define VIEW_FLAT	2
 | |
| 
 | |
| /* Thread constants */
 | |
| #define COLUMN_THREAD_COUNT    6
 | |
| #define COLUMN_THREAD_TITLE    0
 | |
| #define COLUMN_THREAD_READ     1
 | |
| #define COLUMN_THREAD_DATE     2
 | |
| #define COLUMN_THREAD_AUTHOR   3
 | |
| #define COLUMN_THREAD_SIGNED   4
 | |
| #define COLUMN_THREAD_CONTENT  5
 | |
| 
 | |
| #define COLUMN_THREAD_DATA     0 // column for storing the userdata like msgid and parentid
 | |
| 
 | |
| #define ROLE_THREAD_MSGID           Qt::UserRole
 | |
| #define ROLE_THREAD_STATUS          Qt::UserRole + 1
 | |
| #define ROLE_THREAD_MISSING         Qt::UserRole + 2
 | |
| // no need to copy, don't count in ROLE_THREAD_COUNT
 | |
| #define ROLE_THREAD_READCHILDREN    Qt::UserRole + 3
 | |
| #define ROLE_THREAD_UNREADCHILDREN  Qt::UserRole + 4
 | |
| 
 | |
| #define ROLE_THREAD_COUNT           3
 | |
| 
 | |
| #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)
 | |
| {
 | |
|     switch (nIndex) {
 | |
|     case 0:
 | |
|         return COLUMN_THREAD_DATE;
 | |
|     case 1:
 | |
|         return COLUMN_THREAD_TITLE;
 | |
|     case 2:
 | |
|         return COLUMN_THREAD_AUTHOR;
 | |
|     case 3:
 | |
|         return COLUMN_THREAD_CONTENT;
 | |
|     }
 | |
| 
 | |
|     return COLUMN_THREAD_TITLE;
 | |
| }
 | |
| 
 | |
| static int FilterColumnToComboBox(int nIndex)
 | |
| {
 | |
|     switch (nIndex) {
 | |
|     case COLUMN_THREAD_DATE:
 | |
|         return 0;
 | |
|     case COLUMN_THREAD_TITLE:
 | |
|         return 1;
 | |
|     case COLUMN_THREAD_AUTHOR:
 | |
|         return 2;
 | |
|     case COLUMN_THREAD_CONTENT:
 | |
|         return 3;
 | |
|     }
 | |
| 
 | |
|     return FilterColumnToComboBox(COLUMN_THREAD_TITLE);
 | |
| }
 | |
| 
 | |
| /** Constructor */
 | |
| ForumsDialog::ForumsDialog(QWidget *parent)
 | |
| : RsAutoUpdatePage(1000,parent)
 | |
| {
 | |
|     /* Invoke the Qt Designer generated object setup routine */
 | |
|     ui.setupUi(this);
 | |
| 
 | |
|     m_bProcessSettings = false;
 | |
|     subscribeFlags = 0;
 | |
| 
 | |
|     connect( ui.forumTreeWidget, SIGNAL( treeCustomContextMenuRequested( QPoint ) ), this, SLOT( forumListCustomPopupMenu( QPoint ) ) );
 | |
|     connect( ui.threadTreeWidget, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( threadListCustomPopupMenu( QPoint ) ) );
 | |
| 
 | |
| 	connect(ui.newForumButton, SIGNAL(clicked()), this, SLOT(newforum()));
 | |
|     connect(ui.newmessageButton, SIGNAL(clicked()), this, SLOT(createmessage()));
 | |
|     connect(ui.newthreadButton, SIGNAL(clicked()), this, SLOT(createthread()));
 | |
| 
 | |
|     connect( ui.forumTreeWidget, SIGNAL( treeCurrentItemChanged(QString) ), this, SLOT( changedForum(QString) ) );
 | |
| 
 | |
|     connect( ui.threadTreeWidget, SIGNAL( itemSelectionChanged() ), this, SLOT( changedThread () ) );
 | |
|     connect( ui.threadTreeWidget, SIGNAL( itemClicked(QTreeWidgetItem*,int)), this, SLOT( clickedThread (QTreeWidgetItem*,int) ) );
 | |
|     connect( ui.viewBox, SIGNAL( currentIndexChanged ( int ) ), this, SLOT( changedViewBox () ) );
 | |
| 
 | |
|     connect(ui.expandButton, SIGNAL(clicked()), this, SLOT(togglethreadview()));
 | |
|     connect(ui.previousButton, SIGNAL(clicked()), this, SLOT(previousMessage()));
 | |
|     connect(ui.nextButton, SIGNAL(clicked()), this, SLOT(nextMessage()));
 | |
|     connect(ui.downloadButton, SIGNAL(clicked()), this, SLOT(downloadAllFiles()));
 | |
| 
 | |
|     connect(ui.clearButton, SIGNAL(clicked()), this, SLOT(clearFilter()));
 | |
|     connect(ui.filterPatternLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(filterRegExpChanged()));
 | |
|     connect(ui.filterColumnComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterColumnChanged()));
 | |
| 
 | |
|     /* Set initial size the splitter */
 | |
|     QList<int> sizes;
 | |
|     sizes << 300 << width(); // Qt calculates the right sizes
 | |
|     ui.splitter->setSizes(sizes);
 | |
| 
 | |
|     /* Set own item delegate */
 | |
|     RSItemDelegate *itemDelegate = new RSItemDelegate(this);
 | |
|     itemDelegate->setSpacing(QSize(0, 2));
 | |
|     ui.threadTreeWidget->setItemDelegate(itemDelegate);
 | |
| 
 | |
|     /* Set header resize modes and initial section sizes */
 | |
|     QHeaderView * ttheader = ui.threadTreeWidget->header () ;
 | |
|     ttheader->setResizeMode (COLUMN_THREAD_TITLE, QHeaderView::Interactive);
 | |
|     ttheader->resizeSection (COLUMN_THREAD_DATE,  140);
 | |
|     ttheader->resizeSection (COLUMN_THREAD_TITLE, 290);
 | |
| 
 | |
|     ui.threadTreeWidget->sortItems( COLUMN_THREAD_DATE, Qt::DescendingOrder );
 | |
| 
 | |
|     /* Set text of column "Read" to empty - without this the column has a number as header text */
 | |
|     QTreeWidgetItem *headerItem = ui.threadTreeWidget->headerItem();
 | |
|     headerItem->setText(COLUMN_THREAD_READ, "");
 | |
| 
 | |
|     m_ForumNameFont = QFont("Times", 12, QFont::Bold);
 | |
|     ui.forumName->setFont(m_ForumNameFont);
 | |
|     ui.threadTitle->setFont(m_ForumNameFont);
 | |
| 
 | |
|     /* Initialize group tree */
 | |
|     ui.forumTreeWidget->initDisplayMenu(ui.displayButton);
 | |
| 
 | |
|     /* create forum tree */
 | |
|     yourForums = ui.forumTreeWidget->addCategoryItem(tr("Your Forums"), QIcon(IMAGE_FOLDER), true);
 | |
|     subscribedForums = ui.forumTreeWidget->addCategoryItem(tr("Subscribed Forums"), QIcon(IMAGE_FOLDERRED), true);
 | |
|     popularForums = ui.forumTreeWidget->addCategoryItem(tr("Popular Forums"), QIcon(IMAGE_FOLDERGREEN), false);
 | |
|     otherForums = ui.forumTreeWidget->addCategoryItem(tr("Other Forums"), QIcon(IMAGE_FOLDERYELLOW), false);
 | |
| 
 | |
|     lastViewType = -1;
 | |
| 
 | |
|     ui.clearButton->hide();
 | |
| 
 | |
|     // load settings
 | |
|     processSettings(true);
 | |
| 
 | |
|     /* Set header sizes for the fixed columns and resize modes, must be set after processSettings */
 | |
|     ttheader->resizeSection (COLUMN_THREAD_READ,  24);
 | |
|     ttheader->setResizeMode (COLUMN_THREAD_READ, QHeaderView::Fixed);
 | |
|     ttheader->hideSection (COLUMN_THREAD_CONTENT);
 | |
| 
 | |
|     ui.progressBar->hide();
 | |
|     fillThread = NULL;
 | |
| 
 | |
|     insertThreads();
 | |
| 
 | |
|     ui.threadTreeWidget->installEventFilter(this);
 | |
| 
 | |
|     /* Hide platform specific features */
 | |
| #ifdef Q_WS_WIN
 | |
| 
 | |
| #endif
 | |
| }
 | |
| 
 | |
| ForumsDialog::~ForumsDialog()
 | |
| {
 | |
|     if (fillThread) {
 | |
|         fillThread->stop();
 | |
|         delete(fillThread);
 | |
|         fillThread = NULL;
 | |
|     }
 | |
| 
 | |
|     // save settings
 | |
|     processSettings(false);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::processSettings(bool bLoad)
 | |
| {
 | |
|     m_bProcessSettings = true;
 | |
| 
 | |
|     QHeaderView *pHeader = ui.threadTreeWidget->header () ;
 | |
| 
 | |
|     Settings->beginGroup(QString("ForumsDialog"));
 | |
| 
 | |
|     if (bLoad) {
 | |
|         // load settings
 | |
| 
 | |
|         // expandFiles
 | |
|         bool bValue = Settings->value("expandButton", true).toBool();
 | |
|         ui.expandButton->setChecked(bValue);
 | |
|         togglethreadview_internal();
 | |
| 
 | |
|         // filterColumn
 | |
|         int nValue = FilterColumnToComboBox(Settings->value("filterColumn", true).toInt());
 | |
|         ui.filterColumnComboBox->setCurrentIndex(nValue);
 | |
| 
 | |
|         // index of viewBox
 | |
|         ui.viewBox->setCurrentIndex(Settings->value("viewBox", VIEW_THREADED).toInt());
 | |
| 
 | |
|         // state of thread tree
 | |
|         pHeader->restoreState(Settings->value("ThreadTree").toByteArray());
 | |
| 
 | |
|         // state of splitter
 | |
|         ui.splitter->restoreState(Settings->value("Splitter").toByteArray());
 | |
|         ui.threadSplitter->restoreState(Settings->value("threadSplitter").toByteArray());
 | |
|     } else {
 | |
|         // save settings
 | |
| 
 | |
|         // state of thread tree
 | |
|         Settings->setValue("ThreadTree", pHeader->saveState());
 | |
| 
 | |
|         // state of splitter
 | |
|         Settings->setValue("Splitter", ui.splitter->saveState());
 | |
|         Settings->setValue("threadSplitter", ui.threadSplitter->saveState());
 | |
|     }
 | |
| 
 | |
|     ui.forumTreeWidget->processSettings(Settings, bLoad);
 | |
| 
 | |
|     Settings->endGroup();
 | |
|     m_bProcessSettings = false;
 | |
| }
 | |
| 
 | |
| void ForumsDialog::forumListCustomPopupMenu( QPoint point )
 | |
| {
 | |
|     QMenu contextMnu( this );
 | |
| 
 | |
|     QAction *action = contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Subscribe to Forum"), this, SLOT(subscribeToForum()));
 | |
|     action->setDisabled (mCurrForumId.empty() || IS_FORUM_SUBSCRIBED(subscribeFlags));
 | |
| 
 | |
|     action = contextMnu.addAction(QIcon(IMAGE_UNSUBSCRIBE), tr("Unsubscribe to Forum"), this, SLOT(unsubscribeToForum()));
 | |
|     action->setEnabled (!mCurrForumId.empty() && IS_FORUM_SUBSCRIBED(subscribeFlags));
 | |
| 
 | |
|     contextMnu.addSeparator();
 | |
| 
 | |
|     contextMnu.addAction(QIcon(IMAGE_NEWFORUM), tr("New Forum"), this, SLOT(newforum()));
 | |
| 
 | |
|     action = contextMnu.addAction(QIcon(IMAGE_INFO), tr("Show Forum Details"), this, SLOT(showForumDetails()));
 | |
|     action->setEnabled (!mCurrForumId.empty ());
 | |
| 
 | |
|     action = contextMnu.addAction(QIcon(":/images/settings16.png"), tr("Edit Forum Details"), this, SLOT(editForumDetails()));
 | |
|     action->setEnabled (!mCurrForumId.empty () && IS_FORUM_ADMIN(subscribeFlags));
 | |
| 
 | |
|     QAction *restoreKeysAct = new QAction(QIcon(":/images/settings16.png"), tr("Restore Publish Rights for Forum" ), &contextMnu);
 | |
|     connect( restoreKeysAct , SIGNAL( triggered() ), this, SLOT( restoreForumKeys() ) );
 | |
| 
 | |
|     restoreKeysAct->setEnabled(!mCurrForumId.empty() && !IS_FORUM_ADMIN(subscribeFlags));
 | |
|     contextMnu.addAction( restoreKeysAct);
 | |
| 
 | |
|     action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr("Copy RetroShare Link"), this, SLOT(copyForumLink()));
 | |
|     action->setEnabled(!mCurrForumId.empty());
 | |
| 
 | |
|     contextMnu.addSeparator();
 | |
| 
 | |
|     action = contextMnu.addAction(QIcon(":/images/message-mail-read.png"), tr("Mark all as read"), this, SLOT(markMsgAsReadAll()));
 | |
|     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->setEnabled (!mCurrForumId.empty () && IS_FORUM_SUBSCRIBED(subscribeFlags));
 | |
| 
 | |
| #ifdef DEBUG_FORUMS
 | |
|     contextMnu.addSeparator();
 | |
|     action = contextMnu.addAction("Generate mass data", this, SLOT(generateMassData()));
 | |
|     action->setEnabled (!mCurrForumId.empty() && IS_FORUM_SUBSCRIBED(subscribeFlags));
 | |
| #endif
 | |
| 
 | |
|     contextMnu.exec(QCursor::pos());
 | |
| }
 | |
| 
 | |
| void ForumsDialog::threadListCustomPopupMenu( QPoint point )
 | |
| {
 | |
|     if (fillThread) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     QMenu contextMnu( this );
 | |
| 
 | |
|     QAction *replyAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr( "Reply" ), &contextMnu );
 | |
|     connect( replyAct , SIGNAL( triggered() ), this, SLOT( createmessage() ) );
 | |
| 
 | |
|     QAction *newthreadAct = new QAction(QIcon(IMAGE_DOWNLOADALL), tr( "Start New Thread" ), &contextMnu );
 | |
|     newthreadAct->setEnabled (IS_FORUM_SUBSCRIBED(subscribeFlags));
 | |
|     connect( newthreadAct , SIGNAL( triggered() ), this, SLOT( createthread() ) );
 | |
| 
 | |
|     QAction *replyauthorAct = new QAction(QIcon(IMAGE_MESSAGEREPLY), tr( "Reply to Author" ), &contextMnu );
 | |
|     connect( replyauthorAct , SIGNAL( triggered() ), this, SLOT( replytomessage() ) );
 | |
| 
 | |
|     QAction* expandAll = new QAction(tr( "Expand all" ), &contextMnu );
 | |
|     connect( expandAll , SIGNAL( triggered() ), ui.threadTreeWidget, SLOT (expandAll()) );
 | |
| 
 | |
|     QAction* collapseAll = new QAction(tr( "Collapse all" ), &contextMnu );
 | |
|     connect( collapseAll , SIGNAL( triggered() ), ui.threadTreeWidget, SLOT(collapseAll()) );
 | |
| 
 | |
|     QAction *markMsgAsRead = new QAction(QIcon(":/images/message-mail-read.png"), tr("Mark as read"), &contextMnu);
 | |
|     connect(markMsgAsRead , SIGNAL(triggered()), this, SLOT(markMsgAsRead()));
 | |
| 
 | |
|     QAction *markMsgAsReadChildren = new QAction(QIcon(":/images/message-mail-read.png"), tr("Mark as read") + " (" + tr ("with children") + ")", &contextMnu);
 | |
|     connect(markMsgAsReadChildren, SIGNAL(triggered()), this, SLOT(markMsgAsReadChildren()));
 | |
| 
 | |
|     QAction *markMsgAsUnread = new QAction(QIcon(":/images/message-mail.png"), tr("Mark as unread"), &contextMnu);
 | |
|     connect(markMsgAsUnread , SIGNAL(triggered()), this, SLOT(markMsgAsUnread()));
 | |
| 
 | |
|     QAction *markMsgAsUnreadChildren = new QAction(QIcon(":/images/message-mail.png"), tr("Mark as unread") + " (" + tr ("with children") + ")", &contextMnu);
 | |
|     connect(markMsgAsUnreadChildren , SIGNAL(triggered()), this, SLOT(markMsgAsUnreadChildren()));
 | |
| 
 | |
|     if (IS_FORUM_SUBSCRIBED(subscribeFlags)) {
 | |
|         QList<QTreeWidgetItem*> Rows;
 | |
|         QList<QTreeWidgetItem*> RowsRead;
 | |
|         QList<QTreeWidgetItem*> RowsUnread;
 | |
|         int nCount = getSelectedMsgCount (&Rows, &RowsRead, &RowsUnread);
 | |
| 
 | |
|         if (RowsUnread.size() == 0) {
 | |
| 
 | |
|             markMsgAsRead->setDisabled(true);
 | |
|         }
 | |
|         if (RowsRead.size() == 0) {
 | |
|             markMsgAsUnread->setDisabled(true);
 | |
|         }
 | |
| 
 | |
|         bool bHasUnreadChildren = false;
 | |
|         bool bHasReadChildren = false;
 | |
|         int nRowCount = Rows.count();
 | |
|         for (int i = 0; i < nRowCount; i++) {
 | |
|             if (bHasUnreadChildren || Rows[i]->data(COLUMN_THREAD_DATA, ROLE_THREAD_UNREADCHILDREN).toBool()) {
 | |
|                 bHasUnreadChildren = true;
 | |
|             }
 | |
|             if (bHasReadChildren || Rows[i]->data(COLUMN_THREAD_DATA, ROLE_THREAD_READCHILDREN).toBool()) {
 | |
|                 bHasReadChildren = true;
 | |
|             }
 | |
|         }
 | |
|         markMsgAsReadChildren->setEnabled(bHasUnreadChildren);
 | |
|         markMsgAsUnreadChildren->setEnabled(bHasReadChildren);
 | |
| 
 | |
|         if (nCount == 1) {
 | |
|             replyAct->setEnabled (true);
 | |
|             replyauthorAct->setEnabled (true);
 | |
|         } else {
 | |
|             replyAct->setDisabled (true);
 | |
|             replyauthorAct->setDisabled (true);
 | |
|         }
 | |
|     } else {
 | |
|         markMsgAsRead->setDisabled(true);
 | |
|         markMsgAsReadChildren->setDisabled(true);
 | |
|         markMsgAsUnread->setDisabled(true);
 | |
|         markMsgAsUnreadChildren->setDisabled(true);
 | |
|         replyAct->setDisabled (true);
 | |
|         replyauthorAct->setDisabled (true);
 | |
|     }
 | |
| 
 | |
|     contextMnu.addAction( replyAct);
 | |
|     contextMnu.addAction( newthreadAct);
 | |
|     contextMnu.addAction( replyauthorAct);
 | |
|     QAction* action = contextMnu.addAction(QIcon(IMAGE_COPYLINK), tr( "Copy RetroShare Link"), this, SLOT(copyMessageLink()));
 | |
|     action->setEnabled(!mCurrForumId.empty() && !mCurrThreadId.empty());
 | |
|     contextMnu.addSeparator();
 | |
|     contextMnu.addAction(markMsgAsRead);
 | |
|     contextMnu.addAction(markMsgAsReadChildren);
 | |
|     contextMnu.addAction(markMsgAsUnread);
 | |
|     contextMnu.addAction(markMsgAsUnreadChildren);
 | |
|     contextMnu.addSeparator();
 | |
|     contextMnu.addAction( expandAll);
 | |
|     contextMnu.addAction( collapseAll);
 | |
| 
 | |
|     contextMnu.exec(QCursor::pos());
 | |
| }
 | |
| 
 | |
| bool ForumsDialog::eventFilter(QObject *obj, QEvent *event)
 | |
| {
 | |
|     if (obj == ui.threadTreeWidget) {
 | |
|         if (event->type() == QEvent::KeyPress) {
 | |
|             QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
 | |
|             if (keyEvent && keyEvent->key() == Qt::Key_Space) {
 | |
|                 // Space pressed
 | |
|                 QTreeWidgetItem *item = ui.threadTreeWidget->currentItem ();
 | |
|                 clickedThread (item, COLUMN_THREAD_READ);
 | |
|                 return true; // eat event
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     // pass the event on to the parent class
 | |
|     return RsAutoUpdatePage::eventFilter(obj, event);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::restoreForumKeys(void)
 | |
| {
 | |
| 	rsForums->forumRestoreKeys(mCurrForumId);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::togglethreadview()
 | |
| {
 | |
|     // save state of button
 | |
|     Settings->setValueToGroup("ForumsDialog", "expandButton", ui.expandButton->isChecked());
 | |
| 
 | |
|     togglethreadview_internal();
 | |
| }
 | |
| 
 | |
| void ForumsDialog::togglethreadview_internal()
 | |
| {
 | |
|     if (ui.expandButton->isChecked()) {
 | |
|         ui.postText->setVisible(true);
 | |
|         ui.expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png")));
 | |
|         ui.expandButton->setToolTip(tr("Hide"));
 | |
|     } else  {
 | |
|         ui.postText->setVisible(false);
 | |
|         ui.expandButton->setIcon(QIcon(QString(":/images/edit_add24.png")));
 | |
|         ui.expandButton->setToolTip(tr("Expand"));
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ForumsDialog::updateDisplay()
 | |
| {
 | |
|     std::list<std::string> forumIds;
 | |
|     std::list<std::string>::iterator it;
 | |
|     if (!rsForums)
 | |
|         return;
 | |
| 
 | |
|     if (rsForums->forumsChanged(forumIds))
 | |
|     {
 | |
|         /* update Forums List */
 | |
|         insertForums();
 | |
| 
 | |
|         it = std::find(forumIds.begin(), forumIds.end(), mCurrForumId);
 | |
|         if (it != forumIds.end())
 | |
|         {
 | |
|             /* update threads as well */
 | |
|             insertThreads();
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| static void CleanupItems (QList<QTreeWidgetItem *> &Items)
 | |
| {
 | |
|     QList<QTreeWidgetItem *>::iterator Item;
 | |
|     for (Item = Items.begin (); Item != Items.end (); Item++) {
 | |
|         if (*Item) {
 | |
|             delete (*Item);
 | |
|         }
 | |
|     }
 | |
|     Items.clear();
 | |
| }
 | |
| 
 | |
| void ForumsDialog::forumInfoToGroupItemInfo(const ForumInfo &forumInfo, GroupItemInfo &groupItemInfo)
 | |
| {
 | |
|     groupItemInfo.id = QString::fromStdString(forumInfo.forumId);
 | |
|     groupItemInfo.name = QString::fromStdWString(forumInfo.forumName);
 | |
|     groupItemInfo.description = QString::fromStdWString(forumInfo.forumDesc);
 | |
|     groupItemInfo.popularity = forumInfo.pop;
 | |
|     groupItemInfo.lastpost = QDateTime::fromTime_t(forumInfo.lastPost);
 | |
| 
 | |
|     if (forumInfo.forumFlags & RS_DISTRIB_AUTHEN_REQ) {
 | |
|         groupItemInfo.name += " (" + tr("AUTHD") + ")";
 | |
|         groupItemInfo.icon = QIcon(IMAGE_FORUMAUTHD);
 | |
|     } else {
 | |
|         groupItemInfo.icon = QIcon(IMAGE_FORUM);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ForumsDialog::insertForums()
 | |
| {
 | |
| 	std::list<ForumInfo> forumList;
 | |
| 	std::list<ForumInfo>::iterator it;
 | |
| 	if (!rsForums)
 | |
| 	{
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	rsForums->getForumList(forumList);
 | |
| 
 | |
|     QList<GroupItemInfo> adminList;
 | |
|     QList<GroupItemInfo> subList;
 | |
|     QList<GroupItemInfo> popList;
 | |
|     QList<GroupItemInfo> otherList;
 | |
|     std::multimap<uint32_t, GroupItemInfo> popMap;
 | |
| 
 | |
|     for (it = forumList.begin(); it != forumList.end(); it++) {
 | |
| 		/* sort it into Publish (Own), Subscribed, Popular and Other */
 | |
| 		uint32_t flags = it->subscribeFlags;
 | |
| 
 | |
|         GroupItemInfo groupItemInfo;
 | |
|         forumInfoToGroupItemInfo(*it, groupItemInfo);
 | |
| 
 | |
|         if (flags & RS_DISTRIB_ADMIN) {
 | |
|             adminList.push_back(groupItemInfo);
 | |
|         } else if (flags & RS_DISTRIB_SUBSCRIBED) {
 | |
| 			/* subscribed forum */
 | |
|             subList.push_back(groupItemInfo);
 | |
|         } else {
 | |
| 			/* rate the others by popularity */
 | |
|             popMap.insert(std::make_pair(it->pop, groupItemInfo));
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/* iterate backwards through popMap - take the top 5 or 10% of list */
 | |
| 	uint32_t popCount = 5;
 | |
| 	if (popCount < popMap.size() / 10)
 | |
| 	{
 | |
| 		popCount = popMap.size() / 10;
 | |
| 	}
 | |
| 
 | |
| 	uint32_t i = 0;
 | |
| 	uint32_t popLimit = 0;
 | |
|     std::multimap<uint32_t, GroupItemInfo>::reverse_iterator rit;
 | |
| 	for(rit = popMap.rbegin(); ((rit != popMap.rend()) && (i < popCount)); rit++, i++);
 | |
|     if (rit != popMap.rend()) {
 | |
|         popLimit = rit->first;
 | |
|     }
 | |
| 
 | |
|     for (rit = popMap.rbegin(); rit != popMap.rend(); rit++) {
 | |
| 		if (rit->second.popularity < (int) popLimit) {
 | |
|             otherList.append(rit->second);
 | |
|         } else {
 | |
|             popList.append(rit->second);
 | |
|         }
 | |
| 	}
 | |
| 
 | |
| 	/* now we can add them in as a tree! */
 | |
|     ui.forumTreeWidget->fillGroupItems(yourForums, adminList);
 | |
|     ui.forumTreeWidget->fillGroupItems(subscribedForums, subList);
 | |
|     ui.forumTreeWidget->fillGroupItems(popularForums, popList);
 | |
|     ui.forumTreeWidget->fillGroupItems(otherForums, otherList);
 | |
| 
 | |
| 	updateMessageSummaryList("");
 | |
| }
 | |
| 
 | |
| void ForumsDialog::changedForum(const QString &id)
 | |
| {
 | |
|     mCurrForumId = id.toStdString();
 | |
| 
 | |
|     insertThreads();
 | |
| }
 | |
| 
 | |
| void ForumsDialog::changedThread ()
 | |
| {
 | |
|     if (fillThread) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* just grab the ids of the current item */
 | |
|     QTreeWidgetItem *curr = ui.threadTreeWidget->currentItem();
 | |
| 
 | |
|     if ((!curr) || (!curr->isSelected())) {
 | |
|         mCurrThreadId = "";
 | |
|     } else {
 | |
|         mCurrThreadId = curr->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString();
 | |
|     }
 | |
|     insertPost();
 | |
| }
 | |
| 
 | |
| void ForumsDialog::clickedThread (QTreeWidgetItem *item, int column)
 | |
| {
 | |
|     if (mCurrForumId.empty() || !IS_FORUM_SUBSCRIBED(subscribeFlags)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (item == NULL) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (column == COLUMN_THREAD_READ) {
 | |
|         QList<QTreeWidgetItem*> Rows;
 | |
|         Rows.append(item);
 | |
|         uint32_t status = item->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt();
 | |
|         setMsgAsReadUnread(Rows, IS_UNREAD(status));
 | |
|         return;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ForumsDialog::CalculateIconsAndFonts(QTreeWidgetItem *pItem, bool &bHasReadChilddren, bool &bHasUnreadChilddren)
 | |
| {
 | |
|     uint32_t status = pItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt();
 | |
| 
 | |
|     bool bUnread = IS_UNREAD(status);
 | |
|     bool missing = pItem->data(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING).toBool();
 | |
| 
 | |
|     // set icon
 | |
|     if (missing) {
 | |
|         pItem->setIcon(COLUMN_THREAD_READ, QIcon());
 | |
|         pItem->setIcon(COLUMN_THREAD_TITLE, QIcon());
 | |
|     } else {
 | |
|         if (bUnread) {
 | |
|             pItem->setIcon(COLUMN_THREAD_READ, QIcon(":/images/message-state-unread.png"));
 | |
|         } else {
 | |
|             pItem->setIcon(COLUMN_THREAD_READ, QIcon(":/images/message-state-read.png"));
 | |
|         }
 | |
|         if (status & FORUM_MSG_STATUS_READ) {
 | |
|             pItem->setIcon(COLUMN_THREAD_TITLE, QIcon());
 | |
|         } else {
 | |
|             pItem->setIcon(COLUMN_THREAD_TITLE, QIcon(":/images/message-state-new.png"));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     int nItem;
 | |
|     int nItemCount = pItem->childCount();
 | |
| 
 | |
|     bool bMyReadChilddren = false;
 | |
|     bool bMyUnreadChilddren = false;
 | |
| 
 | |
|     for (nItem = 0; nItem < nItemCount; nItem++) {
 | |
|         CalculateIconsAndFonts(pItem->child(nItem), bMyReadChilddren, bMyUnreadChilddren);
 | |
|     }
 | |
| 
 | |
|     // set font
 | |
|     for (int i = 0; i < COLUMN_THREAD_COUNT; i++) {
 | |
|         QFont qf = pItem->font(i);
 | |
| 
 | |
|         if (!IS_FORUM_SUBSCRIBED(subscribeFlags)) {
 | |
|             qf.setBold(false);
 | |
|             pItem->setTextColor(i, Qt::black);
 | |
|         } else if (bUnread) {
 | |
|             qf.setBold(true);
 | |
|             pItem->setTextColor(i, Qt::black);
 | |
|         } else if (bMyUnreadChilddren) {
 | |
|             qf.setBold(true);
 | |
|             pItem->setTextColor(i, Qt::gray);
 | |
|         } else {
 | |
|             qf.setBold(false);
 | |
|             pItem->setTextColor(i, Qt::gray);
 | |
|         }
 | |
|         if (missing) {
 | |
|             /* Missing message */
 | |
|             pItem->setTextColor(i, Qt::darkRed);
 | |
|         }
 | |
|         pItem->setFont(i, qf);
 | |
|     }
 | |
| 
 | |
|     pItem->setData(COLUMN_THREAD_DATA, ROLE_THREAD_READCHILDREN, bHasReadChilddren || bMyReadChilddren);
 | |
|     pItem->setData(COLUMN_THREAD_DATA, ROLE_THREAD_UNREADCHILDREN, bHasUnreadChilddren || bMyUnreadChilddren);
 | |
| 
 | |
|     bHasReadChilddren = bHasReadChilddren || bMyReadChilddren || !bUnread;
 | |
|     bHasUnreadChilddren = bHasUnreadChilddren || bMyUnreadChilddren || bUnread;
 | |
| }
 | |
| 
 | |
| void ForumsDialog::CalculateIconsAndFonts(QTreeWidgetItem *pItem /*= NULL*/)
 | |
| {
 | |
|     bool bDummy1 = false;
 | |
|     bool bDummy2 = false;
 | |
| 
 | |
|     if (pItem) {
 | |
|         CalculateIconsAndFonts(pItem, bDummy1, bDummy2);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     int nItem;
 | |
|     int nItemCount = ui.threadTreeWidget->topLevelItemCount();
 | |
| 
 | |
|     for (nItem = 0; nItem < nItemCount; nItem++) {
 | |
|         bDummy1 = false;
 | |
|         bDummy2 = false;
 | |
|         CalculateIconsAndFonts(ui.threadTreeWidget->topLevelItem(nItem), bDummy1, bDummy2);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ForumsDialog::fillThreadFinished()
 | |
| {
 | |
| #ifdef DEBUG_FORUMS
 | |
|     std::cerr << "ForumsDialog::fillThreadFinished" << std::endl;
 | |
| #endif
 | |
| 
 | |
|     // thread has finished
 | |
|     ForumsFillThread *thread = dynamic_cast<ForumsFillThread*>(sender());
 | |
|     if (thread) {
 | |
|         if (thread == fillThread) {
 | |
|             // current thread has finished, hide progressbar and release thread
 | |
|             ui.progressBar->hide();
 | |
|             fillThread = NULL;
 | |
|         }
 | |
| 
 | |
|         if (thread->wasStopped()) {
 | |
|             // thread was stopped
 | |
| #ifdef DEBUG_FORUMS
 | |
|             std::cerr << "ForumsDialog::fillThreadFinished Thread was stopped" << std::endl;
 | |
| #endif
 | |
|         } else {
 | |
| #ifdef DEBUG_FORUMS
 | |
|             std::cerr << "ForumsDialog::fillThreadFinished Add messages" << std::endl;
 | |
| #endif
 | |
|             /* add all messages in! */
 | |
|             if (lastViewType != thread->viewType || lastForumID != mCurrForumId) {
 | |
|                 ui.threadTreeWidget->clear();
 | |
|                 lastViewType = thread->viewType;
 | |
|                 lastForumID = mCurrForumId;
 | |
|                 ui.threadTreeWidget->insertTopLevelItems(0, thread->items);
 | |
| 
 | |
|                 // clear list
 | |
|                 thread->items.clear();
 | |
|             } else {
 | |
|                 FillThreads (thread->items, thread->expandNewMessages, thread->itemToExpand);
 | |
| 
 | |
|                 // cleanup list
 | |
|                 CleanupItems (thread->items);
 | |
|             }
 | |
| 
 | |
|             QList<QTreeWidgetItem*>::iterator Item;
 | |
|             for (Item = thread->itemToExpand.begin(); Item != thread->itemToExpand.end(); Item++) {
 | |
|                 if ((*Item)->isHidden() == false) {
 | |
|                     (*Item)->setExpanded(true);
 | |
|                 }
 | |
|             }
 | |
|             thread->itemToExpand.clear();
 | |
| 
 | |
|             if (ui.filterPatternLineEdit->text().isEmpty() == false) {
 | |
|                 FilterItems();
 | |
|             }
 | |
| 
 | |
|             insertPost ();
 | |
|             CalculateIconsAndFonts();
 | |
| 
 | |
|             ui.newthreadButton->setEnabled (IS_FORUM_SUBSCRIBED(subscribeFlags));
 | |
|         }
 | |
| 
 | |
| #ifdef DEBUG_FORUMS
 | |
|         std::cerr << "ForumsDialog::fillThreadFinished Delete thread" << std::endl;
 | |
| #endif
 | |
| 
 | |
|         thread->deleteLater();
 | |
|         thread = NULL;
 | |
|     }
 | |
| 
 | |
| #ifdef DEBUG_FORUMS
 | |
|     std::cerr << "ForumsDialog::fillThreadFinished done" << std::endl;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void ForumsDialog::fillThreadProgress(int current, int count)
 | |
| {
 | |
|     // show fill progress
 | |
|     if (count) {
 | |
|         ui.progressBar->setValue(current * ui.progressBar->maximum() / count);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ForumsDialog::insertThreads()
 | |
| {
 | |
| #ifdef DEBUG_FORUMS
 | |
|     /* get the current Forum */
 | |
|     std::cerr << "ForumsDialog::insertThreads()" << std::endl;
 | |
| #endif
 | |
| 
 | |
|     if (fillThread) {
 | |
| #ifdef DEBUG_FORUMS
 | |
|         std::cerr << "ForumsDialog::insertThreads() stop current fill thread" << std::endl;
 | |
| #endif
 | |
|         // stop and disconnect current fill thread
 | |
|         ForumsFillThread *thread = fillThread;
 | |
|         fillThread = NULL;
 | |
| 
 | |
|         // disconnect only the signal "progress", the signal "finished" is needed to delete the thread
 | |
|         thread->disconnect(this, SIGNAL(progress(int,int)));
 | |
|         thread->stop();
 | |
| 
 | |
|         ui.progressBar->hide();
 | |
|     }
 | |
| 
 | |
|     subscribeFlags = 0;
 | |
| 
 | |
|     ui.newmessageButton->setEnabled (false);
 | |
|     ui.newthreadButton->setEnabled (false);
 | |
| 
 | |
|     ui.postText->clear();
 | |
|     ui.threadTitle->clear();
 | |
| 
 | |
|     if (mCurrForumId.empty())
 | |
|     {
 | |
|         /* not an actual forum - clear */
 | |
|         ui.threadTreeWidget->clear();
 | |
|         /* when no Thread selected - clear */
 | |
|         ui.forumName->clear();
 | |
|         /* clear last stored forumID */
 | |
|         mCurrForumId.erase();
 | |
|         lastForumID.erase();
 | |
| 
 | |
| #ifdef DEBUG_FORUMS
 | |
|         std::cerr << "ForumsDialog::insertThreads() Current Thread Invalid" << std::endl;
 | |
| #endif
 | |
| 
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     ForumInfo fi;
 | |
|     if (!rsForums->getForumInfo(mCurrForumId, fi)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     subscribeFlags = fi.subscribeFlags;
 | |
|     ui.forumName->setText(QString::fromStdWString(fi.forumName));
 | |
| 
 | |
|     ui.progressBar->show();
 | |
| 
 | |
|     // create fill thread
 | |
|     fillThread = new ForumsFillThread(this);
 | |
| 
 | |
|     // set data
 | |
|     fillThread->forumId = mCurrForumId;
 | |
|     fillThread->filterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex());
 | |
|     fillThread->subscribeFlags = subscribeFlags;
 | |
|     fillThread->viewType = ui.viewBox->currentIndex();
 | |
|     if (lastViewType != fillThread->viewType || lastForumID != mCurrForumId) {
 | |
|         fillThread->fillComplete = true;
 | |
|     }
 | |
| 
 | |
|     if (fillThread->viewType == VIEW_FLAT) {
 | |
|         ui.threadTreeWidget->setRootIsDecorated(false);
 | |
|     } else {
 | |
|         ui.threadTreeWidget->setRootIsDecorated(true);
 | |
|     }
 | |
| 
 | |
|     // connect thread
 | |
|     connect(fillThread, SIGNAL(finished()), this, SLOT(fillThreadFinished()), Qt::BlockingQueuedConnection);
 | |
|     connect(fillThread, SIGNAL(progress(int,int)), this, SLOT(fillThreadProgress(int,int)));
 | |
| 
 | |
| #ifdef DEBUG_FORUMS
 | |
|     std::cerr << "ForumsDialog::insertThreads() Start fill thread" << std::endl;
 | |
| #endif
 | |
| 
 | |
|     // start thread
 | |
|     fillThread->start();
 | |
| }
 | |
| 
 | |
| void ForumsDialog::FillThreads(QList<QTreeWidgetItem *> &ThreadList, bool expandNewMessages, QList<QTreeWidgetItem*> &itemToExpand)
 | |
| {
 | |
| #ifdef DEBUG_FORUMS
 | |
|     std::cerr << "ForumsDialog::FillThreads()" << std::endl;
 | |
| #endif
 | |
| 
 | |
|     int Index = 0;
 | |
|     QTreeWidgetItem *Thread;
 | |
|     QList<QTreeWidgetItem *>::iterator NewThread;
 | |
| 
 | |
|     // delete not existing
 | |
|     while (Index < ui.threadTreeWidget->topLevelItemCount ()) {
 | |
|         Thread = ui.threadTreeWidget->topLevelItem (Index);
 | |
| 
 | |
|         // search existing new thread
 | |
|         int Found = -1;
 | |
|         for (NewThread = ThreadList.begin (); NewThread != ThreadList.end (); NewThread++) {
 | |
|             if (Thread->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == (*NewThread)->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) {
 | |
|                 // found it
 | |
|                 Found = Index;
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         if (Found >= 0) {
 | |
|             Index++;
 | |
|         } else {
 | |
|             delete (ui.threadTreeWidget->takeTopLevelItem (Index));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // iterate all new threads
 | |
|     for (NewThread = ThreadList.begin (); NewThread != ThreadList.end (); NewThread++) {
 | |
|         // search existing thread
 | |
|         int Found = -1;
 | |
|         int Count = ui.threadTreeWidget->topLevelItemCount ();
 | |
|         for (Index = 0; Index < Count; Index++) {
 | |
|             Thread = ui.threadTreeWidget->topLevelItem (Index);
 | |
|             if (Thread->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == (*NewThread)->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) {
 | |
|                 // found it
 | |
|                 Found = Index;
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (Found >= 0) {
 | |
|             // set child data
 | |
|             int i;
 | |
|             for (i = 0; i < COLUMN_THREAD_COUNT; i++) {
 | |
|                 Thread->setText (i, (*NewThread)->text (i));
 | |
|             }
 | |
|             for (i = 0; i < ROLE_THREAD_COUNT; i++) {
 | |
|                 Thread->setData (COLUMN_THREAD_DATA, Qt::UserRole + i, (*NewThread)->data (COLUMN_THREAD_DATA, Qt::UserRole + i));
 | |
|             }
 | |
| 
 | |
|             // fill recursive
 | |
|             FillChildren (Thread, *NewThread, expandNewMessages, itemToExpand);
 | |
|         } else {
 | |
|             // add new thread
 | |
|             ui.threadTreeWidget->addTopLevelItem (*NewThread);
 | |
|             Thread = *NewThread;
 | |
|             *NewThread = NULL;
 | |
|         }
 | |
| 
 | |
|         uint32_t status = Thread->data (COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt();
 | |
|         if (expandNewMessages && IS_UNREAD(status)) {
 | |
|             QTreeWidgetItem *pParent = Thread;
 | |
|             while ((pParent = pParent->parent()) != NULL) {
 | |
|                 if (std::find(itemToExpand.begin(), itemToExpand.end(), pParent) == itemToExpand.end()) {
 | |
|                     itemToExpand.push_back(pParent);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| #ifdef DEBUG_FORUMS
 | |
|     std::cerr << "ForumsDialog::FillThreads() done" << std::endl;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void ForumsDialog::FillChildren(QTreeWidgetItem *Parent, QTreeWidgetItem *NewParent, bool expandNewMessages, QList<QTreeWidgetItem*> &itemToExpand)
 | |
| {
 | |
|     int Index = 0;
 | |
|     int NewIndex;
 | |
|     int NewCount = NewParent->childCount();
 | |
| 
 | |
|     QTreeWidgetItem *Child;
 | |
|     QTreeWidgetItem *NewChild;
 | |
| 
 | |
|     // delete not existing
 | |
|     while (Index < Parent->childCount ()) {
 | |
|         Child = Parent->child (Index);
 | |
| 
 | |
|         // search existing new child
 | |
|         int Found = -1;
 | |
|         int Count = NewParent->childCount();
 | |
|         for (NewIndex = 0; NewIndex < Count; NewIndex++) {
 | |
|             NewChild = NewParent->child (NewIndex);
 | |
|             if (NewChild->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == Child->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) {
 | |
|                 // found it
 | |
|                 Found = Index;
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         if (Found >= 0) {
 | |
|             Index++;
 | |
|         } else {
 | |
|             delete (Parent->takeChild (Index));
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // iterate all new children
 | |
|     for (NewIndex = 0; NewIndex < NewCount; NewIndex++) {
 | |
|         NewChild = NewParent->child (NewIndex);
 | |
| 
 | |
|         // search existing child
 | |
|         int Found = -1;
 | |
|         int Count = Parent->childCount();
 | |
|         for (Index = 0; Index < Count; Index++) {
 | |
|             Child = Parent->child (Index);
 | |
|             if (Child->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID) == NewChild->data (COLUMN_THREAD_DATA, ROLE_THREAD_MSGID)) {
 | |
|                 // found it
 | |
|                 Found = Index;
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (Found >= 0) {
 | |
|             // set child data
 | |
|             int i;
 | |
|             for (i = 0; i < COLUMN_THREAD_COUNT; i++) {
 | |
|                 Child->setText (i, NewChild->text (i));
 | |
|             }
 | |
|             for (i = 0; i < ROLE_THREAD_COUNT; i++) {
 | |
|                 Child->setData (COLUMN_THREAD_DATA, Qt::UserRole + i, NewChild->data (COLUMN_THREAD_DATA, Qt::UserRole + i));
 | |
|             }
 | |
| 
 | |
|             // fill recursive
 | |
|             FillChildren (Child, NewChild, expandNewMessages, itemToExpand);
 | |
|         } else {
 | |
|             // add new child
 | |
|             Child = NewParent->takeChild(NewIndex);
 | |
|             Parent->addChild (Child);
 | |
|             NewIndex--;
 | |
|             NewCount--;
 | |
|         }
 | |
| 
 | |
|         uint32_t status = Child->data (COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt();
 | |
|         if (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);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ForumsDialog::insertPost()
 | |
| {
 | |
|     if ((mCurrForumId == "") || (mCurrThreadId == ""))
 | |
|     {
 | |
|         ui.postText->setText("");
 | |
|         ui.threadTitle->setText("");
 | |
|         ui.previousButton->setEnabled(false);
 | |
|         ui.nextButton->setEnabled(false);
 | |
|         ui.newmessageButton->setEnabled (false);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     QTreeWidgetItem *curr = ui.threadTreeWidget->currentItem();
 | |
|     if (curr) {
 | |
|         QTreeWidgetItem *Parent = curr->parent ();
 | |
|         int Index = Parent ? Parent->indexOfChild (curr) : ui.threadTreeWidget->indexOfTopLevelItem (curr);
 | |
|         int Count = Parent ? Parent->childCount () : ui.threadTreeWidget->topLevelItemCount ();
 | |
|         ui.previousButton->setEnabled (Index > 0);
 | |
|         ui.nextButton->setEnabled (Index < Count - 1);
 | |
|     } else {
 | |
|         // there is something wrong
 | |
|         ui.previousButton->setEnabled(false);
 | |
|         ui.nextButton->setEnabled(false);
 | |
| 		return;
 | |
|     }
 | |
| 
 | |
|     ui.newmessageButton->setEnabled (IS_FORUM_SUBSCRIBED(subscribeFlags) && mCurrThreadId.empty() == false);
 | |
| 
 | |
|     /* get the Post */
 | |
|     ForumMsgInfo msg;
 | |
|     if (!rsForums->getForumMessage(mCurrForumId, mCurrThreadId, msg))
 | |
|     {
 | |
|         ui.postText->setText("");
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     bool bSetToReadOnActive = Settings->getForumMsgSetToReadOnActivate();
 | |
|     uint32_t status = curr->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt();
 | |
| 
 | |
|     QList<QTreeWidgetItem*> Row;
 | |
|     Row.append(curr);
 | |
|     if (status & FORUM_MSG_STATUS_READ) {
 | |
|         if (bSetToReadOnActive && (status & FORUM_MSG_STATUS_UNREAD_BY_USER)) {
 | |
|             /* set to read */
 | |
|             setMsgAsReadUnread(Row, true);
 | |
|         }
 | |
|     } else {
 | |
|         /* set to read */
 | |
|         if (bSetToReadOnActive) {
 | |
|             setMsgAsReadUnread(Row, true);
 | |
|         } else {
 | |
|             /* set to unread by user */
 | |
|             setMsgAsReadUnread(Row, false);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     QString extraTxt = RsHtml::formatText(QString::fromStdWString(msg.msg), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS);
 | |
| 
 | |
|     ui.postText->setHtml(extraTxt);
 | |
|     ui.threadTitle->setText(QString::fromStdWString(msg.title));
 | |
| }
 | |
| 
 | |
| void ForumsDialog::previousMessage ()
 | |
| {
 | |
|     QTreeWidgetItem *Item = ui.threadTreeWidget->currentItem ();
 | |
|     if (Item == NULL) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     QTreeWidgetItem *Parent = Item->parent ();
 | |
|     int Index = Parent ? Parent->indexOfChild (Item) : ui.threadTreeWidget->indexOfTopLevelItem (Item);
 | |
|     if (Index > 0) {
 | |
|         QTreeWidgetItem *Previous = Parent ? Parent->child (Index - 1) : ui.threadTreeWidget->topLevelItem (Index - 1);
 | |
|         if (Previous) {
 | |
|             ui.threadTreeWidget->setCurrentItem (Previous);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ForumsDialog::nextMessage ()
 | |
| {
 | |
|     QTreeWidgetItem *Item = ui.threadTreeWidget->currentItem ();
 | |
|     if (Item == NULL) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     QTreeWidgetItem *Parent = Item->parent ();
 | |
|     int Index = Parent ? Parent->indexOfChild (Item) : ui.threadTreeWidget->indexOfTopLevelItem (Item);
 | |
|     int Count = Parent ? Parent->childCount () : ui.threadTreeWidget->topLevelItemCount ();
 | |
|     if (Index < Count - 1) {
 | |
|         QTreeWidgetItem *Next = Parent ? Parent->child (Index + 1) : ui.threadTreeWidget->topLevelItem (Index + 1);
 | |
|         if (Next) {
 | |
|             ui.threadTreeWidget->setCurrentItem (Next);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ForumsDialog::downloadAllFiles()
 | |
| {
 | |
| 	QStringList urls;
 | |
| 	if (RsHtml::findAnchors(ui.postText->toHtml(), urls) == false) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (urls.count() == 0) {
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	RetroShareLink::process(urls, RetroShareLink::TYPE_FILE, true);
 | |
| }
 | |
| 
 | |
| // TODO
 | |
| #if 0
 | |
| void ForumsDialog::removemessage()
 | |
| {
 | |
| 	//std::cerr << "ForumsDialog::removemessage()" << std::endl;
 | |
| 	std::string cid, mid;
 | |
| 	if (!getCurrentMsg(cid, mid))
 | |
| 	{
 | |
| 		//std::cerr << "ForumsDialog::removemessage()";
 | |
| 		//std::cerr << " No Message selected" << std::endl;
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	rsMsgs -> MessageDelete(mid);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /* get selected messages
 | |
|    the messages tree is single selected, but who knows ... */
 | |
| int ForumsDialog::getSelectedMsgCount(QList<QTreeWidgetItem*> *pRows, QList<QTreeWidgetItem*> *pRowsRead, QList<QTreeWidgetItem*> *pRowsUnread)
 | |
| {
 | |
|     if (pRowsRead) pRowsRead->clear();
 | |
|     if (pRowsUnread) pRowsUnread->clear();
 | |
| 
 | |
|     QList<QTreeWidgetItem*> selectedItems = ui.threadTreeWidget->selectedItems();
 | |
|     for(QList<QTreeWidgetItem*>::iterator it = selectedItems.begin(); it != selectedItems.end(); it++) {
 | |
|         if (pRows) pRows->append(*it);
 | |
|         if (pRowsRead || pRowsUnread) {
 | |
|             uint32_t status = (*it)->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt();
 | |
|             if (IS_UNREAD(status)) {
 | |
|                 if (pRowsUnread) pRowsUnread->append(*it);
 | |
|             } else {
 | |
|                 if (pRowsRead) pRowsRead->append(*it);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return selectedItems.size();
 | |
| }
 | |
| 
 | |
| void ForumsDialog::setMsgAsReadUnread(QList<QTreeWidgetItem*> &Rows, bool bRead)
 | |
| {
 | |
|     QList<QTreeWidgetItem*>::iterator Row;
 | |
|     std::list<QTreeWidgetItem*> changedItems;
 | |
| 
 | |
|     for (Row = Rows.begin(); Row != Rows.end(); Row++) {
 | |
|         if ((*Row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_MISSING).toBool()) {
 | |
|             /* Missing message */
 | |
|             continue;
 | |
|         }
 | |
| 
 | |
|         uint32_t status = (*Row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt();
 | |
| 
 | |
|         /* set always as read ... */
 | |
|         uint32_t statusNew = status | FORUM_MSG_STATUS_READ;
 | |
|         if (bRead) {
 | |
|             /* ... and as read by user */
 | |
|             statusNew &= ~FORUM_MSG_STATUS_UNREAD_BY_USER;
 | |
|         } else {
 | |
|             /* ... and as unread by user */
 | |
|             statusNew |= FORUM_MSG_STATUS_UNREAD_BY_USER;
 | |
|         }
 | |
|         if (status != statusNew) {
 | |
|             std::string msgId = (*Row)->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString();
 | |
|             rsForums->setMessageStatus(mCurrForumId, msgId, statusNew, FORUM_MSG_STATUS_READ | FORUM_MSG_STATUS_UNREAD_BY_USER);
 | |
| 
 | |
|             (*Row)->setData(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS, statusNew);
 | |
| 
 | |
|             QTreeWidgetItem *parentItem = *Row;
 | |
|             while (parentItem->parent()) {
 | |
|                 parentItem = parentItem->parent();
 | |
|             }
 | |
|             if (std::find(changedItems.begin(), changedItems.end(), parentItem) == changedItems.end()) {
 | |
|                 changedItems.push_back(parentItem);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (changedItems.size()) {
 | |
|         for (std::list<QTreeWidgetItem*>::iterator it = changedItems.begin(); it != changedItems.end(); it++) {
 | |
|             CalculateIconsAndFonts(*it);
 | |
|         }
 | |
|         updateMessageSummaryList(mCurrForumId);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ForumsDialog::markMsgAsReadUnread (bool bRead, bool bChildren, bool bForum)
 | |
| {
 | |
|     if (mCurrForumId.empty() || !IS_FORUM_SUBSCRIBED(subscribeFlags)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     /* get selected messages */
 | |
|     QList<QTreeWidgetItem*> Rows;
 | |
|     if (bForum) {
 | |
|         int itemCount = ui.threadTreeWidget->topLevelItemCount();
 | |
|         for (int item = 0; item < itemCount; item++) {
 | |
|             Rows.push_back(ui.threadTreeWidget->topLevelItem(item));
 | |
|         }
 | |
|     } else {
 | |
|         getSelectedMsgCount (&Rows, NULL, NULL);
 | |
|     }
 | |
| 
 | |
|     if (bChildren) {
 | |
|         /* add children */
 | |
|         QList<QTreeWidgetItem*> AllRows;
 | |
| 
 | |
|         while (Rows.isEmpty() == false) {
 | |
|             QTreeWidgetItem *pRow = Rows.takeFirst();
 | |
| 
 | |
|             /* add only items with the right state or with not FORUM_MSG_STATUS_READ */
 | |
|             uint32_t status = pRow->data(COLUMN_THREAD_DATA, ROLE_THREAD_STATUS).toUInt();
 | |
|              if (IS_UNREAD(status) == bRead || (status & FORUM_MSG_STATUS_READ) == 0) {
 | |
|                 AllRows.append(pRow);
 | |
|             }
 | |
| 
 | |
|             for (int i = 0; i < pRow->childCount(); i++) {
 | |
|                 /* add child to main list and let the main loop do the work */
 | |
|                 Rows.append(pRow->child(i));
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (AllRows.isEmpty()) {
 | |
|             /* nothing to do */
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         setMsgAsReadUnread (AllRows, bRead);
 | |
| 
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     setMsgAsReadUnread (Rows, bRead);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::markMsgAsRead()
 | |
| {
 | |
|     markMsgAsReadUnread(true, false, false);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::markMsgAsReadChildren()
 | |
| {
 | |
|     markMsgAsReadUnread(true, true, false);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::markMsgAsReadAll()
 | |
| {
 | |
|     markMsgAsReadUnread(true, true, true);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::markMsgAsUnread()
 | |
| {
 | |
|     markMsgAsReadUnread(false, false, false);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::markMsgAsUnreadChildren()
 | |
| {
 | |
|     markMsgAsReadUnread(false, true, false);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::markMsgAsUnreadAll()
 | |
| {
 | |
|     markMsgAsReadUnread(false, true, true);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::copyForumLink()
 | |
| {
 | |
|     if (mCurrForumId.empty()) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     ForumInfo fi;
 | |
|     if (rsForums->getForumInfo(mCurrForumId, fi)) {
 | |
|         RetroShareLink link;
 | |
|         if (link.createForum(fi.forumId, "")) {
 | |
|             std::vector<RetroShareLink> urls;
 | |
|             urls.push_back(link);
 | |
|             RSLinkClipboard::copyLinks(urls);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ForumsDialog::copyMessageLink()
 | |
| {
 | |
|     if (mCurrForumId.empty() || mCurrThreadId.empty()) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     ForumInfo fi;
 | |
|     if (rsForums->getForumInfo(mCurrForumId, fi)) {
 | |
|         RetroShareLink link;
 | |
|         if (link.createForum(mCurrForumId, mCurrThreadId)) {
 | |
|             std::vector<RetroShareLink> urls;
 | |
|             urls.push_back(link);
 | |
|             RSLinkClipboard::copyLinks(urls);
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ForumsDialog::newforum()
 | |
| {
 | |
|     CreateForum cf (this);
 | |
|     cf.exec ();
 | |
| }
 | |
| 
 | |
| void ForumsDialog::createmessage()
 | |
| {
 | |
|     if (mCurrForumId.empty () || !IS_FORUM_SUBSCRIBED(subscribeFlags)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     CreateForumMsg *cfm = new CreateForumMsg(mCurrForumId, mCurrThreadId);
 | |
|     cfm->show();
 | |
| 
 | |
|     /* window will destroy itself! */
 | |
| }
 | |
| 
 | |
| void ForumsDialog::createthread()
 | |
| {
 | |
|     if (mCurrForumId.empty ()) {
 | |
|         QMessageBox::information(this, tr("RetroShare"), tr("No Forum Selected!"));
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     CreateForumMsg *cfm = new CreateForumMsg(mCurrForumId, "");
 | |
|     cfm->setWindowTitle(tr("Start New Thread"));
 | |
|     cfm->show();
 | |
| 
 | |
|     /* window will destroy itself! */
 | |
| }
 | |
| 
 | |
| void ForumsDialog::subscribeToForum()
 | |
| {
 | |
| 	forumSubscribe(true);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::unsubscribeToForum()
 | |
| {
 | |
| 	forumSubscribe(false);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::forumSubscribe(bool subscribe)
 | |
| {
 | |
|     if (mCurrForumId.empty()) {
 | |
|             return;
 | |
|     }
 | |
| 
 | |
|     rsForums->forumSubscribe(mCurrForumId, subscribe);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::showForumDetails()
 | |
| {
 | |
|     if (mCurrForumId.empty()) {
 | |
|             return;
 | |
|     }
 | |
| 
 | |
|     ForumDetails fui;
 | |
| 
 | |
|     fui.showDetails (mCurrForumId);
 | |
|     fui.exec ();
 | |
| }
 | |
| 
 | |
| void ForumsDialog::editForumDetails()
 | |
| {
 | |
|     if (mCurrForumId.empty()) {
 | |
|             return;
 | |
|     }
 | |
| 
 | |
|     EditForumDetails editUi(mCurrForumId, this);
 | |
|     editUi.exec();
 | |
| }
 | |
| 
 | |
| void ForumsDialog::replytomessage()
 | |
| {
 | |
|     if (mCurrForumId.empty()) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     std::string fId = mCurrForumId;
 | |
|     std::string pId = mCurrThreadId;
 | |
| 
 | |
|     ForumMsgInfo msgInfo ;
 | |
|     rsForums->getForumMessage(fId,pId,msgInfo) ;
 | |
| 
 | |
|     if (rsPeers->getPeerName(msgInfo.srcId) !="")
 | |
|     {
 | |
|         MessageComposer *nMsgDialog = MessageComposer::newMsg();
 | |
|         nMsgDialog->insertTitleText(QString::fromStdWString(msgInfo.title), MessageComposer::REPLY);
 | |
| 
 | |
|         QTextDocument doc ;
 | |
|         doc.setHtml(QString::fromStdWString(msgInfo.msg)) ;
 | |
| 
 | |
|         nMsgDialog->insertPastedText(doc.toPlainText());
 | |
|         nMsgDialog->addRecipient(MessageComposer::TO, msgInfo.srcId, false);
 | |
|         nMsgDialog->show();
 | |
|         nMsgDialog->activateWindow();
 | |
| 
 | |
|         /* window will destroy itself! */
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         QMessageBox::information(this, tr("RetroShare"),tr("You cant reply a Anonymous Author"));
 | |
|     }
 | |
| }
 | |
| 
 | |
| void ForumsDialog::filterRegExpChanged()
 | |
| {
 | |
| //    QRegExp regExp(ui.filterPatternLineEdit->text(),  Qt::CaseInsensitive , QRegExp::FixedString);
 | |
| //    proxyModel->setFilterRegExp(regExp);
 | |
| 
 | |
|     QString text = ui.filterPatternLineEdit->text();
 | |
| 
 | |
|     if (text.isEmpty()) {
 | |
|         ui.clearButton->hide();
 | |
|     } else {
 | |
|         ui.clearButton->show();
 | |
|     }
 | |
| 
 | |
|     FilterItems();
 | |
| }
 | |
| 
 | |
| /* clear Filter */
 | |
| void ForumsDialog::clearFilter()
 | |
| {
 | |
|     ui.filterPatternLineEdit->clear();
 | |
|     ui.filterPatternLineEdit->setFocus();
 | |
| }
 | |
| 
 | |
| void ForumsDialog::changedViewBox()
 | |
| {
 | |
|     if (m_bProcessSettings) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     // save index
 | |
|     Settings->setValueToGroup("ForumsDialog", "viewBox", ui.viewBox->currentIndex());
 | |
| 
 | |
|     insertThreads();
 | |
| }
 | |
| 
 | |
| void ForumsDialog::filterColumnChanged()
 | |
| {
 | |
|     if (m_bProcessSettings) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     int filterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex());
 | |
|     if (filterColumn == COLUMN_THREAD_CONTENT) {
 | |
|         // need content ... refill
 | |
|         insertThreads();
 | |
|     } else {
 | |
|         FilterItems();
 | |
|     }
 | |
| 
 | |
|     // save index
 | |
|     Settings->setValueToGroup("ForumsDialog", "filterColumn", filterColumn);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::FilterItems()
 | |
| {
 | |
|     QString sPattern = ui.filterPatternLineEdit->text();
 | |
|     int filterColumn = FilterColumnFromComboBox(ui.filterColumnComboBox->currentIndex());
 | |
| 
 | |
|     int nCount = ui.threadTreeWidget->topLevelItemCount ();
 | |
|     for (int nIndex = 0; nIndex < nCount; nIndex++) {
 | |
|         FilterItem(ui.threadTreeWidget->topLevelItem(nIndex), sPattern, filterColumn);
 | |
|     }
 | |
| }
 | |
| 
 | |
| bool ForumsDialog::FilterItem(QTreeWidgetItem *pItem, QString &sPattern, int filterColumn)
 | |
| {
 | |
|     bool bVisible = true;
 | |
| 
 | |
|     if (sPattern.isEmpty() == false) {
 | |
|         if (pItem->text(filterColumn).contains(sPattern, Qt::CaseInsensitive) == false) {
 | |
|             bVisible = false;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     int nVisibleChildCount = 0;
 | |
|     int nCount = pItem->childCount();
 | |
|     for (int nIndex = 0; nIndex < nCount; nIndex++) {
 | |
|         if (FilterItem(pItem->child(nIndex), sPattern, filterColumn)) {
 | |
|             nVisibleChildCount++;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (bVisible || nVisibleChildCount) {
 | |
|         pItem->setHidden(false);
 | |
|     } else {
 | |
|         pItem->setHidden(true);
 | |
|     }
 | |
| 
 | |
|     return (bVisible || nVisibleChildCount);
 | |
| }
 | |
| 
 | |
| void ForumsDialog::updateMessageSummaryList(std::string forumId)
 | |
| {
 | |
|     QTreeWidgetItem *items[2] = { yourForums, subscribedForums };
 | |
| 
 | |
|     for (int item = 0; item < 2; item++) {
 | |
|         int child;
 | |
|         int childCount = items[item]->childCount();
 | |
|         for (child = 0; child < childCount; child++) {
 | |
|             QTreeWidgetItem *childItem = items[item]->child(child);
 | |
|             std::string childId = ui.forumTreeWidget->itemId(childItem).toStdString();
 | |
|             if (childId.empty()) {
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             if (forumId.empty() || childId == forumId) {
 | |
|                 /* calculate unread messages */
 | |
|                 unsigned int newMessageCount = 0;
 | |
|                 unsigned int unreadMessageCount = 0;
 | |
|                 rsForums->getMessageCount(childId, newMessageCount, unreadMessageCount);
 | |
| 
 | |
|                 ui.forumTreeWidget->setUnreadCount(childItem, unreadMessageCount);
 | |
| 
 | |
|                 if (forumId.empty() == false) {
 | |
|                     /* Calculate only this forum */
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| bool ForumsDialog::navigate(const std::string& forumId, const std::string& msgId)
 | |
| {
 | |
|     if (forumId.empty()) {
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     if (ui.forumTreeWidget->activateId(QString::fromStdString(forumId), msgId.empty()) == NULL) {
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /* Threads are filled in changedForum */
 | |
|     if (mCurrForumId != forumId) {
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     if (msgId.empty()) {
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /* Search exisiting item */
 | |
|     QTreeWidgetItemIterator itemIterator(ui.threadTreeWidget);
 | |
|     QTreeWidgetItem *item = NULL;
 | |
|     while ((item = *itemIterator) != NULL) {
 | |
|         itemIterator++;
 | |
| 
 | |
|         if (item->data(COLUMN_THREAD_DATA, ROLE_THREAD_MSGID).toString().toStdString() == msgId) {
 | |
|             ui.threadTreeWidget->setCurrentItem(item);
 | |
|             ui.threadTreeWidget->setFocus();
 | |
|             return true;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| void ForumsDialog::generateMassData()
 | |
| {
 | |
| #ifdef DEBUG_FORUMS
 | |
|     if (mCurrForumId.empty ()) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     if (QMessageBox::question(this, "Generate mass data", "Do you really want to generate mass data ?", QMessageBox::Yes|QMessageBox::No, QMessageBox::No) == QMessageBox::No) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     for (int thread = 1; thread < 1000; thread++) {
 | |
|         ForumMsgInfo threadInfo;
 | |
|         threadInfo.forumId = mCurrForumId;
 | |
|         threadInfo.title = QString("Test %1").arg(thread, 3, 10, QChar('0')).toStdWString();
 | |
|         threadInfo.msg = QString("That is only a test").toStdWString();
 | |
| 
 | |
|         if (rsForums->ForumMessageSend(threadInfo) == false) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         for (int msg = 1; msg < 3; msg++) {
 | |
|             ForumMsgInfo msgInfo;
 | |
|             msgInfo.forumId = mCurrForumId;
 | |
|             msgInfo.threadId = threadInfo.msgId;
 | |
|             msgInfo.parentId = threadInfo.msgId;
 | |
|             msgInfo.title = threadInfo.title;
 | |
|             msgInfo.msg = threadInfo.msg;
 | |
| 
 | |
|             if (rsForums->ForumMessageSend(msgInfo) == false) {
 | |
|                 return;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| #endif
 | |
| }
 | |
| 
 | |
| // ForumsFillThread
 | |
| ForumsFillThread::ForumsFillThread(ForumsDialog *parent)
 | |
|     : QThread(parent)
 | |
| {
 | |
|     stopped = false;
 | |
| 
 | |
|     expandNewMessages = Settings->getExpandNewMessages();
 | |
|     fillComplete = false;
 | |
| 
 | |
|     filterColumn = 0;
 | |
|     subscribeFlags = 0;
 | |
|     viewType = 0;
 | |
| }
 | |
| 
 | |
| ForumsFillThread::~ForumsFillThread()
 | |
| {
 | |
| #ifdef DEBUG_FORUMS
 | |
|     std::cerr << "ForumsFillThread::~ForumsFillThread" << std::endl;
 | |
| #endif
 | |
|     // remove all items (when items are available, the thread was terminated)
 | |
|     CleanupItems (items);
 | |
|     itemToExpand.clear();
 | |
| }
 | |
| 
 | |
| void ForumsFillThread::stop()
 | |
| {
 | |
|     stopped = true;
 | |
| }
 | |
| 
 | |
| void ForumsFillThread::run()
 | |
| {
 | |
| #ifdef DEBUG_FORUMS
 | |
|     std::cerr << "ForumsFillThread::run()" << std::endl;
 | |
| #endif
 | |
| 
 | |
|     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 << "ForumsFillThread::run() Adding TopLevel Thread: mId: " << 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::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::fromUtf8(rsPeers->getPeerName(msginfo.srcId).c_str());
 | |
|         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::endl;
 | |
| #endif
 | |
| 
 | |
|             if (rsForums->getForumThreadMsgList(forumId, pId, msgs))
 | |
|             {
 | |
| #ifdef DEBUG_FORUMS
 | |
|                 std::cerr << "ForumsFillThread::run() #Children " << msgs.size() << 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::endl;
 | |
| #endif
 | |
| 
 | |
|                     ForumMsgInfo msginfo;
 | |
|                     if (rsForums->getForumMessage(forumId, mit->msgId, msginfo) == false) {
 | |
| #ifdef DEBUG_FORUMS
 | |
|                         std::cerr << "ForumsFillThread::run() Failed to Get Msg" << 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::fromUtf8(rsPeers->getPeerName(msginfo.srcId).c_str());
 | |
|                     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);
 | |
|     }
 | |
| 
 | |
| #ifdef DEBUG_FORUMS
 | |
|     std::cerr << "ForumsFillThread::run() stopped: " << (wasStopped() ? "yes" : "no") << std::endl;
 | |
| #endif
 | |
| }
 |