Added waiting indicator to group tree for channels/posted when using "Mark all as read/unread".

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@8020 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
thunder2 2015-03-14 21:13:28 +00:00
parent c811d71738
commit d6ca3ffc27
21 changed files with 219 additions and 26 deletions

View File

@ -83,6 +83,9 @@ H [ ] valgrind pass for memory leaks
H [ ] valgrind pass for memory errors
H [ ] valgrind pass for performance
E [ ] remove mktemp => use mkstemp
H [ ] RsGxsDataAccess::processRequests locks mDataMutex until all requests are processed.
Adding a new request or poll for the request status are freezing until the mutex is available.
Packaging
[X] check compilation on debian

View File

@ -578,7 +578,7 @@ void PostedListWidget::insertRelatedPosts(const uint32_t &token)
applyRanking();
}
void PostedListWidget::setAllMessagesRead(bool read)
void PostedListWidget::setAllMessagesReadDo(bool read, uint32_t &token)
{
if (groupId().isNull() || !IS_GROUP_SUBSCRIBED(subscribeFlags())) {
return;
@ -587,7 +587,6 @@ void PostedListWidget::setAllMessagesRead(bool read)
foreach (PostedItem *item, mPostItems) {
RsGxsGrpMsgIdPair msgPair = std::make_pair(item->groupId(), item->messageId());
uint32_t token;
rsPosted->setMessageReadStatus(token, msgPair, read);
}
}

View File

@ -47,7 +47,6 @@ public:
/* GxsMessageFrameWidget */
virtual QIcon groupIcon();
virtual void setAllMessagesRead(bool read);
/* FeedHolder */
virtual QScrollArea *getScrollArea();
@ -66,6 +65,9 @@ protected:
virtual void clearPosts();
virtual bool navigatePostItem(const RsGxsMessageId& msgId);
/* GxsMessageFrameWidget */
virtual void setAllMessagesReadDo(bool read, uint32_t &token);
private slots:
void newPost();

View File

@ -21,6 +21,8 @@
#include <QMenu>
#include <QToolButton>
#include <QLabel>
#include <QMovie>
#include "retroshare/rsgxsflags.h"
#include "GroupTreeWidget.h"
@ -47,6 +49,7 @@
#define ROLE_SEARCH_SCORE Qt::UserRole + 5
#define ROLE_SUBSCRIBE_FLAGS Qt::UserRole + 6
#define ROLE_COLOR Qt::UserRole + 7
#define ROLE_SAVED_ICON Qt::UserRole + 8
#define FILTER_NAME_INDEX 0
#define FILTER_DESC_INDEX 1
@ -351,7 +354,12 @@ void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList<
item->setData(COLUMN_DATA, ROLE_LASTPOST, -lastPost); // negative for correct sorting
/* Set icon */
item->setIcon(COLUMN_NAME, itemInfo.icon);
if (ui->treeWidget->itemWidget(item, COLUMN_NAME)) {
/* Item is waiting, save icon in role */
item->setData(COLUMN_DATA, ROLE_SAVED_ICON, itemInfo.icon);
} else {
item->setIcon(COLUMN_NAME, itemInfo.icon);
}
/* Set popularity */
QString tooltip = PopularityDefs::tooltip(itemInfo.popularity);
@ -465,6 +473,50 @@ QTreeWidgetItem *GroupTreeWidget::activateId(const QString &id, bool focus)
return item;
}
bool GroupTreeWidget::setWaiting(const QString &id, bool wait)
{
QTreeWidgetItem *item = getItemFromId(id);
if (!item) {
return false;
}
QWidget *w = ui->treeWidget->itemWidget(item, COLUMN_NAME);
if (wait) {
if (w) {
/* Allready waiting */
} else {
/* Save icon in role */
QIcon icon = item->icon(COLUMN_NAME);
item->setData(COLUMN_DATA, ROLE_SAVED_ICON, icon);
/* Create empty icon of the same size */
QPixmap pixmap(ui->treeWidget->iconSize());
pixmap.fill(Qt::transparent);
item->setIcon(COLUMN_NAME, QIcon(pixmap));
QLabel *label = new QLabel(this);
QMovie *movie = new QMovie(":/images/loader/circleball-16.gif");
label->setMovie(movie);
ui->treeWidget->setItemWidget(item, COLUMN_NAME, label);
movie->start();
}
} else {
if (w) {
ui->treeWidget->setItemWidget(item, COLUMN_NAME, NULL);
delete(w);
/* Set icon saved in role */
item->setIcon(COLUMN_NAME, item->data(COLUMN_DATA, ROLE_SAVED_ICON).value<QIcon>());
item->setData(COLUMN_DATA, ROLE_SAVED_ICON, QIcon());
}
}
return true;
}
RSTreeWidget *GroupTreeWidget::treeWidget()
{
return ui->treeWidget;

View File

@ -94,6 +94,8 @@ public:
QTreeWidgetItem *getItemFromId(const QString &id);
QTreeWidgetItem *activateId(const QString &id, bool focus);
bool setWaiting(const QString &id, bool wait);
RSTreeWidget *treeWidget();
QColor textColorCategory() const { return mTextColor[GROUPTREEWIDGET_COLOR_CATEGORY]; }

View File

@ -534,6 +534,7 @@ GxsMessageFrameWidget *GxsGroupFrameDialog::createMessageWidget(const RsGxsGroup
ui->messageTabWidget->setTabIcon(index, msgWidget->groupIcon());
connect(msgWidget, SIGNAL(groupChanged(QWidget*)), this, SLOT(messageTabInfoChanged(QWidget*)));
connect(msgWidget, SIGNAL(waitingChanged(QWidget*)), this, SLOT(messageTabWaitingChanged(QWidget*)));
connect(msgWidget, SIGNAL(loadComment(RsGxsGroupId,RsGxsMessageId,QString)), this, SLOT(loadComment(RsGxsGroupId,RsGxsMessageId,QString)));
return msgWidget;
@ -644,6 +645,21 @@ void GxsGroupFrameDialog::messageTabInfoChanged(QWidget *widget)
ui->messageTabWidget->setTabIcon(index, msgWidget->groupIcon());
}
void GxsGroupFrameDialog::messageTabWaitingChanged(QWidget *widget)
{
int index = ui->messageTabWidget->indexOf(widget);
if (index < 0) {
return;
}
GxsMessageFrameWidget *msgWidget = dynamic_cast<GxsMessageFrameWidget*>(ui->messageTabWidget->widget(index));
if (!msgWidget) {
return;
}
ui->groupTreeWidget->setWaiting(QString::fromStdString(msgWidget->groupId().toStdString()), msgWidget->isWaiting());
}
///***** INSERT GROUP LISTS *****/
void GxsGroupFrameDialog::groupInfoToGroupItemInfo(const RsGroupMetaData &groupInfo, GroupItemInfo &groupItemInfo, const RsUserdata */*userdata*/)
{

View File

@ -109,6 +109,7 @@ private slots:
void messageTabCloseRequested(int index);
void messageTabChanged(int index);
void messageTabInfoChanged(QWidget *widget);
void messageTabWaitingChanged(QWidget *widget);
void copyGroupLink();

View File

@ -86,6 +86,15 @@ bool GxsMessageFramePostWidget::navigate(const RsGxsMessageId &msgId)
return navigatePostItem(msgId);
}
bool GxsMessageFramePostWidget::isLoading()
{
if (mStateHelper->isLoading(mTokenTypePosts) || mStateHelper->isLoading(mTokenTypeRelatedPosts)) {
return true;
}
return GxsMessageFrameWidget::isLoading();
}
void GxsMessageFramePostWidget::updateDisplay(bool complete)
{
if (complete) {

View File

@ -43,6 +43,7 @@ public:
virtual QString groupName(bool withUnreadCount);
// virtual QIcon groupIcon() = 0;
virtual bool navigate(const RsGxsMessageId& msgId);
virtual bool isLoading();
/* GXS functions */
virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req);
@ -50,7 +51,9 @@ public:
int subscribeFlags() { return mSubscribeFlags; }
protected:
/* RsGxsUpdateBroadcastWidget */
virtual void updateDisplay(bool complete);
virtual void groupNameChanged(const QString &/*name*/) {}
virtual void clearPosts() = 0;

View File

@ -31,10 +31,23 @@ GxsMessageFrameWidget::GxsMessageFrameWidget(RsGxsIfaceHelper *ifaceImpl, QWidge
mTokenQueue = new TokenQueue(ifaceImpl->getTokenService(), this);
mStateHelper = new UIStateHelper(this);
/* Set read status */
mTokenTypeAcknowledgeReadStatus = nextTokenType();
mAcknowledgeReadStatusToken = 0;
/* Add dummy entry to store waiting status */
mStateHelper->addWidget(mTokenTypeAcknowledgeReadStatus, NULL, 0);
}
GxsMessageFrameWidget::~GxsMessageFrameWidget()
{
if (mStateHelper->isLoading(mTokenTypeAcknowledgeReadStatus)) {
mStateHelper->setLoading(mTokenTypeAcknowledgeReadStatus, false);
emit waitingChanged(this);
}
delete(mTokenQueue);
}
@ -43,6 +56,20 @@ const RsGxsGroupId &GxsMessageFrameWidget::groupId()
return mGroupId;
}
bool GxsMessageFrameWidget::isLoading()
{
return false;
}
bool GxsMessageFrameWidget::isWaiting()
{
if (mStateHelper->isLoading(mTokenTypeAcknowledgeReadStatus)) {
return true;
}
return false;
}
void GxsMessageFrameWidget::setGroupId(const RsGxsGroupId &groupId)
{
if (mGroupId == groupId) {
@ -51,13 +78,47 @@ void GxsMessageFrameWidget::setGroupId(const RsGxsGroupId &groupId)
}
}
mGroupId = groupId;
mAcknowledgeReadStatusToken = 0;
if (mStateHelper->isLoading(mTokenTypeAcknowledgeReadStatus)) {
mStateHelper->setLoading(mTokenTypeAcknowledgeReadStatus, false);
emit waitingChanged(this);
}
mGroupId = groupId;
groupIdChanged();
}
void GxsMessageFrameWidget::loadRequest(const TokenQueue */*queue*/, const TokenRequest &/*req*/)
void GxsMessageFrameWidget::setAllMessagesRead(bool read)
{
uint32_t token = 0;
setAllMessagesReadDo(read, token);
if (token) {
/* Wait for acknowlegde of the token */
mAcknowledgeReadStatusToken = token;
mTokenQueue->queueRequest(mAcknowledgeReadStatusToken, 0, 0, mTokenTypeAcknowledgeReadStatus);
mStateHelper->setLoading(mTokenTypeAcknowledgeReadStatus, true);
emit waitingChanged(this);
}
}
void GxsMessageFrameWidget::loadRequest(const TokenQueue *queue, const TokenRequest &req)
{
if (queue == mTokenQueue)
{
if (req.mUserType == mTokenTypeAcknowledgeReadStatus) {
if (mAcknowledgeReadStatusToken == req.mToken) {
/* Set read status is finished */
mStateHelper->setLoading(mTokenTypeAcknowledgeReadStatus, false);
emit waitingChanged(this);
}
return;
}
}
std::cerr << "GxsMessageFrameWidget::loadRequest() ERROR: INVALID TYPE";
std::cerr << std::endl;
}

