From 54d0d8ab8bac01fc32bf14467231cc4fbc731e7f Mon Sep 17 00:00:00 2001 From: defnax Date: Wed, 25 Dec 2019 17:16:58 +0100 Subject: [PATCH] Added new Card View for Posted --- .../src/gui/Posted/PostedCardView.cpp | 545 ++++++++++++++++++ .../src/gui/Posted/PostedCardView.h | 96 +++ .../src/gui/Posted/PostedCardView.ui | 527 +++++++++++++++++ retroshare-gui/src/gui/Posted/PostedItem.cpp | 5 + .../src/gui/Posted/PostedListWidget.cpp | 246 +++++++- .../src/gui/Posted/PostedListWidget.h | 9 + .../src/gui/Posted/PostedListWidget.ui | 199 +++++-- .../src/gui/Posted/Posted_images.qrc | 6 +- retroshare-gui/src/gui/Posted/images/card.png | Bin 0 -> 2257 bytes .../src/gui/Posted/images/classic.png | Bin 0 -> 2361 bytes .../src/gui/Posted/images/down-arrow.png | Bin 2005 -> 2641 bytes .../src/gui/Posted/images/down-hover.png | Bin 0 -> 1848 bytes .../src/gui/Posted/images/notes.png | Bin 1771 -> 2227 bytes .../src/gui/Posted/images/up-arrow.png | Bin 1925 -> 2603 bytes .../src/gui/Posted/images/up-hover.png | Bin 0 -> 1823 bytes .../src/gui/qss/stylesheet/Standard.qss | 4 + retroshare-gui/src/retroshare-gui.pro | 3 + 17 files changed, 1591 insertions(+), 49 deletions(-) create mode 100644 retroshare-gui/src/gui/Posted/PostedCardView.cpp create mode 100644 retroshare-gui/src/gui/Posted/PostedCardView.h create mode 100644 retroshare-gui/src/gui/Posted/PostedCardView.ui create mode 100644 retroshare-gui/src/gui/Posted/images/card.png create mode 100644 retroshare-gui/src/gui/Posted/images/classic.png create mode 100644 retroshare-gui/src/gui/Posted/images/down-hover.png create mode 100644 retroshare-gui/src/gui/Posted/images/up-hover.png diff --git a/retroshare-gui/src/gui/Posted/PostedCardView.cpp b/retroshare-gui/src/gui/Posted/PostedCardView.cpp new file mode 100644 index 000000000..f7f59a056 --- /dev/null +++ b/retroshare-gui/src/gui/Posted/PostedCardView.cpp @@ -0,0 +1,545 @@ +/******************************************************************************* + * retroshare-gui/src/gui/Posted/PostedCardView.cpp * + * * + * Copyright (C) 2019 Retroshare Team * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#include +#include +#include + +#include "rshare.h" +#include "PostedCardView.h" +#include "gui/feeds/FeedHolder.h" +#include "gui/gxs/GxsIdDetails.h" +#include "util/misc.h" +#include "util/HandleRichText.h" + +#include "ui_PostedCardView.h" + +#include +#include + +#define LINK_IMAGE ":/images/thumb-link.png" + +/** Constructor */ + +PostedCardView::PostedCardView(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate) : + GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsPosted, autoUpdate) +{ + setup(); + + requestGroup(); + requestMessage(); + requestComment(); +} + +PostedCardView::PostedCardView(FeedHolder *feedHolder, uint32_t feedId, const RsPostedGroup &group, const RsPostedPost &post, bool isHome, bool autoUpdate) : + GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsPosted, autoUpdate) +{ + setup(); + + mMessageId = post.mMeta.mMsgId; + + + setGroup(group, false); + setPost(post); + requestComment(); +} + +PostedCardView::PostedCardView(FeedHolder *feedHolder, uint32_t feedId, const RsPostedPost &post, bool isHome, bool autoUpdate) : + GxsFeedItem(feedHolder, feedId, post.mMeta.mGroupId, post.mMeta.mMsgId, isHome, rsPosted, autoUpdate) +{ + setup(); + + requestGroup(); + setPost(post); + requestComment(); +} + +PostedCardView::~PostedCardView() +{ + delete(ui); +} + +void PostedCardView::setup() +{ + /* Invoke the Qt Designer generated object setup routine */ + ui = new Ui::PostedCardView; + ui->setupUi(this); + + setAttribute(Qt::WA_DeleteOnClose, true); + + mInFill = false; + + /* clear ui */ + ui->titleLabel->setText(tr("Loading")); + ui->dateLabel->clear(); + ui->fromLabel->clear(); + ui->siteLabel->clear(); + + /* general ones */ + connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(removeItem())); + + /* specific */ + connect(ui->readAndClearButton, SIGNAL(clicked()), this, SLOT(readAndClearItem())); + + connect(ui->commentButton, SIGNAL( clicked()), this, SLOT(loadComments())); + connect(ui->voteUpButton, SIGNAL(clicked()), this, SLOT(makeUpVote())); + connect(ui->voteDownButton, SIGNAL(clicked()), this, SLOT( makeDownVote())); + connect(ui->readButton, SIGNAL(toggled(bool)), this, SLOT(readToggled(bool))); + + QAction *CopyLinkAction = new QAction(QIcon(""),tr("Copy RetroShare Link"), this); + connect(CopyLinkAction, SIGNAL(triggered()), this, SLOT(copyMessageLink())); + + + int S = QFontMetricsF(font()).height() ; + + ui->voteUpButton->setIconSize(QSize(S*1.5,S*1.5)); + ui->voteDownButton->setIconSize(QSize(S*1.5,S*1.5)); + ui->commentButton->setIconSize(QSize(S*1.5,S*1.5)); + ui->readButton->setIconSize(QSize(S*1.5,S*1.5)); + ui->shareButton->setIconSize(QSize(S*1.5,S*1.5)); + + QMenu *menu = new QMenu(); + menu->addAction(CopyLinkAction); + ui->shareButton->setMenu(menu); + + ui->clearButton->hide(); + ui->readAndClearButton->hide(); +} + +bool PostedCardView::setGroup(const RsPostedGroup &group, bool doFill) +{ + if (groupId() != group.mMeta.mGroupId) { + std::cerr << "PostedCardView::setGroup() - Wrong id, cannot set post"; + std::cerr << std::endl; + return false; + } + + mGroup = group; + + if (doFill) { + fill(); + } + + return true; +} + +bool PostedCardView::setPost(const RsPostedPost &post, bool doFill) +{ + if (groupId() != post.mMeta.mGroupId || messageId() != post.mMeta.mMsgId) { + std::cerr << "PostedCardView::setPost() - Wrong id, cannot set post"; + std::cerr << std::endl; + return false; + } + + mPost = post; + + if (doFill) { + fill(); + } + + return true; +} + +void PostedCardView::loadGroup(const uint32_t &token) +{ + std::vector groups; + if (!rsPosted->getGroupData(token, groups)) + { + std::cerr << "PostedCardView::loadGroup() ERROR getting data"; + std::cerr << std::endl; + return; + } + + if (groups.size() != 1) + { + std::cerr << "PostedCardView::loadGroup() Wrong number of Items"; + std::cerr << std::endl; + return; + } + + setGroup(groups[0]); +} + +void PostedCardView::loadMessage(const uint32_t &token) +{ + std::vector posts; + std::vector cmts; + if (!rsPosted->getPostData(token, posts, cmts)) + { + std::cerr << "GxsChannelPostItem::loadMessage() ERROR getting data"; + std::cerr << std::endl; + return; + } + + if (posts.size() == 1) + { + setPost(posts[0]); + } + else if (cmts.size() == 1) + { + RsGxsComment cmt = cmts[0]; + + //ui->newCommentLabel->show(); + //ui->commLabel->show(); + //ui->commLabel->setText(QString::fromUtf8(cmt.mComment.c_str())); + + //Change this item to be uploaded with thread element. + setMessageId(cmt.mMeta.mThreadId); + requestMessage(); + } + else + { + std::cerr << "GxsChannelPostItem::loadMessage() Wrong number of Items. Remove It."; + std::cerr << std::endl; + removeItem(); + return; + } +} + +void PostedCardView::loadComment(const uint32_t &token) +{ + std::vector cmts; + if (!rsPosted->getRelatedComments(token, cmts)) + { + std::cerr << "GxsChannelPostItem::loadComment() ERROR getting data"; + std::cerr << std::endl; + return; + } + + size_t comNb = cmts.size(); + QString sComButText = tr("Comment"); + if (comNb == 1) { + sComButText = sComButText.append("(1)"); + } else if (comNb > 1) { + sComButText = " " + tr("Comments").append(" (%1)").arg(comNb); + } + ui->commentButton->setText(sComButText); +} + +void PostedCardView::fill() +{ + if (isLoading()) { + /* Wait for all requests */ + return; + } + + QPixmap sqpixmap2 = QPixmap(":/images/thumb-default.png"); + + mInFill = true; + int desired_height = 1.5*(ui->voteDownButton->height() + ui->voteUpButton->height() + ui->scoreLabel->height()); + int desired_width = sqpixmap2.width()*desired_height/(float)sqpixmap2.height(); + + QDateTime qtime; + qtime.setTime_t(mPost.mMeta.mPublishTs); + QString timestamp = qtime.toString("hh:mm dd-MMM-yyyy"); + QString timestamp2 = misc::timeRelativeToNow(mPost.mMeta.mPublishTs); + ui->dateLabel->setText(timestamp2); + ui->dateLabel->setToolTip(timestamp); + + ui->fromLabel->setId(mPost.mMeta.mAuthorId); + + // Use QUrl to check/parse our URL + // The only combination that seems to work: load as EncodedUrl, extract toEncoded(). + QByteArray urlarray(mPost.mLink.c_str()); + QUrl url = QUrl::fromEncoded(urlarray.trimmed()); + QString urlstr = "Invalid Link"; + QString sitestr = "Invalid Link"; + + bool urlOkay = url.isValid(); + if (urlOkay) + { + QString scheme = url.scheme(); + if ((scheme != "https") + && (scheme != "http") + && (scheme != "ftp") + && (scheme != "retroshare")) + { + urlOkay = false; + sitestr = "Invalid Link Scheme"; + } + } + + if (urlOkay) + { + urlstr = QString(" "); + urlstr += messageName(); + urlstr += QString(" "); + + QString siteurl = url.toEncoded(); + sitestr = QString(" %2 ").arg(siteurl).arg(siteurl); + + ui->titleLabel->setText(urlstr); + }else + { + ui->titleLabel->setText(messageName()); + + } + + if (urlarray.isEmpty()) + { + ui->siteLabel->hide(); + } + + ui->siteLabel->setText(sitestr); + + if(mPost.mImage.mData != NULL) + { + QPixmap pixmap; + GxsIdDetails::loadPixmapFromData(mPost.mImage.mData, mPost.mImage.mSize, pixmap,GxsIdDetails::ORIGINAL); + // Wiping data - as its been passed to thumbnail. + + QPixmap sqpixmap = pixmap.scaled(desired_width,desired_height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); + + ui->pictureLabel->setPixmap(pixmap); + } + else if (mPost.mImage.mData == NULL) + { + ui->picture_frame->hide(); + } + else + { + ui->picture_frame->show(); + } + + + //QString score = "Hot" + QString::number(post.mHotScore); + //score += " Top" + QString::number(post.mTopScore); + //score += " New" + QString::number(post.mNewScore); + + QString score = QString::number(mPost.mTopScore); + + ui->scoreLabel->setText(score); + + // FIX THIS UP LATER. + ui->notes->setText(RsHtml().formatText(NULL, QString::fromUtf8(mPost.mNotes.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS)); + + if(ui->notes->text().isEmpty()) + ui->notes->hide(); + // differences between Feed or Top of Comment. + if (mFeedHolder) + { + // feed. + //frame_comment->show(); + ui->commentButton->show(); + + if (mPost.mComments) + { + QString commentText = QString::number(mPost.mComments); + commentText += " "; + commentText += tr("Comments"); + ui->commentButton->setText(commentText); + } + else + { + ui->commentButton->setText(tr("Comment")); + } + + setReadStatus(IS_MSG_NEW(mPost.mMeta.mMsgStatus), IS_MSG_UNREAD(mPost.mMeta.mMsgStatus) || IS_MSG_NEW(mPost.mMeta.mMsgStatus)); + } + else + { + // no feed. + //frame_comment->hide(); + ui->commentButton->hide(); + + ui->readButton->hide(); + ui->newLabel->hide(); + } + + if (mIsHome) + { + ui->clearButton->hide(); + ui->readAndClearButton->hide(); + } + else + { + ui->clearButton->show(); + ui->readAndClearButton->show(); + } + + // disable voting buttons - if they have already voted. + if (mPost.mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) + { + ui->voteUpButton->setEnabled(false); + ui->voteDownButton->setEnabled(false); + } + +#if 0 + uint32_t up, down, nComments; + + bool ok = rsPosted->retrieveScores(mPost.mMeta.mServiceString, up, down, nComments); + + if(ok) + { + int32_t vote = up - down; + scoreLabel->setText(QString::number(vote)); + + numCommentsLabel->setText("

# Comments: " + + QString::number(nComments) + "

"); + } +#endif + + mInFill = false; + + emit sizeChanged(this); +} + +const RsPostedPost &PostedCardView::getPost() const +{ + return mPost; +} + +RsPostedPost &PostedCardView::post() +{ + return mPost; +} + +QString PostedCardView::groupName() +{ + return QString::fromUtf8(mGroup.mMeta.mGroupName.c_str()); +} + +QString PostedCardView::messageName() +{ + return QString::fromUtf8(mPost.mMeta.mMsgName.c_str()); +} + +void PostedCardView::makeDownVote() +{ + RsGxsGrpMsgIdPair msgId; + msgId.first = mPost.mMeta.mGroupId; + msgId.second = mPost.mMeta.mMsgId; + + ui->voteUpButton->setEnabled(false); + ui->voteDownButton->setEnabled(false); + + emit vote(msgId, false); +} + +void PostedCardView::makeUpVote() +{ + RsGxsGrpMsgIdPair msgId; + msgId.first = mPost.mMeta.mGroupId; + msgId.second = mPost.mMeta.mMsgId; + + ui->voteUpButton->setEnabled(false); + ui->voteDownButton->setEnabled(false); + + emit vote(msgId, true); +} + +void PostedCardView::loadComments() +{ + std::cerr << "PostedCardView::loadComments()"; + std::cerr << std::endl; + + if (mFeedHolder) + { + QString title = QString::fromUtf8(mPost.mMeta.mMsgName.c_str()); + +#warning (csoler) Posted item versions not handled yet. When it is the case, start here. + + QVector post_versions ; + post_versions.push_back(mPost.mMeta.mMsgId) ; + + mFeedHolder->openComments(0, mPost.mMeta.mGroupId, post_versions,mPost.mMeta.mMsgId, title); + } +} + +void PostedCardView::setReadStatus(bool isNew, bool isUnread) +{ + if (isUnread) + { + ui->readButton->setChecked(true); + ui->readButton->setIcon(QIcon(":/images/message-state-unread.png")); + } + else + { + ui->readButton->setChecked(false); + ui->readButton->setIcon(QIcon(":/images/message-state-read.png")); + } + + ui->newLabel->setVisible(isNew); + + ui->mainFrame->setProperty("new", isNew); + ui->mainFrame->style()->unpolish(ui->mainFrame); + ui->mainFrame->style()->polish( ui->mainFrame); +} + +void PostedCardView::readToggled(bool checked) +{ + if (mInFill) { + return; + } + + RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); + + uint32_t token; + rsPosted->setMessageReadStatus(token, msgPair, !checked); + + setReadStatus(false, checked); +} + +void PostedCardView::readAndClearItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "PostedCardView::readAndClearItem()"; + std::cerr << std::endl; +#endif + + readToggled(false); + removeItem(); +} + + +void PostedCardView::doExpand(bool open) +{ + /*if (open) + { + + } + else + { + + } + + emit sizeChanged(this);*/ + +} + +void PostedCardView::copyMessageLink() +{ + if (groupId().isNull() || mMessageId.isNull()) { + return; + } + + RetroShareLink link = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_POSTED, groupId(), mMessageId, messageName()); + + if (link.valid()) { + QList urls; + urls.push_back(link); + RSLinkClipboard::copyLinks(urls); + } +} diff --git a/retroshare-gui/src/gui/Posted/PostedCardView.h b/retroshare-gui/src/gui/Posted/PostedCardView.h new file mode 100644 index 000000000..7cf51f682 --- /dev/null +++ b/retroshare-gui/src/gui/Posted/PostedCardView.h @@ -0,0 +1,96 @@ +/******************************************************************************* + * retroshare-gui/src/gui/Posted/PostedCardView.h * + * * + * Copyright (C) 2019 by Retroshare Team * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + *******************************************************************************/ + +#ifndef _POSTED_CARDVIEW_H +#define _POSTED_CARDVIEW_H + +#include + +#include +#include "gui/gxs/GxsFeedItem.h" + +namespace Ui { +class PostedCardView; +} + +class FeedHolder; +class RsPostedPost; + +class PostedCardView : public GxsFeedItem +{ + Q_OBJECT + +public: + PostedCardView(FeedHolder *parent, uint32_t feedId, const RsGxsGroupId &groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate); + PostedCardView(FeedHolder *parent, uint32_t feedId, const RsPostedGroup &group, const RsPostedPost &post, bool isHome, bool autoUpdate); + PostedCardView(FeedHolder *parent, uint32_t feedId, const RsPostedPost &post, bool isHome, bool autoUpdate); + virtual ~PostedCardView(); + + bool setGroup(const RsPostedGroup& group, bool doFill = true); + bool setPost(const RsPostedPost& post, bool doFill = true); + + const RsPostedPost &getPost() const; + RsPostedPost &post(); + +protected: + /* FeedItem */ + virtual void doExpand(bool open); + +private slots: + void loadComments(); + void makeUpVote(); + void makeDownVote(); + void readToggled(bool checked); + void readAndClearItem(); + void copyMessageLink(); + +signals: + void vote(const RsGxsGrpMsgIdPair& msgId, bool up); + +protected: + /* GxsGroupFeedItem */ + virtual QString groupName(); + virtual void loadGroup(const uint32_t &token); + virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_UNKNOWN; } + + /* GxsFeedItem */ + virtual QString messageName(); + virtual void loadMessage(const uint32_t &token); + virtual void loadComment(const uint32_t &token); + +private: + void setup(); + void fill(); + void setReadStatus(bool isNew, bool isUnread); + +private: + bool mInFill; + + RsPostedGroup mGroup; + RsPostedPost mPost; + RsGxsMessageId mMessageId; + + /** Qt Designer generated object */ + Ui::PostedCardView *ui; +}; + +//Q_DECLARE_METATYPE(RsPostedPost) + +#endif diff --git a/retroshare-gui/src/gui/Posted/PostedCardView.ui b/retroshare-gui/src/gui/Posted/PostedCardView.ui new file mode 100644 index 000000000..125c56d39 --- /dev/null +++ b/retroshare-gui/src/gui/Posted/PostedCardView.ui @@ -0,0 +1,527 @@ + + + PostedCardView + + + + 0 + 0 + 614 + 160 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + false + + + QFrame::Box + + + QFrame::Sunken + + + + 0 + + + 0 + + + 0 + + + 2 + + + 0 + + + 6 + + + + + + 0 + 0 + + + + + Arial + 10 + 75 + true + + + + This is a very very very very loooooooooooooooonnnnnnnnnnnnnnnnng title don't you think? Yes it is and should wrap around I hope + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + true + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse + + + + + + + + 0 + 0 + + + + site + + + true + + + + + + + 5 + + + 0 + + + 6 + + + + + + 0 + 0 + + + + + 50 + false + + + + Posted by + + + + + + + + 0 + 0 + + + + Signed by + + + true + + + + + + + + 0 + 0 + + + + You eyes only + + + true + + + + + + + + 24 + 16777215 + + + + Qt::NoFocus + + + Toggle Message Read Status + + + + :/images/message-state-unread.png:/images/message-state-unread.png + + + true + + + false + + + true + + + + + + + New + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 70 + 20 + + + + + + + + + + + 37 + 0 + + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + + 0 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + + 0 + 0 + + + + Vote up + + + + + + + :/images/up-arrow.png:/images/up-arrow.png + + + true + + + + + + + + 9 + + + + 0 + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + Vote down + + + + + + \/ + + + + :/images/down-arrow.png:/images/down-arrow.png + + + true + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 5 + + + + + + + + + + + + + Comments + + + + :/images/comments.png:/images/comments.png + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Share + + + + :/images/share.png:/images/share.png + + + true + + + + + + + Qt::Horizontal + + + + 308 + 20 + + + + + + + + + 24 + 16777215 + + + + Qt::NoFocus + + + Set as read and remove item + + + + :/icons/png/correct.png:/icons/png/correct.png + + + + + + + + 24 + 16777215 + + + + Qt::NoFocus + + + Remove Item + + + + :/icons/png/exit2.png:/icons/png/exit2.png + + + + + + + + + + + + true + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + + Qt::Horizontal + + + + 219 + 18 + + + + + + + + PictureLabel + + + true + + + + + + + Qt::Horizontal + + + + 268 + 17 + + + + + + + + + + + + + + + GxsIdLabel + QLabel +
gui/gxs/GxsIdLabel.h
+
+ + StyledLabel + QLabel +
gui/common/StyledLabel.h
+
+
+ + + + + + +
diff --git a/retroshare-gui/src/gui/Posted/PostedItem.cpp b/retroshare-gui/src/gui/Posted/PostedItem.cpp index 5d4e00a93..8907d7261 100644 --- a/retroshare-gui/src/gui/Posted/PostedItem.cpp +++ b/retroshare-gui/src/gui/Posted/PostedItem.cpp @@ -302,6 +302,11 @@ void PostedItem::fill() } + if (urlarray.isEmpty()) + { + ui->siteLabel->hide(); + } + ui->siteLabel->setText(sitestr); if(mPost.mImage.mData != NULL) diff --git a/retroshare-gui/src/gui/Posted/PostedListWidget.cpp b/retroshare-gui/src/gui/Posted/PostedListWidget.cpp index 8a1973457..e918cc03d 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidget.cpp +++ b/retroshare-gui/src/gui/Posted/PostedListWidget.cpp @@ -19,6 +19,7 @@ *******************************************************************************/ #include +#include #include "PostedListWidget.h" #include "ui_PostedListWidget.h" @@ -26,10 +27,12 @@ #include "gui/gxs/GxsIdDetails.h" #include "PostedCreatePostDialog.h" #include "PostedItem.h" +#include "PostedCardView.h" #include "gui/common/UIStateHelper.h" #include "gui/RetroShareLink.h" #include "util/HandleRichText.h" #include "util/DateTime.h" +#include "gui/settings/rsharesettings.h" #include #include "retroshare/rsgxscircles.h" @@ -39,6 +42,10 @@ #define TOPIC_DEFAULT_IMAGE ":/icons/png/posted.png" +/* View mode */ +#define VIEW_MODE_CLASSIC 1 +#define VIEW_MODE_CARD 2 + /** Constructor */ PostedListWidget::PostedListWidget(const RsGxsGroupId &postedId, QWidget *parent) : GxsMessageFramePostWidget(rsPosted, parent), @@ -61,6 +68,12 @@ PostedListWidget::PostedListWidget(const RsGxsGroupId &postedId, QWidget *parent connect(ui->comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(getRankings(int))); + QSignalMapper *signalMapper = new QSignalMapper(this); + connect(ui->classicViewButton, SIGNAL(clicked()), signalMapper, SLOT(map())); + connect(ui->cardViewButton, SIGNAL(clicked()), signalMapper, SLOT(map())); + signalMapper->setMapping(ui->classicViewButton, VIEW_MODE_CLASSIC); + signalMapper->setMapping(ui->cardViewButton, VIEW_MODE_CARD); + connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(setViewMode(int))); // default sort method. mSortMethod = RsPosted::HotRankType; @@ -101,17 +114,23 @@ PostedListWidget::~PostedListWidget() delete(ui); } -void PostedListWidget::processSettings(bool /*load*/) +void PostedListWidget::processSettings(bool load) { -// Settings->beginGroup(QString("PostedListWidget")); -// -// if (load) { -// // load settings -// } else { -// // save settings -// } -// -// Settings->endGroup(); + Settings->beginGroup(QString("PostedListWidget")); + + if (load) { + // load settings + + /* View mode */ + setViewMode(Settings->value("viewMode", VIEW_MODE_CLASSIC).toInt()); + } else { + // save settings + + /* View mode */ + Settings->setValue("viewMode", viewMode()); + } + + Settings->endGroup(); } QIcon PostedListWidget::groupIcon() @@ -141,6 +160,13 @@ QScrollArea *PostedListWidget::getScrollArea() return ui->scrollArea; } +// Overloaded from FeedHolder. +/*QScrollArea *PostedListWidget::getScrollArea() +{ + return ui->scrollAreaCardView; +}*/ + + void PostedListWidget::deleteFeedItem(QWidget */*item*/, uint32_t /*type*/) { std::cerr << "PostedListWidget::deleteFeedItem() Nah"; @@ -404,11 +430,23 @@ void PostedListWidget::loadPost(const RsPostedPost &post) PostedItem *item = new PostedItem(this, 0, dummyGroup, post, true, false); connect(item, SIGNAL(vote(RsGxsGrpMsgIdPair,bool)), this, SLOT(submitVote(RsGxsGrpMsgIdPair,bool))); mPosts.insert(post.mMeta.mMsgId, item); - //QLayout *alayout = ui.scrollAreaWidgetContents->layout(); - //alayout->addWidget(item); + mPostItems.push_back(item); } +void PostedListWidget::loadPostCardView(const RsPostedPost &post) +{ + /* Group is not always available because of the TokenQueue */ + RsPostedGroup dummyGroup; + dummyGroup.mMeta.mGroupId = groupId(); + + PostedCardView *cvitem = new PostedCardView(this, 0, dummyGroup, post, true, false); + connect(cvitem, SIGNAL(vote(RsGxsGrpMsgIdPair,bool)), this, SLOT(submitVote(RsGxsGrpMsgIdPair,bool))); + mCVPosts.insert(post.mMeta.mMsgId, cvitem); + + mPostCardView.push_back(cvitem); +} + static bool CmpPIHot(const GxsFeedItem *a, const GxsFeedItem *b) { const PostedItem *aa = dynamic_cast(a); @@ -461,6 +499,58 @@ static bool CmpPINew(const GxsFeedItem *a, const GxsFeedItem *b) return (aa->getPost().mNewScore > bb->getPost().mNewScore); } +static bool CVHot(const GxsFeedItem *a, const GxsFeedItem *b) +{ + const PostedCardView *aa = dynamic_cast(a); + const PostedCardView *bb = dynamic_cast(b); + + if (!aa || !bb) { + return true; + } + + const RsPostedPost &postA = aa->getPost(); + const RsPostedPost &postB = bb->getPost(); + + if (postA.mHotScore == postB.mHotScore) + { + return (postA.mNewScore > postB.mNewScore); + } + + return (postA.mHotScore > postB.mHotScore); +} + +static bool CVTop(const GxsFeedItem *a, const GxsFeedItem *b) +{ + const PostedCardView *aa = dynamic_cast(a); + const PostedCardView *bb = dynamic_cast(b); + + if (!aa || !bb) { + return true; + } + + const RsPostedPost &postA = aa->getPost(); + const RsPostedPost &postB = bb->getPost(); + + if (postA.mTopScore == postB.mTopScore) + { + return (postA.mNewScore > postB.mNewScore); + } + + return (postA.mTopScore > postB.mTopScore); +} + +static bool CVNew(const GxsFeedItem *a, const GxsFeedItem *b) +{ + const PostedCardView *aa = dynamic_cast(a); + const PostedCardView *bb = dynamic_cast(b); + + if (!aa || !bb) { + return true; + } + + return (aa->getPost().mNewScore > bb->getPost().mNewScore); +} + void PostedListWidget::applyRanking() { /* uses current settings to sort posts, then add to layout */ @@ -477,16 +567,19 @@ void PostedListWidget::applyRanking() std::cerr << "PostedListWidget::applyRanking() HOT"; std::cerr << std::endl; qSort(mPostItems.begin(), mPostItems.end(), CmpPIHot); + qSort(mPostCardView.begin(), mPostCardView.end(), CVHot); break; case RsPosted::NewRankType: std::cerr << "PostedListWidget::applyRanking() NEW"; std::cerr << std::endl; qSort(mPostItems.begin(), mPostItems.end(), CmpPINew); + qSort(mPostCardView.begin(), mPostCardView.end(), CVNew); break; case RsPosted::TopRankType: std::cerr << "PostedListWidget::applyRanking() TOP"; std::cerr << std::endl; qSort(mPostItems.begin(), mPostItems.end(), CmpPITop); + qSort(mPostCardView.begin(), mPostCardView.end(), CVTop); break; } mLastSortMethod = mSortMethod; @@ -496,8 +589,11 @@ void PostedListWidget::applyRanking() /* go through list (skipping out-of-date items) to get */ QLayout *alayout = ui->scrollAreaWidgetContents->layout(); + + int counter = 0; time_t min_ts = 0; + foreach (PostedItem *item, mPostItems) { std::cerr << "PostedListWidget::applyRanking() Item: " << item; @@ -534,11 +630,52 @@ void PostedListWidget::applyRanking() ++counter; } + // Card View + QLayout *cviewlayout = ui->scrollAreaWidgetContentsCardView->layout(); + + foreach (PostedCardView *item, mPostCardView) + { + std::cerr << "PostedListWidget::applyRanking() Item: " << item; + std::cerr << std::endl; + + if (item->getPost().mMeta.mPublishTs < min_ts) + { + std::cerr << "\t Skipping OLD"; + std::cerr << std::endl; + item->hide(); + continue; + } + + if (counter >= mPostIndex + mPostShow) + { + std::cerr << "\t END - Counter too high"; + std::cerr << std::endl; + item->hide(); + } + else if (counter >= mPostIndex) + { + std::cerr << "\t Adding to Layout"; + std::cerr << std::endl; + /* add it in! */ + cviewlayout->addWidget(item); + item->show(); + } + else + { + std::cerr << "\t Skipping to Low"; + std::cerr << std::endl; + item->hide(); + } + ++counter; + } + std::cerr << "PostedListWidget::applyRanking() Loaded New Order"; std::cerr << std::endl; // trigger a redraw. ui->scrollAreaWidgetContents->update(); + ui->scrollAreaWidgetContentsCardView->update(); + } void PostedListWidget::blank() @@ -548,10 +685,17 @@ void PostedListWidget::blank() } void PostedListWidget::clearPosts() { - /* clear all messages */ + /* clear all classic view messages */ foreach (PostedItem *item, mPostItems) { delete(item); } + + /* clear all card view messages */ + foreach (PostedCardView *item, mPostCardView) { + delete(item); + } + + mPostCardView.clear(); mPostItems.clear(); mPosts.clear(); } @@ -601,6 +745,45 @@ void PostedListWidget::shallowClearPosts() PostedItem *item = *pit; alayout->removeWidget(item); } + + + //Posted Card view + + std::list postedCardViewItems; + std::list::iterator pcvit; + + QLayout *cviewlayout = ui->scrollAreaWidgetContentsCardView->layout(); + int countcv = cviewlayout->count(); + for(int i = 0; i < countcv; ++i) + { + QLayoutItem *litem = cviewlayout->itemAt(i); + if (!litem) + { + std::cerr << "PostedListWidget::shallowClearPosts() missing litem"; + std::cerr << std::endl; + continue; + } + + PostedCardView *item = dynamic_cast(litem->widget()); + if (item) + { + std::cerr << "PostedListWidget::shallowClearPosts() item: " << item; + std::cerr << std::endl; + + postedCardViewItems.push_back(item); + } + else + { + std::cerr << "PostedListWidget::shallowClearPosts() Found Child, which is not a PostedItem???"; + std::cerr << std::endl; + } + } + + for(pcvit = postedCardViewItems.begin(); pcvit != postedCardViewItems.end(); ++pcvit) + { + PostedCardView *item = *pcvit; + cviewlayout->removeWidget(item); + } } bool PostedListWidget::insertGroupData(const uint32_t &token, RsGroupMetaData &metaData) @@ -628,6 +811,7 @@ void PostedListWidget::insertAllPosts(const uint32_t &token, GxsMessageFramePost { RsPostedPost& p = *vit; loadPost(p); + loadPostCardView(p); } applyRanking(); @@ -721,3 +905,39 @@ void PostedListWidget::loadRequest(const TokenQueue *queue, const TokenRequest & GxsMessageFramePostWidget::loadRequest(queue, req); } + +int PostedListWidget::viewMode() +{ + if (ui->classicViewButton->isChecked()) { + return VIEW_MODE_CLASSIC; + } else if (ui->cardViewButton->isChecked()) { + return VIEW_MODE_CARD; + } + + /* Default */ + return VIEW_MODE_CLASSIC; +} + +void PostedListWidget::setViewMode(int viewMode) +{ + switch (viewMode) { + case VIEW_MODE_CLASSIC: + ui->stackedWidget->setCurrentIndex(0); + + + ui->classicViewButton->setChecked(true); + ui->cardViewButton->setChecked(false); + + break; + case VIEW_MODE_CARD: + ui->stackedWidget->setCurrentIndex(1); + + ui->cardViewButton->setChecked(true); + ui->classicViewButton->setChecked(false); + + break; + default: + setViewMode(VIEW_MODE_CLASSIC); + return; + } +} diff --git a/retroshare-gui/src/gui/Posted/PostedListWidget.h b/retroshare-gui/src/gui/Posted/PostedListWidget.h index 8184a444c..ddd726513 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidget.h +++ b/retroshare-gui/src/gui/Posted/PostedListWidget.h @@ -29,6 +29,7 @@ class RsPostedGroup; class RsPostedPost; class PostedItem; +class PostedCardView; namespace Ui { class PostedListWidget; @@ -79,16 +80,21 @@ private slots: void showNext(); void showPrev(); + void setViewMode(int viewMode); + private: void processSettings(bool load); void updateShowText(); + int viewMode(); + /*! * Only removes it from layout */ void shallowClearPosts(); void loadPost(const RsPostedPost &post); + void loadPostCardView(const RsPostedPost &post); void insertPostedDetails(const RsPostedGroup &group); @@ -115,6 +121,9 @@ private: QMap mPosts; QList mPostItems; + QMap mCVPosts; + QList mPostCardView; + /* UI - from Designer */ Ui::PostedListWidget *ui; }; diff --git a/retroshare-gui/src/gui/Posted/PostedListWidget.ui b/retroshare-gui/src/gui/Posted/PostedListWidget.ui index cb9b906ef..304a79c76 100644 --- a/retroshare-gui/src/gui/Posted/PostedListWidget.ui +++ b/retroshare-gui/src/gui/Posted/PostedListWidget.ui @@ -7,16 +7,13 @@ 0 0 616 - 428 + 595 Form - - - 3 - + 0 @@ -29,7 +26,10 @@ 0 - + + 0 + + QFrame::Box @@ -37,12 +37,9 @@ QFrame::Sunken - - - 6 - + - 4 + 6 2 @@ -164,6 +161,59 @@ + + + + 0 + + + + + Classic view + + + + :/images/classic.png:/images/classic.png + + + + 24 + 24 + + + + true + + + true + + + + + + + Card View + + + + :/images/card.png:/images/card.png + + + + 24 + 24 + + + + true + + + true + + + + + @@ -205,7 +255,7 @@ - + QFrame::StyledPanel @@ -478,30 +528,13 @@ p, li { white-space: pre-wrap; } - - - - true + + + + 1 - - - - 0 - 0 - 614 - 16 - - - - - 0 - 0 - - - - - 0 - + + 0 @@ -514,6 +547,102 @@ p, li { white-space: pre-wrap; } 0 + + + + true + + + + + 0 + 0 + 614 + 16 + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + true + + + + + 0 + 0 + 614 + 16 + + + + + 0 + 0 + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + diff --git a/retroshare-gui/src/gui/Posted/Posted_images.qrc b/retroshare-gui/src/gui/Posted/Posted_images.qrc index 8c713b53f..2a1a10d0c 100644 --- a/retroshare-gui/src/gui/Posted/Posted_images.qrc +++ b/retroshare-gui/src/gui/Posted/Posted_images.qrc @@ -1,6 +1,6 @@ - images/posted_16.png + images/posted_16.png images/posted_24.png images/posted_32.png images/posted_48.png @@ -23,5 +23,9 @@ images/link.png images/post.png images/photo.png + images/classic.png + images/card.png + images/down-hover.png + images/up-hover.png diff --git a/retroshare-gui/src/gui/Posted/images/card.png b/retroshare-gui/src/gui/Posted/images/card.png new file mode 100644 index 0000000000000000000000000000000000000000..47cc72d0aebe2905a7b9a6f12524a854f7989337 GIT binary patch literal 2257 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 uT(nXx4Jcq(#rqfY8#Dy~ literal 0 HcmV?d00001 diff --git a/retroshare-gui/src/gui/Posted/images/notes.png b/retroshare-gui/src/gui/Posted/images/notes.png index a73a039685015b38071a49b50d19fa42355ee9d6..800eec4925c9836d8c30bc89dab6e31d2e500287 100644 GIT binary patch literal 2227 zcmb7`c{J2}AIHBKd$P4yB2BVn2_v#xUG=kO2_*&-$=DKxAwu)yUdO#sc`}OVe^FU{bvF+E zXqmx&cK)IF5!2f$u8$2QD^+?TPM?%tOZV2-(yWb*OdpO9ol8(9j^#22J6otV!M~c9 zJJL+A1xsffe39!|Rpgj%tB|#SqRif4WB6E8d%_%U-CDo6mAL)fgShG%G??Yt#H1lgYf?T)fENF@v{7 z_1Y821_k}@Ej7kAHeDfsfq^XNe$r;IGX>KWkcF&!W>e6g)m*(6LGj$Y-mU`J{GC(s z27LZIB|O>gTyj zAWul6JeAQgGyQ_34E=WH$%ZV8cUZdHNJ&+d??ps;KeQzI*Sxbq9>0$YoV_Eo1k24V zgtvWG1K(#b&sjIg<`%}r9*%xGSa4h8eNBFH2I+MEvyA!oDsaoj#>UmmyP47fIPPhFOSy#Lpyn861f=c<>j@hc~3!< zhMmMh>mu<%a~|tGgC9P8*mly=l=}6FPlq(EnSfN-PH?aD_B)&yGwezWkfe)%LJQ30 zBN4<=ON@H~zWim+htP1pql1yL0f}nkrNM-DPClBm<4hTuYE2IoFGDp%JM`^tJ6G3v z1ea%P;dP#h;baq94+SaN|8s4MVt&Jp;;H-fRoLgAo}Tt`nZlBii9PJcc*}lxx!>pP zEH#|bolGED1OI_+7iOgR zKJhseVQwFps!=W*VOAV9_V$_?$G#8I%;<5dd=gtSK(|AJGb`X`Zl?M1=qOi=~5y}ax%h96@ zhSfD_ms<&?nApl_l`A3_E5MEmG$y3Zr2ZK)(~v*A{9l`M-p665$|XHv?}?8R_@s4a*Fmsb%@&GJ!DK zcr8CXM_7rMb86E5u1$cWG=z)$@|b;1 zV5`mFa2K(tl}x~sU$x!wt`se+F|RYp8y&A23qt~%LonON((n`eopmb=>x~V79XhRy z8Ky+NH{vQN;=tLwT7Fo_v`}qDDNkjS=SkAN;aj z>>+4>i&X#JFJHc((Ovre>OTgm0Jz~U2lL3uT_#B%G)zI%U_*PG0FK1rS#z?}>Z#1I zTAABr_R!_8bIGoO(?RTy_<4se4lA>_;dkD;H9$0wN=sQ%>~E-g`USxQl}A2EOYVD< zv%r7Z>WZ5`@o(1u0RLaaT^Q}Lw3hcjd{`701>BgI8T{!Qvc&d@2#s;eos~J?!krtU zC%?G6CAtyShk|xHr`uMFW5r(Xr3uEyP@~lK4`>2?dM{B8jA2=(%gx`lCWB#!dI+gR5tz6>Zbg)5V3Xi{r`j z7Gg%GCMFom*AIJyl+@KxVP?gpA~DAo{F#U&xOTn!&P!3dcGV5UlEOkA)8YYfu;l7@ zHoo^(zGq88|IDMeE-M?uK119D`8-*6hFc^7IsmK%{qwMzS{8OR+9Ke&SrMrk)xeU= z_*4hQE8+%#8Mfk?PY;6&t(&9ML}`kfDLb#z#btM_7Q6nQ%YsaabL%t1-~C)F)lBfg O08VypQ2m*}+y4S+ED(GE delta 1697 zcmZuxdo8xu!$y; zc1)@9$Rsp_r5f*2gji098Af3$OFR2GyJtK5&pqdJ?z#7T&gb*Fw`$#tMz)Qb5d?q{ zgg6k;GJes;6jF|GbF%k2Qz#ie80q7yt0MhKpY=%j!X4`+(ACgS?{PX3fu;W1lteAQ zm?Uh;_(A`InuUka6WoEQ&0$v# zPeS>Ih)c0u_@cKfIXlae=9YU`V>^qUTne;P-JGc9pbGs_t(ZB6#>B?C+f!5Ga|x-H zx1NTSkdx!jc1;zCOeh$b$KyrfQ!^1~d&K?U1zgxQ6#=|c!zUHGJ4E8BIr$YnZE&}K&X-}_;v$=47%6D-@QQMJcz{j zvI6G~_(U8(H7Xw{27ga~JJC_hNv;}bH&r*-*SBkDKrMUo9<8!*=WbEh_}8K zkvLM7PrAh=5pKxT;jMMkE9Cn@3g*VC3(vN8EQ-7DBED`PL3Z;!r4|gRMjR5V=IU^O z{qdHMJ|mBL=qG;F^`lO*THAqst@XJMDMMRETt%1is1DU!1127O8t1uzE8neCAM6o6lx9n7<7vqb@ zPikNHmThU8cysC8Utf=V1jsVdQj6fLc{wWm);dHgcy2n6~ILyOtKQRyN8E|;U-q; zWJD!Zsh_kh|En->&h4@ND5Aqpk7)53QVlHbGyK6^1_C@oP6rPWgl^IVRpa}!W?>^b z#_2hqXwlhvgSjWz5c0dqaixkULCXRb-lX3Cpq8xBZsYoEWXn@WLF@aEDSEl?^91#$ z`A^jz?&j`<$-Nf$HJ>TL%wfm(jXAaBy>|@K7xWq7Lh4wTy_Xwp%?QGM zc6Jp$;yZUolp~`1xeb=fhX6 z+e58=wJ5A>qnJRZhFsMtf;Z_v)u zgQbv4k0)oq(vcEU64YB|DNo@9ulU>?v$QQ$ZI4XH?Am3pKYPI(P6`CtJGi!u^*+tb z&4#c?Z>;6vTBO#UhOf&D4@ol#B$_B%aA*BniGkNX_-u~hUv$=#G_2cV1D)+%Un$YF zkf*uH{FBRo#v{+^pJArnw{m4@hiem+=uBRg-B+yxZQm^^!Ev;!59Yp6DC%UnUyF8W zA?r_t?ZDK+H#sg$A?a>qw36}TjiPIlhv%s+aXPv^@vs`Nk8C1V19x(S%VW06QCwN! z&~8jE2+97B0RIB$Q*Hig>BZqeQh5{U9WRX}IgVpxF4kOhL1MAlHX5VVX{4hk#xwI2~xBs&Y-l8^JkT;I8|kQ9fgt4@#p2w{?CuU cIgbs2Q*~`8I`KIUKn(!k=1g>|a0pKL9r;WWVE_OC diff --git a/retroshare-gui/src/gui/Posted/images/up-arrow.png b/retroshare-gui/src/gui/Posted/images/up-arrow.png index 728ccf06831c0b198216e764ae1c945379cb695c..7f276af8f19d77442672c5704e91618fcf57b70f 100644 GIT binary patch delta 2557 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 G$o~M4rsX&u00~a3y8)-vBP*7-ZbZ>KLZ*U+Wt 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 Oa=?e+@6~dg&iV`CYdLTL literal 0 HcmV?d00001 diff --git a/retroshare-gui/src/gui/qss/stylesheet/Standard.qss b/retroshare-gui/src/gui/qss/stylesheet/Standard.qss index 282f4917f..4abbd0eff 100644 --- a/retroshare-gui/src/gui/qss/stylesheet/Standard.qss +++ b/retroshare-gui/src/gui/qss/stylesheet/Standard.qss @@ -857,6 +857,10 @@ PostedItem QLabel#fromBoldLabel, QLabel#fromLabel, QLabel#dateLabel, QLabel#site color: #787c7e; } +PostedCardView QFrame#voteFrame { + background: #f8f9fa; +} + GxsCommentDialog QComboBox#sortBox { font: bold; color: #0099cc; diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index 188bd9546..67540cc3a 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -1344,6 +1344,7 @@ posted { HEADERS += gui/Posted/PostedDialog.h \ gui/Posted/PostedListWidget.h \ gui/Posted/PostedItem.h \ + gui/Posted/PostedCardView.h \ gui/Posted/PostedGroupDialog.h \ gui/feeds/PostedGroupItem.h \ gui/Posted/PostedCreatePostDialog.h \ @@ -1355,6 +1356,7 @@ posted { FORMS += gui/Posted/PostedListWidget.ui \ gui/feeds/PostedGroupItem.ui \ gui/Posted/PostedItem.ui \ + gui/Posted/PostedCardView.ui \ gui/Posted/PostedCreatePostDialog.ui \ #gui/Posted/PostedDialog.ui \ @@ -1365,6 +1367,7 @@ posted { gui/Posted/PostedListWidget.cpp \ gui/feeds/PostedGroupItem.cpp \ gui/Posted/PostedItem.cpp \ + gui/Posted/PostedCardView.cpp \ gui/Posted/PostedGroupDialog.cpp \ gui/Posted/PostedCreatePostDialog.cpp \ gui/Posted/PostedUserNotify.cpp