Added basic widget RSFeedWidget for showing feed items in a QTreeWidget as replacement for the QScrollArea.

- Use sort of QTreeWidget
- Filter items
- Open/collapse selected item with +/-
- Remove selecteds item with dselete key

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@7478 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
thunder2 2014-08-01 14:49:58 +00:00
parent e588b25b67
commit d13aa90b2b
20 changed files with 841 additions and 183 deletions

View file

@ -32,14 +32,14 @@
/** Constructor */ /** Constructor */
PostedItem::PostedItem(FeedHolder *parent, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome) : PostedItem::PostedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome) :
GxsFeedItem(parent, feedId, groupId, messageId, isHome, rsPosted, true, false) GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsPosted, true, false)
{ {
setup(); setup();
} }
PostedItem::PostedItem(FeedHolder *parent, uint32_t feedId, const RsPostedPost &post, bool isHome) : PostedItem::PostedItem(FeedHolder *feedHolder, uint32_t feedId, const RsPostedPost &post, bool isHome) :
GxsFeedItem(parent, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsPosted, false, false), GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsPosted, false, false),
mPost(post) mPost(post)
{ {
setup(); setup();
@ -115,7 +115,7 @@ void PostedItem::setContent(const RsPostedPost &post)
// FIX THIS UP LATER. // FIX THIS UP LATER.
notes->setText(QString::fromUtf8(post.mNotes.c_str())); notes->setText(QString::fromUtf8(post.mNotes.c_str()));
// differences between Feed or Top of Comment. // differences between Feed or Top of Comment.
if (mParent) if (mFeedHolder)
{ {
// feed. // feed.
frame_notes->hide(); frame_notes->hide();
@ -218,9 +218,10 @@ void PostedItem::loadComments()
{ {
std::cerr << "PostedItem::loadComments()"; std::cerr << "PostedItem::loadComments()";
std::cerr << std::endl; std::cerr << std::endl;
if (mParent)
if (mFeedHolder)
{ {
QString title = QString::fromUtf8(mPost.mMeta.mMsgName.c_str()); QString title = QString::fromUtf8(mPost.mMeta.mMsgName.c_str());
mParent->openComments(0, mPost.mMeta.mGroupId, mPost.mMeta.mMsgId, title); mFeedHolder->openComments(0, mPost.mMeta.mGroupId, mPost.mMeta.mMsgId, title);
} }
} }

View file

@ -46,6 +46,9 @@ public:
void setContent(const RsPostedPost& post); void setContent(const RsPostedPost& post);
virtual void setContent(const QVariant &content); virtual void setContent(const QVariant &content);
/* FeedItem */
virtual void expand(bool /*open*/) {}
private slots: private slots:
void loadComments(); void loadComments();
void makeUpVote(); void makeUpVote();

View file

@ -423,12 +423,8 @@ void PostedListWidget::applyRanking()
QLayout *alayout = ui->scrollAreaWidgetContents->layout(); QLayout *alayout = ui->scrollAreaWidgetContents->layout();
int counter = 0; int counter = 0;
time_t min_ts = 0; time_t min_ts = 0;
foreach (GxsFeedItem *feedItem, mPostItems) foreach (PostedItem *item, mPostItems)
{ {
PostedItem *item = dynamic_cast<PostedItem*>(feedItem);
if (!item) {
continue;
}
std::cerr << "PostedListWidget::applyRanking() Item: " << item; std::cerr << "PostedListWidget::applyRanking() Item: " << item;
std::cerr << std::endl; std::cerr << std::endl;
@ -472,8 +468,11 @@ void PostedListWidget::applyRanking()
void PostedListWidget::clearPosts() void PostedListWidget::clearPosts()
{ {
GxsMessageFramePostWidget::clearPosts(); /* clear all messages */
foreach (PostedItem *item, mPostItems) {
delete(item);
}
mPostItems.clear();
mPosts.clear(); mPosts.clear();
} }
@ -585,12 +584,18 @@ void PostedListWidget::insertRelatedPosts(const uint32_t &token)
applyRanking(); applyRanking();
} }
void PostedListWidget::setMessageRead(GxsFeedItem *item, bool read) void PostedListWidget::setAllMessagesRead(bool read)
{ {
RsGxsGrpMsgIdPair msgPair = std::make_pair(item->groupId(), item->messageId()); if (groupId().isNull() || !IS_GROUP_SUBSCRIBED(subscribeFlags())) {
return;
}
uint32_t token; foreach (PostedItem *item, mPostItems) {
rsPosted->setMessageReadStatus(token, msgPair, read); RsGxsGrpMsgIdPair msgPair = std::make_pair(item->groupId(), item->messageId());
uint32_t token;
rsPosted->setMessageReadStatus(token, msgPair, read);
}
} }
/*********************** **** **** **** ***********************/ /*********************** **** **** **** ***********************/

View file

@ -47,6 +47,7 @@ public:
/* GxsMessageFrameWidget */ /* GxsMessageFrameWidget */
virtual QIcon groupIcon(); virtual QIcon groupIcon();
virtual void setAllMessagesRead(bool read);
/* FeedHolder */ /* FeedHolder */
virtual QScrollArea *getScrollArea(); virtual QScrollArea *getScrollArea();
@ -62,7 +63,6 @@ protected:
virtual bool insertGroupData(const uint32_t &token, RsGroupMetaData &metaData); virtual bool insertGroupData(const uint32_t &token, RsGroupMetaData &metaData);
virtual void insertPosts(const uint32_t &token); virtual void insertPosts(const uint32_t &token);
virtual void insertRelatedPosts(const uint32_t &token); virtual void insertRelatedPosts(const uint32_t &token);
virtual void setMessageRead(GxsFeedItem *item, bool read);
virtual void clearPosts(); virtual void clearPosts();
private slots: private slots:
@ -112,6 +112,7 @@ private:
uint32_t mTokenTypeVote; uint32_t mTokenTypeVote;
QMap<RsGxsMessageId, PostedItem*> mPosts; QMap<RsGxsMessageId, PostedItem*> mPosts;
QList<PostedItem*> mPostItems;
/* UI - from Designer */ /* UI - from Designer */
Ui::PostedListWidget *ui; Ui::PostedListWidget *ui;

View file

@ -182,7 +182,7 @@ void LineEditClear::setCurrentFilter(int id)
if (action->data().toInt() == id) { if (action->data().toInt() == id) {
action->setChecked(true); action->setChecked(true);
activateAction(action); activateAction(action);
// emit filterChanged(id); emit filterChanged(id);
break; break;
} }
} }

View file

@ -0,0 +1,406 @@
/****************************************************************
* This file is distributed under the following license:
*
* Copyright (c) 2014, RetroShare Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#include <QKeyEvent>
#include "RSFeedWidget.h"
#include "ui_RSFeedWidget.h"
#include "RSTreeWidgetItem.h"
#include "gui/feeds/FeedItem.h"
#include "gui/gxs/GxsFeedItem.h"
#define COLUMN_FEED 0
RSFeedWidget::RSFeedWidget(QWidget *parent)
: QWidget(parent), ui(new Ui::RSFeedWidget)
{
/* Invoke the Qt Designer generated object setup routine */
ui->setupUi(this);
/* Sort */
mFeedCompareRole = new RSTreeWidgetItemCompareRole;
/* Filter */
mFilterCallback = NULL;
mFilterType = 0;
/* Remove */
mEnableRemove = false;
ui->treeWidget->installEventFilter(this);
}
RSFeedWidget::~RSFeedWidget()
{
delete(mFeedCompareRole);
delete(ui);
}
bool RSFeedWidget::eventFilter(QObject *object, QEvent *event)
{
if (object == ui->treeWidget) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent) {
if (keyEvent->key() == Qt::Key_Plus || keyEvent->key() == Qt::Key_Minus) {
bool open = (keyEvent->key() == Qt::Key_Plus);
QList<FeedItem*> feedItems;
selectedFeedItems(feedItems);
foreach (FeedItem *feedItem, feedItems) {
feedItem->expand(open);
}
return true; // eat event
}
if (mEnableRemove && keyEvent->key() == Qt::Key_Delete) {
QList<QTreeWidgetItem*> selectedItems = ui->treeWidget->selectedItems();
foreach (QTreeWidgetItem *treeItem, selectedItems) {
FeedItem *feedItem = feedItemFromTreeItem(treeItem);
if (feedItem) {
disconnectSignals(feedItem);
delete(feedItem);
}
delete(treeItem);
}
return true; // eat event
}
}
}
}
/* Pass the event on to the parent class */
return QWidget::eventFilter(object, event);
}
void RSFeedWidget::connectSignals(FeedItem *feedItem)
{
connect(feedItem, SIGNAL(feedItemDestroyed(FeedItem*)), this, SLOT(feedItemDestroyed(FeedItem*)));
connect(feedItem, SIGNAL(sizeChanged(FeedItem*)), this, SLOT(feedItemSizeChanged(FeedItem*)));
}
void RSFeedWidget::disconnectSignals(FeedItem *feedItem)
{
disconnect(feedItem, SIGNAL(feedItemDestroyed(FeedItem*)), this, SLOT(feedItemDestroyed(FeedItem*)));
disconnect(feedItem, SIGNAL(sizeChanged(FeedItem*)), this, SLOT(feedItemSizeChanged(FeedItem*)));
}
FeedItem *RSFeedWidget::feedItemFromTreeItem(QTreeWidgetItem *treeItem)
{
return dynamic_cast<FeedItem*>(ui->treeWidget->itemWidget(treeItem, COLUMN_FEED));
}
void RSFeedWidget::addFeedItem(FeedItem *feedItem, Qt::ItemDataRole sortRole, const QVariant &value)
{
if (!feedItem) {
return;
}
QTreeWidgetItem *treeItem = new RSTreeWidgetItem(mFeedCompareRole);
treeItem->setData(COLUMN_FEED, sortRole, value);
ui->treeWidget->addTopLevelItem(treeItem);
ui->treeWidget->setItemWidget(treeItem, 0, feedItem);
connectSignals(feedItem);
filterItem(treeItem, feedItem);
}
void RSFeedWidget::addFeedItem(FeedItem *feedItem, const QMap<Qt::ItemDataRole, QVariant> &sort)
{
if (!feedItem) {
return;
}
QTreeWidgetItem *treeItem = new RSTreeWidgetItem(mFeedCompareRole);
QMap<Qt::ItemDataRole, QVariant>::const_iterator it;
for (it = sort.begin(); it != sort.end(); ++it) {
treeItem->setData(COLUMN_FEED, it.key(), it.value());
}
ui->treeWidget->addTopLevelItem(treeItem);
ui->treeWidget->setItemWidget(treeItem, 0, feedItem);
connectSignals(feedItem);
filterItem(treeItem, feedItem);
}
void RSFeedWidget::setSort(FeedItem *feedItem, Qt::ItemDataRole sortRole, const QVariant &value)
{
if (!feedItem) {
return;
}
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem);
if (!treeItem) {
return;
}
treeItem->setData(COLUMN_FEED, sortRole, value);
}
void RSFeedWidget::setSort(FeedItem *feedItem, const QMap<Qt::ItemDataRole, QVariant> &sort)
{
if (!feedItem) {
return;
}
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem);
if (!treeItem) {
return;
}
QMap<Qt::ItemDataRole, QVariant>::const_iterator it;
for (it = sort.begin(); it != sort.end(); ++it) {
treeItem->setData(COLUMN_FEED, it.key(), it.value());
}
}
void RSFeedWidget::clear()
{
ui->treeWidget->clear();
}
void RSFeedWidget::setSortRole(Qt::ItemDataRole role, Qt::SortOrder order)
{
setSortingEnabled(true);
mFeedCompareRole->setRole(COLUMN_FEED, role);
ui->treeWidget->sortItems(COLUMN_FEED, order);
}
void RSFeedWidget::setSortingEnabled(bool enable)
{
ui->treeWidget->setSortingEnabled(enable);
}
void RSFeedWidget::setFilterCallback(RSFeedWidgetFilterCallbackFunction callback)
{
mFilterCallback = callback;
filterItems();
}
void RSFeedWidget::setFilter(const QString &text, int type)
{
if (mFilterText == text && mFilterType == type) {
return;
}
mFilterText = text;
mFilterType = type;
filterItems();
}
void RSFeedWidget::setFilterText(const QString &text)
{
setFilter(text, mFilterType);
}
void RSFeedWidget::setFilterType(int type)
{
setFilter(mFilterText, type);
}
void RSFeedWidget::filterItems()
{
if (!mFilterCallback) {
return;
}
QTreeWidgetItemIterator it(ui->treeWidget);
QTreeWidgetItem *item;
while ((item = *it) != NULL) {
++it;
FeedItem *feedItem = feedItemFromTreeItem(item);
if (!feedItem) {
continue;
}
filterItem(item, feedItem);
}
}
void RSFeedWidget::filterItem(QTreeWidgetItem *treeItem, FeedItem *feedItem)
{
if (!mFilterCallback) {
return;
}
treeItem->setHidden(!mFilterCallback(feedItem, mFilterText, mFilterType));
}
void RSFeedWidget::enableRemove(bool enable)
{
mEnableRemove = enable;
}
void RSFeedWidget::setSelectionMode(QAbstractItemView::SelectionMode mode)
{
ui->treeWidget->setSelectionMode(mode);
}
void RSFeedWidget::removeFeedItem(FeedItem *feedItem)
{
if (!feedItem) {
return;
}
disconnectSignals(feedItem);
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem);
if (treeItem) {
delete(treeItem);
}
}
void RSFeedWidget::feedItemSizeChanged(FeedItem */*feedItem*/)
{
if (updatesEnabled()) {
setUpdatesEnabled(false);
QApplication::processEvents();
setUpdatesEnabled(true);
} else {
QApplication::processEvents();
}
ui->treeWidget->doItemsLayout();
}
void RSFeedWidget::feedItemDestroyed(FeedItem *feedItem)
{
/* No need to disconnect when object will be destroyed */
QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem);
if (treeItem) {
delete(treeItem);
}
}
QTreeWidgetItem *RSFeedWidget::findTreeWidgetItem(FeedItem *feedItem)
{
QTreeWidgetItemIterator it(ui->treeWidget);
QTreeWidgetItem *treeItem;
while ((treeItem = *it) != NULL) {
++it;
if (feedItemFromTreeItem(treeItem) == feedItem) {
return treeItem;
}
}
return NULL;
}
class RSFeedWidgetCallback
{
public:
RSFeedWidgetCallback() {}
virtual void callback(FeedItem *feedItem, const QVariant &data) = 0;
};
void RSFeedWidget::withAll(RSFeedWidgetCallbackFunction callback, const QVariant &data)
{
if (!callback) {
return;
}
QTreeWidgetItemIterator it(ui->treeWidget);
QTreeWidgetItem *treeItem;
while ((treeItem = *it) != NULL) {
++it;
FeedItem *feedItem = feedItemFromTreeItem(treeItem);
if (!feedItem) {
continue;
}
callback(feedItem, data);
}
}
FeedItem *RSFeedWidget::findFeedItem(RSFeedWidgetFindCallbackFunction callback, const QVariant &data1, const QVariant &data2)
{
if (!callback) {
return NULL;
}
QTreeWidgetItemIterator it(ui->treeWidget);
QTreeWidgetItem *treeItem;
while ((treeItem = *it) != NULL) {
++it;
FeedItem *feedItem = feedItemFromTreeItem(treeItem);
if (!feedItem) {
continue;
}
if (callback(feedItem, data1, data2)) {
return feedItem;
}
}
return NULL;
}
void RSFeedWidget::selectedFeedItems(QList<FeedItem*> &feedItems)
{
foreach (QTreeWidgetItem *treeItem, ui->treeWidget->selectedItems()) {
FeedItem *feedItem = feedItemFromTreeItem(treeItem);
if (!feedItem) {
continue;
}
feedItems.push_back(feedItem);
}
}
static bool findGxsFeedItemCallback(FeedItem *feedItem, const QVariant &data1, const QVariant &data2)
{
if (!data1.canConvert<RsGxsGroupId>() || !data2.canConvert<RsGxsMessageId>()) {
return false;
}
GxsFeedItem *item = dynamic_cast<GxsFeedItem*>(feedItem);
if (!item) {
return false;
}
if (item->groupId() != data1.value<RsGxsGroupId>() ||
item->messageId() != data2.value<RsGxsMessageId>()) {
return false;
}
return true;
}
GxsFeedItem *RSFeedWidget::findGxsFeedItem(const RsGxsGroupId &groupId, const RsGxsMessageId &messageId)
{
FeedItem *feedItem = findFeedItem(findGxsFeedItemCallback, qVariantFromValue(groupId), qVariantFromValue(messageId));
return dynamic_cast<GxsFeedItem*>(feedItem);
}