View File

@ -38,12 +38,14 @@ public:
const RsGxsGroupId &groupId();
void setGroupId(const RsGxsGroupId &groupId);
void setAllMessagesRead(bool read);
virtual void groupIdChanged() = 0;
virtual QString groupName(bool withUnreadCount) = 0;
virtual QIcon groupIcon() = 0;
virtual void setAllMessagesRead(bool read) = 0;
virtual bool navigate(const RsGxsMessageId& msgId) = 0;
virtual bool isLoading();
virtual bool isWaiting();
/* GXS functions */
uint32_t nextTokenType() { return ++mNextTokenType; }
@ -51,12 +53,20 @@ public:
signals:
void groupChanged(QWidget *widget);
void waitingChanged(QWidget *widget);
void loadComment(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId, const QString &title);
protected:
virtual void setAllMessagesReadDo(bool read, uint32_t &token) = 0;
protected:
TokenQueue *mTokenQueue;
UIStateHelper *mStateHelper;
/* Set read status */
uint32_t mTokenTypeAcknowledgeReadStatus;
uint32_t mAcknowledgeReadStatusToken;
private:
RsGxsGroupId mGroupId; /* current group */
uint32_t mNextTokenType;

View File

@ -503,29 +503,45 @@ void GxsChannelPostsWidget::insertRelatedPosts(const uint32_t &token)
insertChannelPosts(posts, NULL, true);
}
class GxsChannelPostsReadData
{
public:
GxsChannelPostsReadData(bool read)
{
mRead = read;
mLastToken = 0;
}
public:
bool mRead;
uint32_t mLastToken;
};
static void setAllMessagesReadCallback(FeedItem *feedItem, void *data)
{
GxsChannelPostItem *channelPostItem = dynamic_cast<GxsChannelPostItem*>(feedItem);
if (!channelPostItem) {
return;
}
GxsChannelPostItem *channelPostItem = dynamic_cast<GxsChannelPostItem*>(feedItem);
if (!channelPostItem) {
return;
}
bool is_not_new = !channelPostItem->isUnread() ;
GxsChannelPostsReadData *readData = (GxsChannelPostsReadData*) data;
bool is_not_new = !channelPostItem->isUnread() ;
if(is_not_new == *(bool*)data)
return ;
if(is_not_new == readData->mRead)
return ;
RsGxsGrpMsgIdPair msgPair = std::make_pair(channelPostItem->groupId(), channelPostItem->messageId());
uint32_t token;
rsGxsChannels->setMessageReadStatus(token, msgPair, *((bool*) data));
RsGxsGrpMsgIdPair msgPair = std::make_pair(channelPostItem->groupId(), channelPostItem->messageId());
rsGxsChannels->setMessageReadStatus(readData->mLastToken, msgPair, readData->mRead);
}
void GxsChannelPostsWidget::setAllMessagesRead(bool read)
void GxsChannelPostsWidget::setAllMessagesReadDo(bool read, uint32_t &token)
{
if (groupId().isNull() || !IS_GROUP_SUBSCRIBED(subscribeFlags())) {
return;
}
ui->feedWidget->withAll(setAllMessagesReadCallback, &read);
GxsChannelPostsReadData data(read);
ui->feedWidget->withAll(setAllMessagesReadCallback, &data);
token = data.mLastToken;
}

