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 000000000..47cc72d0a Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/card.png differ diff --git a/retroshare-gui/src/gui/Posted/images/classic.png b/retroshare-gui/src/gui/Posted/images/classic.png new file mode 100644 index 000000000..b85e0a119 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/classic.png differ diff --git a/retroshare-gui/src/gui/Posted/images/down-arrow.png b/retroshare-gui/src/gui/Posted/images/down-arrow.png index b6c7fcc06..1e531f03d 100644 Binary files a/retroshare-gui/src/gui/Posted/images/down-arrow.png and b/retroshare-gui/src/gui/Posted/images/down-arrow.png differ diff --git a/retroshare-gui/src/gui/Posted/images/down-hover.png b/retroshare-gui/src/gui/Posted/images/down-hover.png new file mode 100644 index 000000000..b822a0d87 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/down-hover.png differ diff --git a/retroshare-gui/src/gui/Posted/images/notes.png b/retroshare-gui/src/gui/Posted/images/notes.png index a73a03968..800eec492 100644 Binary files a/retroshare-gui/src/gui/Posted/images/notes.png and b/retroshare-gui/src/gui/Posted/images/notes.png differ diff --git a/retroshare-gui/src/gui/Posted/images/up-arrow.png b/retroshare-gui/src/gui/Posted/images/up-arrow.png index 728ccf068..7f276af8f 100644 Binary files a/retroshare-gui/src/gui/Posted/images/up-arrow.png and b/retroshare-gui/src/gui/Posted/images/up-arrow.png differ diff --git a/retroshare-gui/src/gui/Posted/images/up-hover.png b/retroshare-gui/src/gui/Posted/images/up-hover.png new file mode 100644 index 000000000..6e1144f96 Binary files /dev/null and b/retroshare-gui/src/gui/Posted/images/up-hover.png differ 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