View file

@ -0,0 +1,113 @@
/****************************************************************
* This file is distributed under the following license:
*
* Copyright (c) 2014, RetroShare Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#ifndef _RSFEEDTREEWIDGET_H
#define _RSFEEDTREEWIDGET_H
#include <QAbstractItemView>
#include <QWidget>
#include <QMap>
#include "retroshare/rsgxsifacetypes.h"
#define FEED_TREEWIDGET_SORTROLE Qt::UserRole
class FeedItem;
class QTreeWidgetItem;
class RSTreeWidgetItemCompareRole;
class GxsFeedItem;
namespace Ui {
class RSFeedWidget;
}
typedef void (*RSFeedWidgetCallbackFunction)(FeedItem *feedItem, const QVariant &data);
typedef bool (*RSFeedWidgetFindCallbackFunction)(FeedItem *feedItem, const QVariant &data1, const QVariant &data2);
typedef bool (*RSFeedWidgetFilterCallbackFunction)(FeedItem *feedItem, const QString &text, int filter);
class RSFeedWidget : public QWidget
{
Q_OBJECT
public:
RSFeedWidget(QWidget *parent = 0);
virtual ~RSFeedWidget();
void addFeedItem(FeedItem *feedItem, Qt::ItemDataRole sortRole, const QVariant &value);
void addFeedItem(FeedItem *feedItem, const QMap<Qt::ItemDataRole, QVariant> &sort);
void setSort(FeedItem *feedItem, Qt::ItemDataRole sortRole, const QVariant &value);
void setSort(FeedItem *feedItem, const QMap<Qt::ItemDataRole, QVariant> &sort);
void removeFeedItem(FeedItem *feedItem);
void clear();
void setSortRole(Qt::ItemDataRole role, Qt::SortOrder order);
void setSortingEnabled(bool enable);
void setFilterCallback(RSFeedWidgetFilterCallbackFunction callback);
void enableRemove(bool enable);
void setSelectionMode(QAbstractItemView::SelectionMode mode);
void withAll(RSFeedWidgetCallbackFunction callback, const QVariant &data);
FeedItem *findFeedItem(RSFeedWidgetFindCallbackFunction callback, const QVariant &data1, const QVariant &data2);
void selectedFeedItems(QList<FeedItem*> &feedItems);
/* Convenience functions */
GxsFeedItem *findGxsFeedItem(const RsGxsGroupId &groupId, const RsGxsMessageId &messageId);
public slots:
void setFilter(const QString &text, int type);
void setFilterText(const QString &text);
void setFilterType(int type);
protected:
bool eventFilter(QObject *object, QEvent *event);
private slots:
void feedItemDestroyed(FeedItem *feedItem);
void feedItemSizeChanged(FeedItem *feedItem);
private:
void connectSignals(FeedItem *feedItem);
void disconnectSignals(FeedItem *feedItem);
FeedItem *feedItemFromTreeItem(QTreeWidgetItem *treeItem);
QTreeWidgetItem *findTreeWidgetItem(FeedItem *feedItem);
void filterItems();
void filterItem(QTreeWidgetItem *treeItem, FeedItem *feedItem);
private:
/* Sort */
RSTreeWidgetItemCompareRole *mFeedCompareRole;
/* Filter */
RSFeedWidgetFilterCallbackFunction mFilterCallback;
QString mFilterText;
int mFilterType;
/* Remove */
bool mEnableRemove;
Ui::RSFeedWidget *ui;
};
#endif