View File

@ -56,7 +56,6 @@ public:
/* GxsMessageFrameWidget */
virtual QIcon groupIcon();
virtual void setAllMessagesRead(bool read);
/* FeedHolder */
virtual QScrollArea *getScrollArea();
@ -75,6 +74,9 @@ protected:
virtual void fillThreadCreatePost(const QVariant &post, bool related, int current, int count);
virtual bool navigatePostItem(const RsGxsMessageId& msgId);
/* GxsMessageFrameWidget */
virtual void setAllMessagesReadDo(bool read, uint32_t &token);
private slots:
void createMsg();
void toggleAutoDownload();

View File

@ -1511,7 +1511,7 @@ void GxsForumThreadWidget::markMsgAsUnreadChildren()
markMsgAsReadUnread(false, true, false);
}
void GxsForumThreadWidget::setAllMessagesRead(bool read)
void GxsForumThreadWidget::setAllMessagesReadDo(bool read, uint32_t &/*token*/)
{
markMsgAsReadUnread(read, true, true);
}
@ -1543,6 +1543,15 @@ bool GxsForumThreadWidget::navigate(const RsGxsMessageId &msgId)
return false;
}
bool GxsForumThreadWidget::isLoading()
{
if (mStateHelper->isLoading(mTokenTypeGroupData) || mFillThread) {
return true;
}
return GxsMessageFrameWidget::isLoading();
}
void GxsForumThreadWidget::copyMessageLink()
{
if (groupId().isNull() || mThreadId.isNull()) {

View File

@ -43,8 +43,8 @@ public:
virtual void groupIdChanged();
virtual QString groupName(bool withUnreadCount);
virtual QIcon groupIcon();
virtual void setAllMessagesRead(bool read);
virtual bool navigate(const RsGxsMessageId& msgId);
virtual bool isLoading();
unsigned int newCount() { return mNewCount; }
unsigned int unreadCount() { return mUnreadCount; }
@ -58,8 +58,13 @@ public:
protected:
bool eventFilter(QObject *obj, QEvent *ev);
void changeEvent(QEvent *e);
/* RsGxsUpdateBroadcastWidget */
virtual void updateDisplay(bool complete);
/* GxsMessageFrameWidget */
virtual void setAllMessagesReadDo(bool read, uint32_t &token);
private slots:
/** Create the context popup menu and it's submenus */
void threadListCustomPopupMenu(QPoint point);

View File

@ -462,8 +462,9 @@
<file>images/trustsettings.png</file>
<file>images/uploads.png</file>
<file>images/headerFrame.png</file>
<file>images/loader/16-loader.gif</file>
<file>images/loader/32-loader.gif</file>
<file>images/loader/indicator-16.gif</file>
<file>images/loader/indicator-32.gif</file>
<file>images/loader/circleball-16.gif</file>
<file>images/loader/progress.gif</file>
<file>images/mimetypes/pdf.png</file>
<file>images/mimetypes/rscollection-16.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,2 @@
More at
http://ajaxload.info/

View File

@ -34,7 +34,7 @@ HashingStatus::HashingStatus(QWidget *parent)
hbox->setMargin(0);
hbox->setSpacing(6);
movie = new QMovie(":/images/loader/16-loader.gif");
movie = new QMovie(":/images/loader/indicator-16.gif");
movie->setSpeed(80); // 2x speed
hashloader = new QLabel(this);
hashloader->setMovie(movie);