diff --git a/retroshare-gui/src/gui/Posted/PostedItem.cpp b/retroshare-gui/src/gui/Posted/PostedItem.cpp index 850ba7314..fe5ebae19 100644 --- a/retroshare-gui/src/gui/Posted/PostedItem.cpp +++ b/retroshare-gui/src/gui/Posted/PostedItem.cpp @@ -32,14 +32,14 @@ /** Constructor */ -PostedItem::PostedItem(FeedHolder *parent, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome) : - GxsFeedItem(parent, feedId, groupId, messageId, isHome, rsPosted, true, false) +PostedItem::PostedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome) : + GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsPosted, true, false) { setup(); } -PostedItem::PostedItem(FeedHolder *parent, uint32_t feedId, const RsPostedPost &post, bool isHome) : - GxsFeedItem(parent, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsPosted, false, false), +PostedItem::PostedItem(FeedHolder *feedHolder, uint32_t feedId, const RsPostedPost &post, bool isHome) : + GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsPosted, false, false), mPost(post) { setup(); @@ -115,7 +115,7 @@ void PostedItem::setContent(const RsPostedPost &post) // FIX THIS UP LATER. notes->setText(QString::fromUtf8(post.mNotes.c_str())); // differences between Feed or Top of Comment. - if (mParent) + if (mFeedHolder) { // feed. frame_notes->hide(); @@ -218,9 +218,10 @@ void PostedItem::loadComments() { std::cerr << "PostedItem::loadComments()"; std::cerr << std::endl; - if (mParent) + + if (mFeedHolder) { 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); } } diff --git a/retroshare-gui/src/gui/Posted/PostedItem.h b/retroshare-gui/src/gui/Posted/PostedItem.h index 0462f07bb..d62ad88f4 100644 --- a/retroshare-gui/src/gui/Posted/PostedItem.h +++ b/retroshare-gui/src/gui/Posted/PostedItem.h @@ -46,6 +46,9 @@ public: void setContent(const RsPostedPost& post); virtual void setContent(const QVariant &content); + /* FeedItem */ + virtual void expand(bool /*open*/) {} + private slots: void loadComments(); void makeUpVote(); diff --git a/retroshare-gui/src/gui/Posted/PostedListWidget.cpp b/retroshare-gui/src/gui/Posted/PostedListWidget.cpp index 56930d245..4e1ee6116 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidget.cpp +++ b/retroshare-gui/src/gui/Posted/PostedListWidget.cpp @@ -423,12 +423,8 @@ void PostedListWidget::applyRanking() QLayout *alayout = ui->scrollAreaWidgetContents->layout(); int counter = 0; time_t min_ts = 0; - foreach (GxsFeedItem *feedItem, mPostItems) + foreach (PostedItem *item, mPostItems) { - PostedItem *item = dynamic_cast(feedItem); - if (!item) { - continue; - } std::cerr << "PostedListWidget::applyRanking() Item: " << item; std::cerr << std::endl; @@ -472,8 +468,11 @@ void PostedListWidget::applyRanking() void PostedListWidget::clearPosts() { - GxsMessageFramePostWidget::clearPosts(); - + /* clear all messages */ + foreach (PostedItem *item, mPostItems) { + delete(item); + } + mPostItems.clear(); mPosts.clear(); } @@ -585,12 +584,18 @@ void PostedListWidget::insertRelatedPosts(const uint32_t &token) 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; - rsPosted->setMessageReadStatus(token, msgPair, read); + foreach (PostedItem *item, mPostItems) { + RsGxsGrpMsgIdPair msgPair = std::make_pair(item->groupId(), item->messageId()); + + uint32_t token; + rsPosted->setMessageReadStatus(token, msgPair, read); + } } /*********************** **** **** **** ***********************/ diff --git a/retroshare-gui/src/gui/Posted/PostedListWidget.h b/retroshare-gui/src/gui/Posted/PostedListWidget.h index f3b18196c..af848a0d9 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidget.h +++ b/retroshare-gui/src/gui/Posted/PostedListWidget.h @@ -47,6 +47,7 @@ public: /* GxsMessageFrameWidget */ virtual QIcon groupIcon(); + virtual void setAllMessagesRead(bool read); /* FeedHolder */ virtual QScrollArea *getScrollArea(); @@ -62,7 +63,6 @@ protected: virtual bool insertGroupData(const uint32_t &token, RsGroupMetaData &metaData); virtual void insertPosts(const uint32_t &token); virtual void insertRelatedPosts(const uint32_t &token); - virtual void setMessageRead(GxsFeedItem *item, bool read); virtual void clearPosts(); private slots: @@ -112,6 +112,7 @@ private: uint32_t mTokenTypeVote; QMap mPosts; + QList mPostItems; /* UI - from Designer */ Ui::PostedListWidget *ui; diff --git a/retroshare-gui/src/gui/common/LineEditClear.cpp b/retroshare-gui/src/gui/common/LineEditClear.cpp index e5291a078..daf97d600 100644 --- a/retroshare-gui/src/gui/common/LineEditClear.cpp +++ b/retroshare-gui/src/gui/common/LineEditClear.cpp @@ -182,7 +182,7 @@ void LineEditClear::setCurrentFilter(int id) if (action->data().toInt() == id) { action->setChecked(true); activateAction(action); -// emit filterChanged(id); + emit filterChanged(id); break; } } diff --git a/retroshare-gui/src/gui/common/RSFeedWidget.cpp b/retroshare-gui/src/gui/common/RSFeedWidget.cpp new file mode 100644 index 000000000..94faa444e --- /dev/null +++ b/retroshare-gui/src/gui/common/RSFeedWidget.cpp @@ -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 + +#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(event); + if (keyEvent) { + if (keyEvent->key() == Qt::Key_Plus || keyEvent->key() == Qt::Key_Minus) { + bool open = (keyEvent->key() == Qt::Key_Plus); + + QList feedItems; + selectedFeedItems(feedItems); + + foreach (FeedItem *feedItem, feedItems) { + feedItem->expand(open); + } + + return true; // eat event + } + + if (mEnableRemove && keyEvent->key() == Qt::Key_Delete) { + QList 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(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 &sort) +{ + if (!feedItem) { + return; + } + + QTreeWidgetItem *treeItem = new RSTreeWidgetItem(mFeedCompareRole); + + QMap::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 &sort) +{ + if (!feedItem) { + return; + } + + QTreeWidgetItem *treeItem = findTreeWidgetItem(feedItem); + if (!treeItem) { + return; + } + + QMap::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 &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() || !data2.canConvert()) { + return false; + } + + GxsFeedItem *item = dynamic_cast(feedItem); + if (!item) { + return false; + } + + if (item->groupId() != data1.value() || + item->messageId() != data2.value()) { + return false; + } + + return true; +} + +GxsFeedItem *RSFeedWidget::findGxsFeedItem(const RsGxsGroupId &groupId, const RsGxsMessageId &messageId) +{ + FeedItem *feedItem = findFeedItem(findGxsFeedItemCallback, qVariantFromValue(groupId), qVariantFromValue(messageId)); + return dynamic_cast(feedItem); +} diff --git a/retroshare-gui/src/gui/common/RSFeedWidget.h b/retroshare-gui/src/gui/common/RSFeedWidget.h new file mode 100644 index 000000000..6d7ee6b80 --- /dev/null +++ b/retroshare-gui/src/gui/common/RSFeedWidget.h @@ -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 +#include +#include + +#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 &sort); + + void setSort(FeedItem *feedItem, Qt::ItemDataRole sortRole, const QVariant &value); + void setSort(FeedItem *feedItem, const QMap &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 &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 diff --git a/retroshare-gui/src/gui/common/RSFeedWidget.ui b/retroshare-gui/src/gui/common/RSFeedWidget.ui new file mode 100644 index 000000000..6f3aaeb62 --- /dev/null +++ b/retroshare-gui/src/gui/common/RSFeedWidget.ui @@ -0,0 +1,60 @@ + + + RSFeedWidget + + + + 0 + 0 + 337 + 229 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::ScrollPerPixel + + + false + + + false + + + true + + + false + + + + 1 + + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/FeedItem.cpp b/retroshare-gui/src/gui/feeds/FeedItem.cpp new file mode 100644 index 000000000..cb15acf77 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/FeedItem.cpp @@ -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); +} diff --git a/retroshare-gui/src/gui/feeds/FeedItem.h b/retroshare-gui/src/gui/feeds/FeedItem.h new file mode 100644 index 000000000..75d935e2e --- /dev/null +++ b/retroshare-gui/src/gui/feeds/FeedItem.h @@ -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 + +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 diff --git a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp index 03037a4c5..cbc65cba6 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp +++ b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.cpp @@ -48,8 +48,8 @@ #define SELF_LOAD 1 #define DATA_PROVIDED 2 -GxsChannelPostItem::GxsChannelPostItem(FeedHolder *parent, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate) : - GxsFeedItem(parent, feedId, groupId, messageId, isHome, rsGxsChannels, true, autoUpdate) +GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate) : + GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsGxsChannels, true, autoUpdate) { mMode = SELF_LOAD; @@ -57,8 +57,8 @@ GxsChannelPostItem::GxsChannelPostItem(FeedHolder *parent, uint32_t feedId, cons } /** Constructor */ -GxsChannelPostItem::GxsChannelPostItem(FeedHolder *parent, 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) +GxsChannelPostItem::GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelPost &post, uint32_t subFlags, bool isHome, bool autoUpdate) : + GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsGxsChannels, false, autoUpdate) { std::cerr << "GxsChannelPostItem::GxsChannelPostItem() Direct Load"; std::cerr << std::endl; @@ -249,7 +249,7 @@ void GxsChannelPostItem::loadPost(const RsGxsChannelPost &post) } // differences between Feed or Top of Comment. - if (mParent) + if (mFeedHolder) { ui->commentButton->show(); @@ -348,7 +348,8 @@ void GxsChannelPostItem::setReadStatus(bool isNew, bool isUnread) ui->frame->style()->unpolish(ui->frame); 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->setProperty("new", isNew); @@ -447,14 +448,14 @@ void GxsChannelPostItem::updateItem() //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->expandButton->setIcon(QIcon(QString(":/images/edit_remove24.png"))); @@ -469,12 +470,19 @@ void GxsChannelPostItem::toggle() 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 ***********************/ void GxsChannelPostItem::readAndClearItem() diff --git a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h index 359ea89e4..ce05c1bfc 100644 --- a/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h +++ b/retroshare-gui/src/gui/feeds/GxsChannelPostItem.h @@ -44,8 +44,8 @@ class GxsChannelPostItem : public GxsFeedItem public: /** Default Constructor */ - GxsChannelPostItem(FeedHolder *parent, 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 RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate); + GxsChannelPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsChannelPost &post, uint32_t subscribeFlags, bool isHome, bool autoUpdate); virtual ~GxsChannelPostItem(); 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 std::list &getFileItems() {return mFileItems; } + /* FeedItem */ + virtual void expand(bool open); + protected: virtual void loadMessage(const uint32_t &token); virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_CHANNEL; } diff --git a/retroshare-gui/src/gui/gxs/GxsFeedItem.cpp b/retroshare-gui/src/gui/gxs/GxsFeedItem.cpp index 5552526c5..ee52b9522 100644 --- a/retroshare-gui/src/gui/gxs/GxsFeedItem.cpp +++ b/retroshare-gui/src/gui/gxs/GxsFeedItem.cpp @@ -42,17 +42,17 @@ void GxsFeedItem::removeItem() std::cerr << std::endl; #endif - if (mParent) + if (mFeedHolder) { - mParent->lockLayout(this, true); + mFeedHolder->lockLayout(this, true); } hide(); - if (mParent) + if (mFeedHolder) { - mParent->lockLayout(this, false); - mParent->deleteFeedItem(this, mFeedId); + mFeedHolder->lockLayout(this, false); + mFeedHolder->deleteFeedItem(this, mFeedId); } } @@ -63,9 +63,9 @@ void GxsFeedItem::comments(const QString &title) std::cerr << std::endl; #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) : - QWidget(NULL) +GxsFeedItem::GxsFeedItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, RsGxsIfaceHelper *iface, bool loadData, bool autoUpdate) : + FeedItem(NULL) { std::cerr << "GxsFeedItem::GxsFeedItem()"; std::cerr << std::endl; /* this are just generally useful for all children */ - mParent = parent; + mFeedHolder = feedHolder; mFeedId = feedId; mIsHome = isHome; diff --git a/retroshare-gui/src/gui/gxs/GxsFeedItem.h b/retroshare-gui/src/gui/gxs/GxsFeedItem.h index 06a5e7d9a..273484c2a 100644 --- a/retroshare-gui/src/gui/gxs/GxsFeedItem.h +++ b/retroshare-gui/src/gui/gxs/GxsFeedItem.h @@ -24,7 +24,10 @@ #ifndef _GXS_GENERIC_FEED_ITEM_H #define _GXS_GENERIC_FEED_ITEM_H +#include + #include +#include "gui/feeds/FeedItem.h" #include "util/TokenQueue.h" #include "gui/RetroShareLink.h" @@ -33,13 +36,13 @@ class FeedHolder; class RsGxsUpdateBroadcastBase; -class GxsFeedItem : public QWidget, public TokenResponse +class GxsFeedItem : public FeedItem, public TokenResponse { Q_OBJECT public: /** 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(); RsGxsGroupId groupId() { return mGroupId; } @@ -75,7 +78,7 @@ private slots: void fillDisplay(bool complete); protected: - FeedHolder *mParent; + FeedHolder *mFeedHolder; uint32_t mFeedId; bool mIsHome; @@ -92,4 +95,7 @@ private: RsGxsUpdateBroadcastBase *mUpdateBroadcastBase; }; +Q_DECLARE_METATYPE(RsGxsGroupId) +Q_DECLARE_METATYPE(RsGxsMessageId) + #endif diff --git a/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.cpp b/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.cpp index 3b3b1fdbf..7a4ebc35b 100644 --- a/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.cpp +++ b/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.cpp @@ -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 ********************************/ /**************************************************************/ diff --git a/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.h b/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.h index 0373b60f4..9f4c19016 100644 --- a/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.h +++ b/retroshare-gui/src/gui/gxs/GxsMessageFramePostWidget.h @@ -40,7 +40,6 @@ public: virtual void setGroupId(const RsGxsGroupId &groupId); virtual QString groupName(bool withUnreadCount); // virtual QIcon groupIcon() = 0; - virtual void setAllMessagesRead(bool read); /* GXS functions */ uint32_t nextTokenType() { return ++mNextTokenType; } @@ -52,8 +51,7 @@ protected: virtual void updateDisplay(bool complete); virtual void groupNameChanged(const QString &/*name*/) {} - virtual void setMessageRead(GxsFeedItem *item, bool read) = 0; - virtual void clearPosts(); + virtual void clearPosts() = 0; /* GXS functions */ void requestGroupData(); @@ -74,7 +72,6 @@ protected: uint32_t mTokenTypePosts; uint32_t mTokenTypeRelatedPosts; UIStateHelper *mStateHelper; - QList mPostItems; private: RsGxsGroupId mGroupId; /* current group */ diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.cpp index 25785c941..b5b1ca80d 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.cpp @@ -19,6 +19,8 @@ * Boston, MA 02110-1301, USA. ****************************************************************/ +#include + #include "GxsChannelPostsWidget.h" #include "ui_GxsChannelPostsWidget.h" #include "gui/feeds/GxsChannelPostItem.h" @@ -31,6 +33,8 @@ #define CHAN_DEFAULT_IMAGE ":/images/channels.png" +#define ROLE_PUBLISH FEED_TREEWIDGET_SORTROLE + /**** * #define DEBUG_CHANNEL ***/ @@ -49,6 +53,8 @@ GxsChannelPostsWidget::GxsChannelPostsWidget(const RsGxsGroupId &channelId, QWid /* Invoke the Qt Designer generated object setup routine */ ui->setupUi(this); + mInProcessSettings = false; + /* Setup UI helper */ // 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("Message"), FILTER_MSG, tr("Search Message")); 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)), this, SLOT(filterItems(QString))); + connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), ui->feedWidget, SLOT(setFilterText(QString))); connect(ui->filterLineEdit, SIGNAL(filterChanged(int)), this, SLOT(filterChanged(int))); /*************** Setup Left Hand Side (List of Channels) ****************/ @@ -81,7 +86,9 @@ GxsChannelPostsWidget::GxsChannelPostsWidget(const RsGxsGroupId &channelId, QWid ui->nameLabel->setMinimumWidth(20); - mInProcessSettings = false; + /* Initialize feed widget */ + ui->feedWidget->setSortRole(ROLE_PUBLISH, Qt::DescendingOrder); + ui->feedWidget->setFilterCallback(filterItem); /* load settings */ processSettings(true); @@ -111,18 +118,19 @@ GxsChannelPostsWidget::~GxsChannelPostsWidget() delete ui; } -void GxsChannelPostsWidget::processSettings(bool /*load*/) +void GxsChannelPostsWidget::processSettings(bool load) { mInProcessSettings = true; -// Settings->beginGroup(QString("ChannelPostsWidget")); -// -// if (load) { -// // load settings -// } else { -// // save settings -// } -// -// Settings->endGroup(); + Settings->beginGroup(QString("ChannelPostsWidget")); + + if (load) { + // load settings + ui->filterLineEdit->setCurrentFilter(Settings->value("filter", FILTER_TITLE).toInt()); + } else { + // save settings + } + + Settings->endGroup(); mInProcessSettings = false; } @@ -155,7 +163,7 @@ QIcon GxsChannelPostsWidget::groupIcon() QScrollArea *GxsChannelPostsWidget::getScrollArea() { - return ui->scrollArea; + return NULL; } void GxsChannelPostsWidget::deleteFeedItem(QWidget * /*item*/, uint32_t /*type*/) @@ -216,116 +224,85 @@ void GxsChannelPostsWidget::insertChannelDetails(const RsGxsChannelGroup &group) void GxsChannelPostsWidget::filterChanged(int filter) { + ui->feedWidget->setFilterType(filter); + if (mInProcessSettings) { return; } - filterItems(ui->filterLineEdit->text()); // 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(); - - /* Search exisiting item */ - QList::iterator lit; - for (lit = mPostItems.begin(); lit != mPostItems.end(); lit++) - { - GxsChannelPostItem *item = dynamic_cast(*lit); - if (!item) { - continue; - } - filterItem(item,text,filter); + GxsChannelPostItem *item = dynamic_cast(feedItem); + if (!item) { + return true; } -} -bool GxsChannelPostsWidget::filterItem(GxsChannelPostItem *pItem, const QString &text, const int filter) -{ bool bVisible = text.isEmpty(); switch(filter) { case FILTER_TITLE: - bVisible=pItem->getTitleLabel().contains(text,Qt::CaseInsensitive); + bVisible = item->getTitleLabel().contains(text,Qt::CaseInsensitive); break; case FILTER_MSG: - bVisible=pItem->getMsgLabel().contains(text,Qt::CaseInsensitive); + bVisible = item->getMsgLabel().contains(text,Qt::CaseInsensitive); break; case FILTER_FILE_NAME: { - std::list fileItems=pItem->getFileItems(); + std::list fileItems = item->getFileItems(); std::list::iterator lit; - for(lit = fileItems.begin(); lit != fileItems.end(); lit++) + for(lit = fileItems.begin(); lit != fileItems.end(); ++lit) { SubFileItem *fi = *lit; - QString fileName=QString::fromUtf8(fi->FileName().c_str()); - bVisible=(bVisible || fileName.contains(text,Qt::CaseInsensitive)); + QString fileName = QString::fromUtf8(fi->FileName().c_str()); + bVisible = (bVisible || fileName.contains(text,Qt::CaseInsensitive)); } - } break; + } default: - bVisible=true; + bVisible = true; break; } - pItem->setVisible(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); + return bVisible; } void GxsChannelPostsWidget::insertChannelPosts(std::vector &posts, bool related) { std::vector::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; + ui->feedWidget->setSortingEnabled(false); + for (it = posts.begin(); it != posts.end(); it++) { + const RsGxsChannelPost &msg = *it; + GxsChannelPostItem *item = NULL; if (related) { - foreach (GxsFeedItem *loopItem, mPostItems) { - if (loopItem->messageId() == it->mMeta.mMsgId) { - item = dynamic_cast(loopItem); - break; - } - } + FeedItem *feedItem = ui->feedWidget->findGxsFeedItem(msg.mMeta.mGroupId, msg.mMeta.mMsgId); + item = dynamic_cast(feedItem); } if (item) { item->setContent(*it); //TODO: Sort timestamp } else { item = new GxsChannelPostItem(this, 0, *it, subscribeFlags, true, false); - if (!ui->filterLineEdit->text().isEmpty()) - 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->addFeedItem(item, ROLE_PUBLISH, QDateTime::fromTime_t(msg.mMeta.mPublishTs)); } } + + ui->feedWidget->setSortingEnabled(true); +} + +void GxsChannelPostsWidget::clearPosts() +{ + ui->feedWidget->clear(); } void GxsChannelPostsWidget::subscribeGroup(bool subscribe) @@ -391,10 +368,24 @@ void GxsChannelPostsWidget::insertRelatedPosts(const uint32_t &token) 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(feedItem); + if (!channelPostItem) { + return; + } + + RsGxsGrpMsgIdPair msgPair = std::make_pair(channelPostItem->groupId(), channelPostItem->messageId()); 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); } diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.h b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.h index 6d4767fb1..a14caa8cf 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.h +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.h @@ -32,9 +32,9 @@ namespace Ui { class GxsChannelPostsWidget; } -//class ChanMsgItem; class GxsChannelPostItem; class QTreeWidgetItem; +class FeedItem; class GxsChannelPostsWidget : public GxsMessageFramePostWidget, public FeedHolder { @@ -48,6 +48,7 @@ public: /* GxsMessageFrameWidget */ virtual QIcon groupIcon(); + virtual void setAllMessagesRead(bool read); /* FeedHolder */ virtual QScrollArea *getScrollArea(); @@ -61,14 +62,13 @@ protected: virtual bool insertGroupData(const uint32_t &token, RsGroupMetaData &metaData); virtual void insertPosts(const uint32_t &token); virtual void insertRelatedPosts(const uint32_t &token); - virtual void setMessageRead(GxsFeedItem *item, bool read); + virtual void clearPosts(); private slots: void createMsg(); void toggleAutoDownload(); void subscribeGroup(bool subscribe); void filterChanged(int filter); - void filterItems(const QString& text); //void fillThreadFinished(); //void fillThreadAddMsg(const QString &channelId, const QString &channelMsgId, int current, int count); @@ -77,7 +77,7 @@ private: void processSettings(bool load); 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 insertChannelPosts(std::vector &posts, bool related); diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.ui b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.ui index 1b5e31a6c..9dee95082 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.ui +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelPostsWidget.ui @@ -14,7 +14,16 @@ 4 - + + 0 + + + 0 + + + 0 + + 0 @@ -26,7 +35,16 @@ QFrame::Sunken - + + 4 + + + 4 + + + 4 + + 4 @@ -212,40 +230,19 @@ - - - true + + + + 0 + 0 + - - - - 0 - 0 - 679 - 16 - - - - - 0 - 0 - - - - - 0 - - - 0 - - - toolBarFrame - scrollArea headFrame + feedWidget @@ -258,6 +255,12 @@ QToolButton
gui/common/SubscribeToolButton.h
+ + RSFeedWidget + QWidget +
gui/common/RSFeedWidget.h
+ 1 +
diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index e3caa4a89..7d844e921 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -450,6 +450,7 @@ HEADERS += rshare.h \ gui/common/RSPlainTextEdit.h \ gui/common/RSTreeWidget.h \ gui/common/RSTreeWidgetItem.h \ + gui/common/RSFeedWidget.h \ gui/common/RSTabWidget.h \ gui/common/RSItemDelegate.h \ gui/common/PeerDefs.h \ @@ -495,6 +496,7 @@ HEADERS += rshare.h \ gui/elastic/arrow.h \ gui/elastic/node.h \ gui/NewsFeed.h \ + gui/feeds/FeedItem.h \ gui/feeds/FeedHolder.h \ gui/feeds/PeerItem.h \ gui/feeds/MsgItem.h \ @@ -615,6 +617,7 @@ FORMS += gui/StartDialog.ui \ gui/common/RSImageBlockWidget.ui \ gui/common/RsCollectionDialog.ui \ gui/common/HeaderFrame.ui \ + gui/common/RSFeedWidget.ui \ gui/style/StyleDialog.ui \ gui/dht/DhtWindow.ui \ gui/bwctrl/BwCtrlWindow.ui \ @@ -740,6 +743,7 @@ SOURCES += main.cpp \ gui/common/RSPlainTextEdit.cpp \ gui/common/RSTreeWidget.cpp \ gui/common/RSTreeWidgetItem.cpp \ + gui/common/RSFeedWidget.cpp \ gui/common/RSTabWidget.cpp \ gui/common/RSItemDelegate.cpp \ gui/common/PeerDefs.cpp \ @@ -816,6 +820,7 @@ SOURCES += main.cpp \ gui/elastic/arrow.cpp \ gui/elastic/node.cpp \ gui/NewsFeed.cpp \ + gui/feeds/FeedItem.cpp \ gui/feeds/FeedHolder.cpp \ gui/feeds/PeerItem.cpp \ gui/feeds/MsgItem.cpp \