View file

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RSFeedWidget</class>
<widget class="QWidget" name="RSFeedWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>337</width>
<height>229</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QTreeWidget" name="treeWidget">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
<property name="itemsExpandable">
<bool>false</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,32 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2014 RetroShare Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#include "FeedItem.h"
/** Constructor */
FeedItem::FeedItem(QWidget *parent) : QWidget(parent)
{
}
FeedItem::~FeedItem()
{
emit feedItemDestroyed(this);
}

View file

@ -0,0 +1,44 @@
/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2014 RetroShare Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
****************************************************************/
#ifndef _FEED_ITEM_H
#define _FEED_ITEM_H
#include <QWidget>
class FeedItem : public QWidget
{
Q_OBJECT
public:
/** Default Constructor */
FeedItem(QWidget *parent = 0);
/** Default Destructor */
virtual ~FeedItem();
virtual void expand(bool open) = 0;
signals:
void sizeChanged(FeedItem *feedItem);
void feedItemDestroyed(FeedItem *feedItem);
};
#endif

View file

@ -48,8 +48,8 @@
#define SELF_LOAD 1 #define SELF_LOAD 1
#define DATA_PROVIDED 2 #define DATA_PROVIDED 2
GxsChannelPostItem::GxsChannelPostItem(FeedHolder *parent, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate) : GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate) :
GxsFeedItem(parent, feedId, groupId, messageId, isHome, rsGxsChannels, true, autoUpdate) GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsGxsChannels, true, autoUpdate)
{ {
mMode = SELF_LOAD; mMode = SELF_LOAD;
@ -57,8 +57,8 @@ GxsChannelPostItem::GxsChannelPostItem(FeedHolder *parent, uint32_t feedId, cons
} }
/** Constructor */ /** Constructor */
GxsChannelPostItem::GxsChannelPostItem(FeedHolder *parent, uint32_t feedId, const RsGxsChannelPost &post, uint32_t subFlags, bool isHome, bool autoUpdate) : GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelPost &post, uint32_t subFlags, bool isHome, bool autoUpdate) :
GxsFeedItem(parent, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsGxsChannels, false, autoUpdate) GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsGxsChannels, false, autoUpdate)
{ {
std::cerr << "GxsChannelPostItem::GxsChannelPostItem() Direct Load"; std::cerr << "GxsChannelPostItem::GxsChannelPostItem() Direct Load";
std::cerr << std::endl; std::cerr << std::endl;
@ -249,7 +249,7 @@ void GxsChannelPostItem::loadPost(const RsGxsChannelPost &post)
} }
// differences between Feed or Top of Comment. // differences between Feed or Top of Comment.
if (mParent) if (mFeedHolder)
{ {
ui->commentButton->show(); ui->commentButton->show();
@ -348,7 +348,8 @@ void GxsChannelPostItem::setReadStatus(bool isNew, bool isUnread)
ui->frame->style()->unpolish(ui->frame); ui->frame->style()->unpolish(ui->frame);
QPalette palette = ui->frame->palette(); QPalette palette = ui->frame->palette();
palette.setColor(ui->frame->backgroundRole(), isNew ? COLOR_NEW : COLOR_NORMAL); palette.setColor(ui->frame->backgroundRole(), isNew ? COLOR_NEW : COLOR_NORMAL); // QScrollArea
palette.setColor(QPalette::Base, isNew ? COLOR_NEW : COLOR_NORMAL); // QTreeWidget
ui->frame->setPalette(palette); ui->frame->setPalette(palette);
ui->frame->setProperty("new", isNew); ui->frame->setProperty("new", isNew);
@ -447,14 +448,14 @@ void GxsChannelPostItem::updateItem()
//downloadButton->setEnabled(true); //downloadButton->setEnabled(true);
} }
void GxsChannelPostItem::toggle() void GxsChannelPostItem::expand(bool open)
{ {
if (mParent) if (mFeedHolder)
{ {
mParent->lockLayout(this, true); mFeedHolder->lockLayout(this, true);
} }
if (ui->expandFrame->isHidden()) if (open)
{ {
ui->expandFrame->show(); ui->expandFrame->show();
ui->expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); ui->expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png")));
@ -469,12 +470,19 @@ void GxsChannelPostItem::toggle()
ui->expandButton->setToolTip(tr("Expand")); ui->expandButton->setToolTip(tr("Expand"));
} }
if (mParent) emit sizeChanged(this);
if (mFeedHolder)
{ {
mParent->lockLayout(this, false); mFeedHolder->lockLayout(this, false);
} }
} }
void GxsChannelPostItem::toggle()
{
expand(ui->expandFrame->isHidden());
}
/*********** SPECIFIC FUNCTIONS ***********************/ /*********** SPECIFIC FUNCTIONS ***********************/
void GxsChannelPostItem::readAndClearItem() void GxsChannelPostItem::readAndClearItem()

View file

@ -44,8 +44,8 @@ class GxsChannelPostItem : public GxsFeedItem
public: public:
/** Default Constructor */ /** Default Constructor */
GxsChannelPostItem(FeedHolder *parent, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate); GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate);
GxsChannelPostItem(FeedHolder *parent, uint32_t feedId, const RsGxsChannelPost &post, uint32_t subscribeFlags, bool isHome, bool autoUpdate); GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelPost &post, uint32_t subscribeFlags, bool isHome, bool autoUpdate);
virtual ~GxsChannelPostItem(); virtual ~GxsChannelPostItem();
virtual void setContent(const QVariant &content); virtual void setContent(const QVariant &content);
@ -57,6 +57,9 @@ public:
const QString getMsgLabel() {return RsHtml().formatText(NULL, QString::fromUtf8(mPost.mMsg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS); } const QString getMsgLabel() {return RsHtml().formatText(NULL, QString::fromUtf8(mPost.mMsg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS); }
const std::list<SubFileItem *> &getFileItems() {return mFileItems; } const std::list<SubFileItem *> &getFileItems() {return mFileItems; }
/* FeedItem */
virtual void expand(bool open);
protected: protected:
virtual void loadMessage(const uint32_t &token); virtual void loadMessage(const uint32_t &token);
virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_CHANNEL; } virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_CHANNEL; }

View file

@ -42,17 +42,17 @@ void GxsFeedItem::removeItem()
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
if (mParent) if (mFeedHolder)
{ {
mParent->lockLayout(this, true); mFeedHolder->lockLayout(this, true);
} }
hide(); hide();
if (mParent) if (mFeedHolder)
{ {
mParent->lockLayout(this, false); mFeedHolder->lockLayout(this, false);
mParent->deleteFeedItem(this, mFeedId); mFeedHolder->deleteFeedItem(this, mFeedId);
} }
} }
@ -63,9 +63,9 @@ void GxsFeedItem::comments(const QString &title)
std::cerr << std::endl; std::cerr << std::endl;
#endif #endif
if (mParent) if (mFeedHolder)
{ {
mParent->openComments(mFeedId, mGroupId, mMessageId, title); mFeedHolder->openComments(mFeedId, mGroupId, mMessageId, title);
} }
} }
@ -131,14 +131,14 @@ void GxsFeedItem::updateItem()
/***********************************************************/ /***********************************************************/
GxsFeedItem::GxsFeedItem(FeedHolder *parent, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, RsGxsIfaceHelper *iface, bool loadData, bool autoUpdate) : GxsFeedItem::GxsFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, RsGxsIfaceHelper *iface, bool loadData, bool autoUpdate) :
QWidget(NULL) FeedItem(NULL)
{ {
std::cerr << "GxsFeedItem::GxsFeedItem()"; std::cerr << "GxsFeedItem::GxsFeedItem()";
std::cerr << std::endl; std::cerr << std::endl;
/* this are just generally useful for all children */ /* this are just generally useful for all children */
mParent = parent; mFeedHolder = feedHolder;
mFeedId = feedId; mFeedId = feedId;
mIsHome = isHome; mIsHome = isHome;

View file

@ -24,7 +24,10 @@
#ifndef _GXS_GENERIC_FEED_ITEM_H #ifndef _GXS_GENERIC_FEED_ITEM_H
#define _GXS_GENERIC_FEED_ITEM_H #define _GXS_GENERIC_FEED_ITEM_H
#include <QMetaType>
#include <retroshare/rsgxsifacehelper.h> #include <retroshare/rsgxsifacehelper.h>
#include "gui/feeds/FeedItem.h"
#include "util/TokenQueue.h" #include "util/TokenQueue.h"
#include "gui/RetroShareLink.h" #include "gui/RetroShareLink.h"
@ -33,13 +36,13 @@
class FeedHolder; class FeedHolder;
class RsGxsUpdateBroadcastBase; class RsGxsUpdateBroadcastBase;
class GxsFeedItem : public QWidget, public TokenResponse class GxsFeedItem : public FeedItem, public TokenResponse
{ {
Q_OBJECT Q_OBJECT
public: public:
/** Note parent can = NULL */ /** Note parent can = NULL */
GxsFeedItem(FeedHolder *parent, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, RsGxsIfaceHelper *iface, bool loadData, bool autoUpdate); GxsFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, RsGxsIfaceHelper *iface, bool loadData, bool autoUpdate);
virtual ~GxsFeedItem(); virtual ~GxsFeedItem();
RsGxsGroupId groupId() { return mGroupId; } RsGxsGroupId groupId() { return mGroupId; }
@ -75,7 +78,7 @@ private slots:
void fillDisplay(bool complete); void fillDisplay(bool complete);
protected: protected:
FeedHolder *mParent; FeedHolder *mFeedHolder;
uint32_t mFeedId; uint32_t mFeedId;
bool mIsHome; bool mIsHome;
@ -92,4 +95,7 @@ private:
RsGxsUpdateBroadcastBase *mUpdateBroadcastBase; RsGxsUpdateBroadcastBase *mUpdateBroadcastBase;
}; };
Q_DECLARE_METATYPE(RsGxsGroupId)
Q_DECLARE_METATYPE(RsGxsMessageId)
#endif #endif

View file

@ -116,26 +116,6 @@ void GxsMessageFramePostWidget::updateDisplay(bool complete)
} }
} }
void GxsMessageFramePostWidget::setAllMessagesRead(bool read)
{
if (mGroupId.isNull() || !IS_GROUP_SUBSCRIBED(mSubscribeFlags)) {
return;
}
foreach (GxsFeedItem *item, mPostItems) {
setMessageRead(item, read);
}
}
void GxsMessageFramePostWidget::clearPosts()
{
/* clear all messages */
foreach (GxsFeedItem *item, mPostItems) {
delete(item);
}
mPostItems.clear();
}
/**************************************************************/ /**************************************************************/
/** Request / Response of Data ********************************/ /** Request / Response of Data ********************************/
/**************************************************************/ /**************************************************************/

View file

@ -40,7 +40,6 @@ public:
virtual void setGroupId(const RsGxsGroupId &groupId); virtual void setGroupId(const RsGxsGroupId &groupId);
virtual QString groupName(bool withUnreadCount); virtual QString groupName(bool withUnreadCount);
// virtual QIcon groupIcon() = 0; // virtual QIcon groupIcon() = 0;
virtual void setAllMessagesRead(bool read);
/* GXS functions */ /* GXS functions */
uint32_t nextTokenType() { return ++mNextTokenType; } uint32_t nextTokenType() { return ++mNextTokenType; }
@ -52,8 +51,7 @@ protected:
virtual void updateDisplay(bool complete); virtual void updateDisplay(bool complete);
virtual void groupNameChanged(const QString &/*name*/) {} virtual void groupNameChanged(const QString &/*name*/) {}
virtual void setMessageRead(GxsFeedItem *item, bool read) = 0; virtual void clearPosts() = 0;
virtual void clearPosts();
/* GXS functions */ /* GXS functions */
void requestGroupData(); void requestGroupData();
@ -74,7 +72,6 @@ protected:
uint32_t mTokenTypePosts; uint32_t mTokenTypePosts;
uint32_t mTokenTypeRelatedPosts; uint32_t mTokenTypeRelatedPosts;
UIStateHelper *mStateHelper; UIStateHelper *mStateHelper;
QList<GxsFeedItem*> mPostItems;
private: private:
RsGxsGroupId mGroupId; /* current group */ RsGxsGroupId mGroupId; /* current group */

View file

@ -19,6 +19,8 @@
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
****************************************************************/ ****************************************************************/
#include <QDateTime>
#include "GxsChannelPostsWidget.h" #include "GxsChannelPostsWidget.h"
#include "ui_GxsChannelPostsWidget.h" #include "ui_GxsChannelPostsWidget.h"
#include "gui/feeds/GxsChannelPostItem.h" #include "gui/feeds/GxsChannelPostItem.h"
@ -31,6 +33,8 @@
#define CHAN_DEFAULT_IMAGE ":/images/channels.png" #define CHAN_DEFAULT_IMAGE ":/images/channels.png"
#define ROLE_PUBLISH FEED_TREEWIDGET_SORTROLE
/**** /****
* #define DEBUG_CHANNEL * #define DEBUG_CHANNEL
***/ ***/
@ -49,6 +53,8 @@ GxsChannelPostsWidget::GxsChannelPostsWidget(const RsGxsGroupId &channelId, QWid
/* Invoke the Qt Designer generated object setup routine */ /* Invoke the Qt Designer generated object setup routine */
ui->setupUi(this); ui->setupUi(this);
mInProcessSettings = false;
/* Setup UI helper */ /* Setup UI helper */
// No progress yet // No progress yet
@ -69,8 +75,7 @@ GxsChannelPostsWidget::GxsChannelPostsWidget(const RsGxsGroupId &channelId, QWid
ui->filterLineEdit->addFilter(QIcon(), tr("Title"), FILTER_TITLE, tr("Search Title")); ui->filterLineEdit->addFilter(QIcon(), tr("Title"), FILTER_TITLE, tr("Search Title"));
ui->filterLineEdit->addFilter(QIcon(), tr("Message"), FILTER_MSG, tr("Search Message")); ui->filterLineEdit->addFilter(QIcon(), tr("Message"), FILTER_MSG, tr("Search Message"));
ui->filterLineEdit->addFilter(QIcon(), tr("Filename"), FILTER_FILE_NAME, tr("Search Filename")); ui->filterLineEdit->addFilter(QIcon(), tr("Filename"), FILTER_FILE_NAME, tr("Search Filename"));
ui->filterLineEdit->setCurrentFilter( Settings->valueFromGroup("ChannelFeed", "filter", FILTER_TITLE).toInt()); connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), ui->feedWidget, SLOT(setFilterText(QString)));
connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString)));
connect(ui->filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterChanged(int))); connect(ui->filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterChanged(int)));
/*************** Setup Left Hand Side (List of Channels) ****************/ /*************** Setup Left Hand Side (List of Channels) ****************/
@ -81,7 +86,9 @@ GxsChannelPostsWidget::GxsChannelPostsWidget(const RsGxsGroupId &channelId, QWid
ui->nameLabel->setMinimumWidth(20); ui->nameLabel->setMinimumWidth(20);
mInProcessSettings = false; /* Initialize feed widget */
ui->feedWidget->setSortRole(ROLE_PUBLISH, Qt::DescendingOrder);
ui->feedWidget->setFilterCallback(filterItem);
/* load settings */ /* load settings */
processSettings(true); processSettings(true);
@ -111,18 +118,19 @@ GxsChannelPostsWidget::~GxsChannelPostsWidget()
delete ui; delete ui;
} }
void GxsChannelPostsWidget::processSettings(bool /*load*/) void GxsChannelPostsWidget::processSettings(bool load)
{ {
mInProcessSettings = true; mInProcessSettings = true;
// Settings->beginGroup(QString("ChannelPostsWidget")); Settings->beginGroup(QString("ChannelPostsWidget"));
//
// if (load) { if (load) {
// // load settings // load settings
// } else { ui->filterLineEdit->setCurrentFilter(Settings->value("filter", FILTER_TITLE).toInt());
// // save settings } else {
// } // save settings
// }
// Settings->endGroup();
Settings->endGroup();
mInProcessSettings = false; mInProcessSettings = false;
} }
@ -155,7 +163,7 @@ QIcon GxsChannelPostsWidget::groupIcon()
QScrollArea *GxsChannelPostsWidget::getScrollArea() QScrollArea *GxsChannelPostsWidget::getScrollArea()
{ {
return ui->scrollArea; return NULL;
} }
void GxsChannelPostsWidget::deleteFeedItem(QWidget * /*item*/, uint32_t /*type*/) void GxsChannelPostsWidget::deleteFeedItem(QWidget * /*item*/, uint32_t /*type*/)
@ -216,116 +224,85 @@ void GxsChannelPostsWidget::insertChannelDetails(const RsGxsChannelGroup &group)
void GxsChannelPostsWidget::filterChanged(int filter) void GxsChannelPostsWidget::filterChanged(int filter)
{ {
ui->feedWidget->setFilterType(filter);
if (mInProcessSettings) { if (mInProcessSettings) {
return; return;
} }
filterItems(ui->filterLineEdit->text());
// save index // save index
Settings->setValueToGroup("ChannelFeed", "filter", filter); Settings->setValueToGroup("ChannelPostsWidget", "filter", filter);
} }
void GxsChannelPostsWidget::filterItems(const QString& text) /*static*/ bool GxsChannelPostsWidget::filterItem(FeedItem *feedItem, const QString &text, int filter)
{ {
int filter = ui->filterLineEdit->currentFilter(); GxsChannelPostItem *item = dynamic_cast<GxsChannelPostItem*>(feedItem);
if (!item) {
/* Search exisiting item */ return true;
QList<GxsFeedItem*>::iterator lit;
for (lit = mPostItems.begin(); lit != mPostItems.end(); lit++)
{
GxsChannelPostItem *item = dynamic_cast<GxsChannelPostItem*>(*lit);
if (!item) {
continue;
}
filterItem(item,text,filter);
} }
}
bool GxsChannelPostsWidget::filterItem(GxsChannelPostItem *pItem, const QString &text, const int filter)
{
bool bVisible = text.isEmpty(); bool bVisible = text.isEmpty();
switch(filter) switch(filter)
{ {
case FILTER_TITLE: case FILTER_TITLE:
bVisible=pItem->getTitleLabel().contains(text,Qt::CaseInsensitive); bVisible = item->getTitleLabel().contains(text,Qt::CaseInsensitive);
break; break;
case FILTER_MSG: case FILTER_MSG:
bVisible=pItem->getMsgLabel().contains(text,Qt::CaseInsensitive); bVisible = item->getMsgLabel().contains(text,Qt::CaseInsensitive);
break; break;
case FILTER_FILE_NAME: case FILTER_FILE_NAME:
{ {
std::list<SubFileItem *> fileItems=pItem->getFileItems(); std::list<SubFileItem *> fileItems = item->getFileItems();
std::list<SubFileItem *>::iterator lit; std::list<SubFileItem *>::iterator lit;
for(lit = fileItems.begin(); lit != fileItems.end(); lit++) for(lit = fileItems.begin(); lit != fileItems.end(); ++lit)
{ {
SubFileItem *fi = *lit; SubFileItem *fi = *lit;
QString fileName=QString::fromUtf8(fi->FileName().c_str()); QString fileName = QString::fromUtf8(fi->FileName().c_str());
bVisible=(bVisible || fileName.contains(text,Qt::CaseInsensitive)); bVisible = (bVisible || fileName.contains(text,Qt::CaseInsensitive));
} }
}
break; break;
}
default: default:
bVisible=true; bVisible = true;
break; break;
} }
pItem->setVisible(bVisible);
return (bVisible); return bVisible;
}
static bool sortChannelMsgSummaryAsc(const RsGxsChannelPost &msg1, const RsGxsChannelPost &msg2)
{
return (msg1.mMeta.mPublishTs > msg2.mMeta.mPublishTs);
}
static bool sortChannelMsgSummaryDesc(const RsGxsChannelPost &msg1, const RsGxsChannelPost &msg2)
{
return (msg1.mMeta.mPublishTs < msg2.mMeta.mPublishTs);
} }
void GxsChannelPostsWidget::insertChannelPosts(std::vector<RsGxsChannelPost> &posts, bool related) void GxsChannelPostsWidget::insertChannelPosts(std::vector<RsGxsChannelPost> &posts, bool related)
{ {
std::vector<RsGxsChannelPost>::const_iterator it; std::vector<RsGxsChannelPost>::const_iterator it;
// Do these need sorting? probably.
// can we add that into the request?
if (related) {
/* Sort descending to add posts at top */
std::sort(posts.begin(), posts.end(), sortChannelMsgSummaryDesc);
} else {
std::sort(posts.begin(), posts.end(), sortChannelMsgSummaryAsc);
}
uint32_t subscribeFlags = 0xffffffff; uint32_t subscribeFlags = 0xffffffff;
ui->feedWidget->setSortingEnabled(false);
for (it = posts.begin(); it != posts.end(); it++) for (it = posts.begin(); it != posts.end(); it++)
{ {
const RsGxsChannelPost &msg = *it;
GxsChannelPostItem *item = NULL; GxsChannelPostItem *item = NULL;
if (related) { if (related) {
foreach (GxsFeedItem *loopItem, mPostItems) { FeedItem *feedItem = ui->feedWidget->findGxsFeedItem(msg.mMeta.mGroupId, msg.mMeta.mMsgId);
if (loopItem->messageId() == it->mMeta.mMsgId) { item = dynamic_cast<GxsChannelPostItem*>(feedItem);
item = dynamic_cast<GxsChannelPostItem*>(loopItem);
break;
}
}
} }
if (item) { if (item) {
item->setContent(*it); item->setContent(*it);
//TODO: Sort timestamp //TODO: Sort timestamp
} else { } else {
item = new GxsChannelPostItem(this, 0, *it, subscribeFlags, true, false); item = new GxsChannelPostItem(this, 0, *it, subscribeFlags, true, false);
if (!ui->filterLineEdit->text().isEmpty()) ui->feedWidget->addFeedItem(item, ROLE_PUBLISH, QDateTime::fromTime_t(msg.mMeta.mPublishTs));
filterItem(item, ui->filterLineEdit->text(), ui->filterLineEdit->currentFilter());
mPostItems.push_back(item);
if (related) {
ui->verticalLayout->insertWidget(0, item);
} else {
ui->verticalLayout->addWidget(item);
}
} }
} }
ui->feedWidget->setSortingEnabled(true);
}
void GxsChannelPostsWidget::clearPosts()
{
ui->feedWidget->clear();
} }
void GxsChannelPostsWidget::subscribeGroup(bool subscribe) void GxsChannelPostsWidget::subscribeGroup(bool subscribe)
@ -391,10 +368,24 @@ void GxsChannelPostsWidget::insertRelatedPosts(const uint32_t &token)
insertChannelPosts(posts, true); insertChannelPosts(posts, true);
} }
void GxsChannelPostsWidget::setMessageRead(GxsFeedItem *item, bool read) static void setAllMessagesReadCallback(FeedItem *feedItem, const QVariant &data)
{ {
RsGxsGrpMsgIdPair msgPair = std::make_pair(item->groupId(), item->messageId()); GxsChannelPostItem *channelPostItem = dynamic_cast<GxsChannelPostItem*>(feedItem);
if (!channelPostItem) {
return;
}
RsGxsGrpMsgIdPair msgPair = std::make_pair(channelPostItem->groupId(), channelPostItem->messageId());
uint32_t token; uint32_t token;
rsGxsChannels->setMessageReadStatus(token, msgPair, read); rsGxsChannels->setMessageReadStatus(token, msgPair, data.toBool());
}
void GxsChannelPostsWidget::setAllMessagesRead(bool read)
{
if (groupId().isNull() || !IS_GROUP_SUBSCRIBED(subscribeFlags())) {
return;
}
ui->feedWidget->withAll(setAllMessagesReadCallback, read);
} }

View file

@ -32,9 +32,9 @@ namespace Ui {
class GxsChannelPostsWidget; class GxsChannelPostsWidget;
} }
//class ChanMsgItem;
class GxsChannelPostItem; class GxsChannelPostItem;
class QTreeWidgetItem; class QTreeWidgetItem;
class FeedItem;
class GxsChannelPostsWidget : public GxsMessageFramePostWidget, public FeedHolder class GxsChannelPostsWidget : public GxsMessageFramePostWidget, public FeedHolder
{ {
@ -48,6 +48,7 @@ public:
/* GxsMessageFrameWidget */ /* GxsMessageFrameWidget */
virtual QIcon groupIcon(); virtual QIcon groupIcon();
virtual void setAllMessagesRead(bool read);
/* FeedHolder */ /* FeedHolder */
virtual QScrollArea *getScrollArea(); virtual QScrollArea *getScrollArea();
@ -61,14 +62,13 @@ protected:
virtual bool insertGroupData(const uint32_t &token, RsGroupMetaData &metaData); virtual bool insertGroupData(const uint32_t &token, RsGroupMetaData &metaData);
virtual void insertPosts(const uint32_t &token); virtual void insertPosts(const uint32_t &token);
virtual void insertRelatedPosts(const uint32_t &token); virtual void insertRelatedPosts(const uint32_t &token);
virtual void setMessageRead(GxsFeedItem *item, bool read); virtual void clearPosts();
private slots: private slots:
void createMsg(); void createMsg();
void toggleAutoDownload(); void toggleAutoDownload();
void subscribeGroup(bool subscribe); void subscribeGroup(bool subscribe);
void filterChanged(int filter); void filterChanged(int filter);
void filterItems(const QString& text);
//void fillThreadFinished(); //void fillThreadFinished();
//void fillThreadAddMsg(const QString &channelId, const QString &channelMsgId, int current, int count); //void fillThreadAddMsg(const QString &channelId, const QString &channelMsgId, int current, int count);
@ -77,7 +77,7 @@ private:
void processSettings(bool load); void processSettings(bool load);
void setAutoDownload(bool autoDl); void setAutoDownload(bool autoDl);
bool filterItem(GxsChannelPostItem *pItem, const QString &text, const int filter); static bool filterItem(FeedItem *feedItem, const QString &text, int filter);
void insertChannelDetails(const RsGxsChannelGroup &group); void insertChannelDetails(const RsGxsChannelGroup &group);
void insertChannelPosts(std::vector<RsGxsChannelPost> &posts, bool related); void insertChannelPosts(std::vector<RsGxsChannelPost> &posts, bool related);

View file

@ -14,7 +14,16 @@
<property name="spacing"> <property name="spacing">
<number>4</number> <number>4</number>
</property> </property>
<property name="margin"> <property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
@ -26,7 +35,16 @@
<enum>QFrame::Sunken</enum> <enum>QFrame::Sunken</enum>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="margin"> <property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number> <number>4</number>
</property> </property>
<item> <item>
@ -212,40 +230,19 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QScrollArea" name="scrollArea"> <widget class="RSFeedWidget" name="feedWidget" native="true">
<property name="widgetResizable"> <property name="sizePolicy">
<bool>true</bool> <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>679</width>
<height>16</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
</layout>
</widget>
</widget> </widget>
</item> </item>
</layout> </layout>
<zorder>toolBarFrame</zorder> <zorder>toolBarFrame</zorder>
<zorder>scrollArea</zorder>
<zorder>headFrame</zorder> <zorder>headFrame</zorder>
<zorder>feedWidget</zorder>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>
@ -258,6 +255,12 @@
<extends>QToolButton</extends> <extends>QToolButton</extends>
<header>gui/common/SubscribeToolButton.h</header> <header>gui/common/SubscribeToolButton.h</header>
</customwidget> </customwidget>
<customwidget>
<class>RSFeedWidget</class>
<extends>QWidget</extends>
<header>gui/common/RSFeedWidget.h</header>
<container>1</container>
</customwidget>
</customwidgets> </customwidgets>
<resources> <resources>
<include location="../images.qrc"/> <include location="../images.qrc"/>

View file

@ -450,6 +450,7 @@ HEADERS += rshare.h \
gui/common/RSPlainTextEdit.h \ gui/common/RSPlainTextEdit.h \
gui/common/RSTreeWidget.h \ gui/common/RSTreeWidget.h \
gui/common/RSTreeWidgetItem.h \ gui/common/RSTreeWidgetItem.h \
gui/common/RSFeedWidget.h \
gui/common/RSTabWidget.h \ gui/common/RSTabWidget.h \
gui/common/RSItemDelegate.h \ gui/common/RSItemDelegate.h \
gui/common/PeerDefs.h \ gui/common/PeerDefs.h \
@ -495,6 +496,7 @@ HEADERS += rshare.h \
gui/elastic/arrow.h \ gui/elastic/arrow.h \
gui/elastic/node.h \ gui/elastic/node.h \
gui/NewsFeed.h \ gui/NewsFeed.h \
gui/feeds/FeedItem.h \
gui/feeds/FeedHolder.h \ gui/feeds/FeedHolder.h \
gui/feeds/PeerItem.h \ gui/feeds/PeerItem.h \
gui/feeds/MsgItem.h \ gui/feeds/MsgItem.h \
@ -615,6 +617,7 @@ FORMS += gui/StartDialog.ui \
gui/common/RSImageBlockWidget.ui \ gui/common/RSImageBlockWidget.ui \
gui/common/RsCollectionDialog.ui \ gui/common/RsCollectionDialog.ui \
gui/common/HeaderFrame.ui \ gui/common/HeaderFrame.ui \
gui/common/RSFeedWidget.ui \
gui/style/StyleDialog.ui \ gui/style/StyleDialog.ui \
gui/dht/DhtWindow.ui \ gui/dht/DhtWindow.ui \
gui/bwctrl/BwCtrlWindow.ui \ gui/bwctrl/BwCtrlWindow.ui \
@ -740,6 +743,7 @@ SOURCES += main.cpp \
gui/common/RSPlainTextEdit.cpp \ gui/common/RSPlainTextEdit.cpp \
gui/common/RSTreeWidget.cpp \ gui/common/RSTreeWidget.cpp \
gui/common/RSTreeWidgetItem.cpp \ gui/common/RSTreeWidgetItem.cpp \
gui/common/RSFeedWidget.cpp \
gui/common/RSTabWidget.cpp \ gui/common/RSTabWidget.cpp \
gui/common/RSItemDelegate.cpp \ gui/common/RSItemDelegate.cpp \
gui/common/PeerDefs.cpp \ gui/common/PeerDefs.cpp \
@ -816,6 +820,7 @@ SOURCES += main.cpp \
gui/elastic/arrow.cpp \ gui/elastic/arrow.cpp \
gui/elastic/node.cpp \ gui/elastic/node.cpp \
gui/NewsFeed.cpp \ gui/NewsFeed.cpp \
gui/feeds/FeedItem.cpp \
gui/feeds/FeedHolder.cpp \ gui/feeds/FeedHolder.cpp \
gui/feeds/PeerItem.cpp \ gui/feeds/PeerItem.cpp \
gui/feeds/MsgItem.cpp \ gui/feeds/MsgItem.cpp \