From e129a2504b9e0677aa1a7f3c52a68dbcd2a4ee19 Mon Sep 17 00:00:00 2001 From: defnax <9952056+defnax@users.noreply.github.com> Date: Wed, 10 Dec 2025 21:08:08 +0100 Subject: [PATCH 01/13] Rework on wire notify and clean up code --- retroshare-gui/src/CMakeLists.txt | 17 +- retroshare-gui/src/gui/MainWindow.cpp | 15 + retroshare-gui/src/gui/MainWindow.h | 13 +- retroshare-gui/src/gui/NewsFeed.cpp | 51 +- retroshare-gui/src/gui/NewsFeed.h | 2 + retroshare-gui/src/gui/RetroShareLink.cpp | 101 ++- retroshare-gui/src/gui/RetroShareLink.h | 3 +- retroshare-gui/src/gui/TheWire/PulseReply.cpp | 40 + retroshare-gui/src/gui/TheWire/PulseReply.ui | 18 +- .../src/gui/TheWire/PulseViewGroup.ui | 12 + .../src/gui/TheWire/PulseViewItem.cpp | 13 + .../src/gui/TheWire/PulseViewItem.h | 3 + retroshare-gui/src/gui/TheWire/WireDialog.cpp | 386 ++++++++- retroshare-gui/src/gui/TheWire/WireDialog.h | 20 +- retroshare-gui/src/gui/TheWire/WireDialog.ui | 8 +- .../src/gui/TheWire/WireUserNotify.cpp | 62 ++ .../src/gui/TheWire/WireUserNotify.h | 42 + .../src/gui/common/NotifyWidget.cpp | 65 ++ retroshare-gui/src/gui/common/NotifyWidget.h | 83 ++ retroshare-gui/src/gui/common/NotifyWidget.ui | 66 ++ retroshare-gui/src/gui/feeds/FeedItem.h | 3 + .../src/gui/feeds/WireNotifyGroupItem.cpp | 265 ++++++ .../src/gui/feeds/WireNotifyGroupItem.h | 73 ++ .../src/gui/feeds/WireNotifyGroupItem.ui | 403 +++++++++ .../src/gui/feeds/WireNotifyPostItem.cpp | 786 ++++++++++++++++++ .../src/gui/feeds/WireNotifyPostItem.h | 108 +++ .../src/gui/feeds/WireNotifyPostItem.ui | 492 +++++++++++ retroshare-gui/src/gui/feeds/WirePostItem.cpp | 695 ++++++++++++++++ retroshare-gui/src/gui/feeds/WirePostItem.h | 108 +++ .../src/gui/gxs/GxsGroupFrameDialog.cpp | 84 +- .../src/gui/gxs/GxsGroupFrameDialog.h | 35 +- .../src/gui/gxs/GxsGroupFrameDialog.ui | 3 +- .../src/gui/gxs/GxsStatisticsProvider.cpp | 60 ++ .../src/gui/gxs/GxsStatisticsProvider.h | 78 ++ retroshare-gui/src/gui/gxs/GxsUserNotify.cpp | 5 +- retroshare-gui/src/gui/gxs/GxsUserNotify.h | 6 +- .../src/gui/gxsforums/GxsForumUserNotify.cpp | 2 +- .../src/gui/gxsforums/GxsForumUserNotify.h | 2 +- retroshare-gui/src/gui/icons.qrc | 3 +- .../src/gui/icons/png/wire-circle.png | Bin 0 -> 5041 bytes .../src/gui/icons/png/wire-notify.png | Bin 0 -> 4639 bytes .../src/gui/settings/NotifyPage.cpp | 11 +- retroshare-gui/src/gui/settings/NotifyPage.ui | 23 +- .../src/gui/settings/rsharesettings.cpp | 8 + .../src/gui/settings/rsharesettings.h | 2 +- retroshare.pri | 3 + 46 files changed, 4142 insertions(+), 136 deletions(-) create mode 100644 retroshare-gui/src/gui/TheWire/WireUserNotify.cpp create mode 100644 retroshare-gui/src/gui/TheWire/WireUserNotify.h create mode 100644 retroshare-gui/src/gui/common/NotifyWidget.cpp create mode 100644 retroshare-gui/src/gui/common/NotifyWidget.h create mode 100644 retroshare-gui/src/gui/common/NotifyWidget.ui create mode 100644 retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp create mode 100644 retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h create mode 100644 retroshare-gui/src/gui/feeds/WireNotifyGroupItem.ui create mode 100644 retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp create mode 100644 retroshare-gui/src/gui/feeds/WireNotifyPostItem.h create mode 100644 retroshare-gui/src/gui/feeds/WireNotifyPostItem.ui create mode 100644 retroshare-gui/src/gui/feeds/WirePostItem.cpp create mode 100644 retroshare-gui/src/gui/feeds/WirePostItem.h create mode 100644 retroshare-gui/src/gui/gxs/GxsStatisticsProvider.cpp create mode 100644 retroshare-gui/src/gui/gxs/GxsStatisticsProvider.h create mode 100644 retroshare-gui/src/gui/icons/png/wire-circle.png create mode 100644 retroshare-gui/src/gui/icons/png/wire-notify.png diff --git a/retroshare-gui/src/CMakeLists.txt b/retroshare-gui/src/CMakeLists.txt index dc70d7c09..6de5ceeba 100644 --- a/retroshare-gui/src/CMakeLists.txt +++ b/retroshare-gui/src/CMakeLists.txt @@ -176,6 +176,7 @@ list( src/gui/common/FlowLayout.cpp src/gui/common/PictureFlow.cpp src/gui/common/ToasterNotify.cpp + src/gui/common/NotifyWidget.cpp src/gui/style/RSStyle.cpp src/gui/style/StyleDialog.cpp @@ -382,6 +383,7 @@ list( src/gui/common/RsCollectionDialog.ui src/gui/common/HeaderFrame.ui src/gui/common/RSFeedWidget.ui + src/gui/common/NotifyWidget.ui src/gui/style/StyleDialog.ui @@ -641,6 +643,7 @@ list( src/gui/common/FlowLayout.h src/gui/common/PictureFlow.h src/gui/common/ToasterNotify.h + src/gui/common/NotifyWidget.h src/gui/style/RSStyle.h src/gui/style/StyleDialog.h @@ -999,7 +1002,10 @@ if(RS_GXSTHEWIRE) src/gui/TheWire/PulseViewGroup.h src/gui/TheWire/PulseReply.h src/gui/TheWire/PulseReplySeperator.h - src/gui/TheWire/PulseMessage.h + src/gui/TheWire/PulseMessage.h + src/gui/TheWire/WireUserNotify.h + src/gui/feeds/WireNotifyGroupItem.h + src/gui/feeds/WireNotifyPostItem.h ) list( @@ -1012,7 +1018,9 @@ if(RS_GXSTHEWIRE) src/gui/TheWire/PulseViewGroup.ui src/gui/TheWire/PulseReply.ui src/gui/TheWire/PulseReplySeperator.ui - src/gui/TheWire/PulseMessage.ui + src/gui/TheWire/PulseMessage.ui + src/gui/feeds/WireNotifyGroupItem.ui + src/gui/feeds/WireNotifyPostItem.ui ) list( @@ -1028,6 +1036,9 @@ if(RS_GXSTHEWIRE) src/gui/TheWire/PulseReply.cpp src/gui/TheWire/PulseReplySeperator.cpp src/gui/TheWire/PulseMessage.cpp + src/gui/TheWire/WireUserNotify.cpp + src/gui/feeds/WireNotifyGroupItem.cpp + src/gui/feeds/WireNotifyPostItem.cpp ) list( @@ -1112,6 +1123,7 @@ if(RS_GXSGUI) src/gui/gxs/GxsFeedWidget.h src/util/TokenQueue.h src/util/RsGxsUpdateBroadcast.h + src/gui/gxs/GxsStatisticsProvider.h ) list( @@ -1147,6 +1159,7 @@ if(RS_GXSGUI) src/gui/gxs/GxsFeedWidget.cpp src/util/TokenQueue.cpp src/util/RsGxsUpdateBroadcast.cpp + src/gui/gxs/GxsStatisticsProvider.cpp ) endif(RS_GXSGUI) diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index a1688867d..a29f2e263 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -1080,6 +1080,11 @@ void SetForegroundWindowInternal(HWND hWnd) case Posted: _instance->ui->stackPages->setCurrentPage( _instance->postedDialog ); return true ; +#ifdef RS_USE_WIRE + case Wire: + _instance->ui->stackPages->setCurrentPage( _instance->wireDialog ); + return true ; +#endif default: std::cerr << "Show page called on value that is not handled yet. Please code it! (value = " << page << ")" << std::endl; } @@ -1117,6 +1122,11 @@ void SetForegroundWindowInternal(HWND hWnd) if (page == _instance->messagesDialog) { return Messages; } +#ifdef RS_USE_WIRE + if (page == _instance->wireDialog) { + return Wire; + } +#endif #if 0 if (page == _instance->channelFeed) { return Channels; @@ -1156,6 +1166,7 @@ void SetForegroundWindowInternal(HWND hWnd) return _instance->transfersDialog->searchDialog; case Messages: return _instance->messagesDialog; + case Channels: return _instance->gxschannelDialog; case Forums: @@ -1164,6 +1175,10 @@ void SetForegroundWindowInternal(HWND hWnd) return _instance->postedDialog; case Home: return _instance->homePage; +#ifdef RS_USE_WIRE + case Wire: + return _instance->wireDialog; +#endif } return NULL; diff --git a/retroshare-gui/src/gui/MainWindow.h b/retroshare-gui/src/gui/MainWindow.h index 59f927ac6..8287fd50f 100644 --- a/retroshare-gui/src/gui/MainWindow.h +++ b/retroshare-gui/src/gui/MainWindow.h @@ -71,7 +71,9 @@ class BandwidthGraph; class MainPage; class NewsFeed; class UserNotify; - +#ifdef RS_USE_WIRE +class WireDialog; +#endif #ifdef MESSENGER_WINDOW class MessengerWindow; #endif @@ -107,7 +109,10 @@ public: Posted = 11, /** Posted links */ People = 12, /** People page. */ Options = 13, /** People page. */ - Home = 14 /** Home page. */ + Home = 14, /** Home page. */ +#ifdef RS_USE_WIRE + Wire = 15 /** Wire page. */ +#endif }; @@ -167,7 +172,9 @@ public: GxsChannelDialog *gxschannelDialog ; GxsForumsDialog *gxsforumDialog ; PostedDialog *postedDialog; - +#ifdef RS_USE_WIRE + WireDialog *wireDialog; +#endif // ForumsDialog *forumsDialog; // ChannelFeed *channelFeed; Idle *idle; diff --git a/retroshare-gui/src/gui/NewsFeed.cpp b/retroshare-gui/src/gui/NewsFeed.cpp index cf901d1e7..ebfd0d81e 100644 --- a/retroshare-gui/src/gui/NewsFeed.cpp +++ b/retroshare-gui/src/gui/NewsFeed.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include "util/misc.h" #include "util/qtthreadsutils.h" @@ -49,6 +50,8 @@ #include "feeds/PostedGroupItem.h" #include "feeds/SecurityItem.h" #include "feeds/SecurityIpItem.h" +#include "feeds/WireNotifyGroupItem.h" +#include "feeds/WireNotifyPostItem.h" #include "settings/rsettingswin.h" #include "settings/rsharesettings.h" @@ -83,7 +86,8 @@ NewsFeed::NewsFeed(QWidget *parent) : MainPage(parent), ui(new Ui::NewsFeed), RsEventType::GXS_CHANNELS , RsEventType::GXS_FORUMS , RsEventType::GXS_POSTED , - RsEventType::MAIL_STATUS + RsEventType::MAIL_STATUS , + RsEventType::WIRE }) { /* Invoke the Qt Designer generated object setup routine */ @@ -129,6 +133,9 @@ NewsFeed::NewsFeed(QWidget *parent) : MainPage(parent), ui(new Ui::NewsFeed), "
  • Channel and Board comments
  • " "
  • New Mail messages
  • " "
  • Private messages from your friends
  • " +#ifdef RS_USE_WIRE + "
  • New Wire pulses and mentions
  • " +#endif "

    " ).arg(QString::number(2*H)); @@ -216,6 +223,10 @@ void NewsFeed::handleEvent_main_thread(std::shared_ptr event) if(event->mType == RsEventType::MAIL_STATUS && (!!(flags & RsFeedTypeFlags::RS_FEED_TYPE_MSG))) handleMailEvent(event); + + if(event->mType == RsEventType::WIRE && (!!(flags & RsFeedTypeFlags::RS_FEED_TYPE_WIRE))) + handleWireEvent(event); + } void NewsFeed::handleMailEvent(std::shared_ptr event) @@ -503,6 +514,44 @@ void NewsFeed::handleSecurityEvent(std::shared_ptr event) MessageComposer::addConnectAttemptMsg(e.mPgpId, e.mSslId, QString::fromStdString(det.name + "(" + det.location + ")")); } +void NewsFeed::handleWireEvent(std::shared_ptr event) +{ + const RsWireEvent *pe = + dynamic_cast(event.get()); + if(!pe) return; + + switch(pe->mWireEventCode) + { + case RsWireEventCode::FOLLOW_STATUS_CHANGED: + addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true)); + break; + case RsWireEventCode::NEW_WIRE: + addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true)); + break; + case RsWireEventCode::NEW_POST: + addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); + break; + case RsWireEventCode::NEW_REPLY: + addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); + break; + case RsWireEventCode::NEW_REPUBLISH: + addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); + break; + case RsWireEventCode::NEW_LIKE: + addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); + break; + case RsWireEventCode::WIRE_UPDATED: + addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true)); + break; +// case RsWireEventCode::POST_UPDATED: +// addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true)); +// break; + default: break; + } + sendNewsFeedChanged(); +} + + void NewsFeed::testFeeds(RsFeedTypeFlags /*notifyFlags*/) { RsFeedTypeFlags flags = RsFeedTypeFlags(Settings->getNewsFeedFlags()); diff --git a/retroshare-gui/src/gui/NewsFeed.h b/retroshare-gui/src/gui/NewsFeed.h index fed1d41b5..b1bc2d967 100644 --- a/retroshare-gui/src/gui/NewsFeed.h +++ b/retroshare-gui/src/gui/NewsFeed.h @@ -49,6 +49,7 @@ const uint32_t NEWSFEED_POSTEDNEWLIST = 0x000b; const uint32_t NEWSFEED_POSTEDMSGLIST = 0x000c; const uint32_t NEWSFEED_CIRCLELIST = 0x000d; const uint32_t NEWSFEED_CHANNELPUBKEYLIST= 0x000e; +const uint32_t NEWSFEED_WIRELIST = 0X000f; namespace Ui { class NewsFeed; @@ -107,6 +108,7 @@ private: void handleMailEvent(std::shared_ptr event); void handlePostedEvent(std::shared_ptr event); void handleChannelEvent(std::shared_ptr event); + void handleWireEvent(std::shared_ptr event); void addFeedItem(FeedItem *item); void addFeedItemIfUnique(FeedItem *item, bool replace); diff --git a/retroshare-gui/src/gui/RetroShareLink.cpp b/retroshare-gui/src/gui/RetroShareLink.cpp index 5f9ba9339..66f9397aa 100644 --- a/retroshare-gui/src/gui/RetroShareLink.cpp +++ b/retroshare-gui/src/gui/RetroShareLink.cpp @@ -33,6 +33,7 @@ #include "FileTransfer/SearchDialog.h" #include "gxschannels/GxsChannelDialog.h" #include "gxsforums/GxsForumsDialog.h" +#include "TheWire/WireDialog.h" #include "msgs/MessageComposer.h" #include "Posted/PostedDialog.h" #include "util/misc.h" @@ -74,7 +75,8 @@ #define HOST_IDENTITY "identity" #define HOST_FILE_TREE "collection" #define HOST_CHAT_ROOM "chat_room" -#define HOST_REGEXP "file|person|forum|channel|search|message|certificate|extra|private_chat|public_msg|posted|identity|collection|chat_room" +#define HOST_REGEXP "file|person|forum|channel|wire|search|message|certificate|extra|private_chat|public_msg|posted|identity|collection|chat_room" +#define HOST_WIRE "wire" #define FILE_NAME "name" #define FILE_SIZE "size" @@ -92,6 +94,10 @@ #define CHANNEL_ID "id" #define CHANNEL_MSGID "msgid" +#define WIRE_NAME "name" +#define WIRE_ID "id" +#define WIRE_MSGID "msgid" + #define SEARCH_KEYWORDS "keywords" #define MESSAGE_ID "id" @@ -289,6 +295,19 @@ void RetroShareLink::fromUrl(const QUrl& url) return; } + if (url.host() == HOST_WIRE) { + _type = TYPE_WIRE; + _name = decodedQueryItemValue(urlQuery, WIRE_NAME); + _hash = urlQuery.queryItemValue(WIRE_ID); + _msgId = urlQuery.queryItemValue(WIRE_MSGID); + +#ifdef DEBUG_RSLINK + std::cerr << "Got a wire link!!" << std::endl; +#endif + check(); + return; + } + if (url.host() == HOST_SEARCH) { _type = TYPE_SEARCH; _name = decodedQueryItemValue(urlQuery, SEARCH_KEYWORDS); @@ -468,7 +487,7 @@ RetroShareLink RetroShareLink::createPerson(const RsPgpId& id) return link; } -//For Forum, Channel & Posted +//For Forum, Channel, Posted and Wire RetroShareLink RetroShareLink::createGxsGroupLink(const RetroShareLink::enumType &linkType, const RsGxsGroupId &groupId, const QString &groupName) { RetroShareLink link; @@ -793,6 +812,17 @@ void RetroShareLink::check() _valid = false; break; + case TYPE_WIRE: + if(_size != 0) + _valid = false; + + if(_name.isEmpty()) + _valid = false; + + if(_hash.isEmpty()) + _valid = false; + break; + case TYPE_SEARCH: if(_size != 0) _valid = false; @@ -886,6 +916,8 @@ QString RetroShareLink::title() const return QString("Forum id: %1").arg(hash()); case TYPE_CHANNEL: return QString("Channel id: %1").arg(hash()); + case TYPE_WIRE: + return QString("Wire id: %1").arg(hash()); case TYPE_SEARCH: return QString("Search files"); @@ -1073,6 +1105,17 @@ QString RetroShareLink::toString() const break; + case TYPE_WIRE: + url.setScheme(RSLINK_SCHEME); + url.setHost(HOST_WIRE); + urlQuery.addQueryItem(WIRE_NAME, encodeItem(_name)); + urlQuery.addQueryItem(WIRE_ID, _hash); + if (!_msgId.isEmpty()) { + urlQuery.addQueryItem(WIRE_MSGID, _msgId); + } + + break; + } #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) @@ -1307,6 +1350,7 @@ static void processList(const QStringList &list, const QString &textSingular, co case TYPE_FILE: case TYPE_FORUM: case TYPE_CHANNEL: + case TYPE_WIRE: case TYPE_SEARCH: case TYPE_MESSAGE: case TYPE_CERTIFICATE: @@ -1355,6 +1399,12 @@ static void processList(const QStringList &list, const QString &textSingular, co QStringList channelUnknown; QStringList channelMsgUnknown; + // wire + QStringList wireFound; + QStringList wireMsgFound; + QStringList wireUnknown; + QStringList wireMsgUnknown; + // search QStringList searchStarted; @@ -1381,9 +1431,9 @@ static void processList(const QStringList &list, const QString &textSingular, co QList processedList; QList errorList; - processedList << &fileAdded << &personAdded << &forumFound << &channelFound << &searchStarted << &messageStarted << &postedFound << &chatroomFound; - errorList << &fileExist << &personExist << &personFailed << &personNotFound << &forumUnknown << &forumMsgUnknown << &channelUnknown << &channelMsgUnknown << &messageReceipientNotAccepted << &messageReceipientUnknown << &postedUnknown << &postedMsgUnknown << &chatroomUnknown; - // not needed: forumFound, channelFound, messageStarted + processedList << &fileAdded << &personAdded << &forumFound << &channelFound << &wireFound << &searchStarted << &messageStarted << &postedFound << &chatroomFound; + errorList << &fileExist << &personExist << &personFailed << &personNotFound << &forumUnknown << &forumMsgUnknown << &channelUnknown << &channelMsgUnknown << &wireUnknown << &wireMsgUnknown << &messageReceipientNotAccepted << &messageReceipientUnknown << &postedUnknown << &postedMsgUnknown << &chatroomUnknown; + // not needed: forumFound, channelFound, wireFound, messageStarted // we want to merge all single file links into one collection // if a collection tree link is found it is processed independen for the other file links @@ -1475,6 +1525,34 @@ static void processList(const QStringList &list, const QString &textSingular, co } break; + case TYPE_WIRE: + { + #ifdef DEBUG_RSLINK + std::cerr << " RetroShareLink::process WireRequest : name : " << link.name().toStdString() << ". id : " << link.hash().toStdString() << ". msgId : " << link.msgId().toStdString() << std::endl; + #endif + + MainWindow::showWindow(MainWindow::Wire); + WireDialog *wireDialog = dynamic_cast(MainWindow::getPage(MainWindow::Wire)); + if (!wireDialog) { + return false; + } + + if (wireDialog->navigate(RsGxsGroupId(link.id().toStdString()), RsGxsMessageId(link.msgId().toStdString()))) { + if (link.msgId().isEmpty()) { + wireFound.append(link.name()); + } else { + wireMsgFound.append(link.name()); + } + } else { + if (link.msgId().isEmpty()) { + wireUnknown.append(link.name()); + } else { + wireMsgUnknown.append(link.name()); + } + } + } + break; + case TYPE_SEARCH: { #ifdef DEBUG_RSLINK @@ -1764,7 +1842,7 @@ static void processList(const QStringList &list, const QString &textSingular, co } else { - ChatDialog* chatDialog = ChatDialog::getChat(chatId, (RsChatFlags)Settings->getChatFlags()); + ChatDialog* chatDialog = ChatDialog::getChat(chatId, (RsChatFlags)Settings->getChatFlags()); if (chatDialog) { chatroomFound.append(link.name()); } else { @@ -1861,6 +1939,16 @@ static void processList(const QStringList &list, const QString &textSingular, co } } + // wire + if (flag & RSLINK_PROCESS_NOTIFY_ERROR) { + if (!wireUnknown.isEmpty()) { + processList(wireUnknown, QObject::tr("Wire not found"), QObject::tr("Wires not found"), result); + } + if (!wireMsgUnknown.isEmpty()) { + processList(wireMsgUnknown, QObject::tr("Wire message not found"), QObject::tr("Wire messages not found"), result); + } + } + // message if (flag & RSLINK_PROCESS_NOTIFY_ERROR) { if (!messageReceipientNotAccepted.isEmpty()) { @@ -2044,3 +2132,4 @@ void RSLinkClipboard::parseText(QString text, QList &links,Retro pos += rx.matchedLength(); } } + diff --git a/retroshare-gui/src/gui/RetroShareLink.h b/retroshare-gui/src/gui/RetroShareLink.h index 2225392fe..d3cdfda16 100644 --- a/retroshare-gui/src/gui/RetroShareLink.h +++ b/retroshare-gui/src/gui/RetroShareLink.h @@ -75,7 +75,8 @@ class RetroShareLink TYPE_POSTED = 0x0b, TYPE_IDENTITY = 0x0c, TYPE_FILE_TREE = 0x0d, - TYPE_CHAT_ROOM = 0x0e + TYPE_CHAT_ROOM = 0x0e, + TYPE_WIRE = 0x0f }; public: diff --git a/retroshare-gui/src/gui/TheWire/PulseReply.cpp b/retroshare-gui/src/gui/TheWire/PulseReply.cpp index 5067b5f9b..ca65570c1 100644 --- a/retroshare-gui/src/gui/TheWire/PulseReply.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseReply.cpp @@ -57,6 +57,8 @@ void PulseReply::setup() connect(toolButton_republish, SIGNAL(clicked()), this, SLOT(actionRepublish())); connect(toolButton_like, SIGNAL(clicked()), this, SLOT(actionLike())); connect(toolButton_view, SIGNAL(clicked()), this, SLOT(actionViewPulse())); + // hided it takes to much space + label_authorName->hide(); } void PulseReply::showReplyLine(bool enable) @@ -150,6 +152,44 @@ void PulseReply::setReferenceString(QString ref) void PulseReply::mousePressEvent(QMouseEvent *event) { + // Check if the event is a left mouse button press +// if (event->button() == Qt::LeftButton && (IS_MSG_UNREAD(mPulse->mMeta.mMsgStatus) || IS_MSG_NEW(mPulse->mMeta.mMsgStatus))) + if (event->button() == Qt::LeftButton && (IS_MSG_UNPROCESSED(mPulse->mMeta.mMsgStatus))) + + { + uint32_t token; + // Perform some action when the left mouse button is pressed + RsGxsGrpMsgIdPair msgPair = std::make_pair(mPulse->mMeta.mGroupId, mPulse->mMeta.mMsgId); + + rsWire->setMessageReadStatus(token, msgPair, true); + std::cout << "Left mouse button pressed on PulseReply!" <button() == Qt::LeftButton; + std::cout << "the first condition:"<< one <mMeta.mMsgStatus); + std::cout << "the second condition:"<< one <mMeta.mMsgStatus); + std::cout << "the third condition:"<< one <mMeta.mMsgStatus); + std::cout << "the fourth condition:"<< one <groupId(), item->messageId()); + +// rsWire->setMessageReadStatus(token, msgPair, read); +// } +//} + diff --git a/retroshare-gui/src/gui/TheWire/PulseReply.ui b/retroshare-gui/src/gui/TheWire/PulseReply.ui index 497d606de..774948559 100644 --- a/retroshare-gui/src/gui/TheWire/PulseReply.ui +++ b/retroshare-gui/src/gui/TheWire/PulseReply.ui @@ -511,7 +511,7 @@ Qt::Horizontal - QSizePolicy::Fixed + QSizePolicy::Expanding @@ -532,21 +532,11 @@ <html><head/><body><p><span style=" color:#2e3436;">· Apr 13 ·</span></p></body></html> + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + - - - - Qt::Horizontal - - - - 64 - 18 - - - - diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui b/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui index 79d9964f6..9faac4ab0 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui @@ -25,6 +25,18 @@ + + 0 + + + 0 + + + 0 + + + 0 + diff --git a/retroshare-gui/src/gui/TheWire/PulseViewItem.cpp b/retroshare-gui/src/gui/TheWire/PulseViewItem.cpp index b46737bfd..3df22aebb 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewItem.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseViewItem.cpp @@ -463,3 +463,16 @@ QString ToNumberUnits(uint32_t count) return ans; } +void PulseDataItem::mousePressEvent(QMouseEvent *event) +{ + // Check if the event is a left mouse button press + if (event->button() == Qt::LeftButton) + { + // Perform some action when the left mouse button is pressed + std::cout << "Left mouse button pressed on PulseViewItem!" < #include @@ -55,11 +60,11 @@ #define WIRE_TOKEN_TYPE_SUBSCRIBE_CHANGE 1 - +#define TOKEN_TYPE_GROUP_SUMMARY 1 /** Constructor */ WireDialog::WireDialog(QWidget *parent) - : MainPage(parent), mGroupSet(GROUP_SET_ALL) + : GxsStatisticsProvider(rsWire, settingsGroupName(),parent, true), mGroupSet(GROUP_SET_ALL) , mAddDialog(nullptr), mGroupSelected(nullptr), mWireQueue(nullptr) , mHistoryIndex(-1), mEventHandlerId(0) { @@ -82,6 +87,9 @@ WireDialog::WireDialog(QWidget *parent) /* setup TokenQueue */ mWireQueue = new TokenQueue(rsWire->getTokenService(), this); + mCountChildMsgs = false; + mShouldUpdateGroupStatistics = false; + mDistSyncAllowed = true; requestGroupData(); @@ -110,27 +118,50 @@ void WireDialog::handleEvent_main_thread(std::shared_ptr event) #endif // The following switch statements refresh the wire feed whenever there is a new event + + std::cout<<"***************the wire event code is ************************* "<mWireEventCode) { + + case RsWireEventCode::READ_STATUS_CHANGED: + updateGroupStatisticsReal(e->mWireGroupId); // update the list immediately + std::cout<<"1"<mWireGroupId); + break; default: - refreshGroups(); +#ifdef GXSWIRE_DEBUG + RsDbg() << " Unknown event occured: "<< e->mWireEventCode << std::endl; +#endif break; } + refreshGroups(); } } @@ -140,12 +171,149 @@ WireDialog::~WireDialog() processSettings(false); clearTwitterView(); - std::cerr << "WireDialog::~WireDialog()" << std::endl; delete(mWireQueue); rsEvents->unregisterEventsHandler(mEventHandlerId); } +UserNotify *WireDialog::createUserNotify(QObject *parent) +{ + return new WireUserNotify(rsWire, this, parent); +} + +//QString WireDialog::getHelpString() const +//{ +// int H = misc::getFontSizeFactor("HelpButton").height(); + +// QString hlp_str = tr( +// "

      Boards

    " +// "

    The wire service is a day to day social network service.

    " +// "

    The Wire service allows you to share your pulses, republish someone else's pulses, like " +// "a pulse.

    " +// "

    A pulse is like a channel or board post. It can be a image or a text or both. You can " +// "only see the pulses of the people you follow.

    " +// "

    Wire posts are kept for %2 days, and sync-ed over the last %3 days, unless you change this.

    " +// ).arg( QString::number(2*H) +// , QString::number(rsWire->getDefaultStoragePeriod()/86400) +// , QString::number(rsWire->getDefaultSyncPeriod()/86400)); + +// return hlp_str ; +//} + +//QString WireDialog::text(TextType type) +//{ +// switch (type) { +// case TEXT_NAME: +// return tr("Wire"); +// case TEXT_NEW: +// return tr("Create Wire"); + +//// Dont know what this does +//// case TEXT_TODO: +//// return "Open points:
      " +//// "
    • Subreddits/tag to posts support" +//// "
    • Picture Support" +//// "
    • Navigate channel link" +//// "
    "; + +// case TEXT_YOUR_GROUP: +// return tr("My Wire"); +// case TEXT_SUBSCRIBED_GROUP: +// return tr("Followed Wires"); +// case TEXT_POPULAR_GROUP: +// return tr("Popular Wires"); +// case TEXT_OTHER_GROUP: +// return tr("Other Wires"); +// } + +// return ""; +//} + +//QString WireDialog::icon(IconType type) +//{ +// switch (type) { +// case ICON_NAME: +// return ":/icons/png/postedlinks.png"; +// case ICON_NEW: +// return ":/icons/png/add.png"; +// case ICON_YOUR_GROUP: +// return ""; +// case ICON_SUBSCRIBED_GROUP: +// return ""; +// case ICON_POPULAR_GROUP: +// return ""; +// case ICON_OTHER_GROUP: +// return ""; +// case ICON_SEARCH: +// return ":/images/find.png"; +// case ICON_DEFAULT: +// return ":/icons/png/posted.png"; +// } + +// return ""; +//} + +//bool WireDialog::getGroupData(std::list& groupInfo) +//{ +// std::vector groups; + +// // request all group infos at once + +// if(! rsWire->getGroups(std::list(),groups)) +// return false; + +// /* Save groups to fill icons and description */ + +// for (auto& group: groups) +// groupInfo.push_back(new RsWireGroup(group)); + +// return true; +//} + +bool WireDialog::getGroupStatistics(const RsGxsGroupId& groupId,GxsGroupStatistic& stat) +{ + // What follows is a hack to replace the GXS group statistics by the actual count of unread messages in wire, + // which should take into account old post versions, discard replies and likes, etc. + + RsWireStatistics s; + bool res = rsWire->getWireStatistics(groupId,s); + + if(!res) + return false; + + stat.mGrpId = groupId; + stat.mNumMsgs = s.mNumberOfPulses; + + stat.mTotalSizeOfMsgs = 0; // hopefuly unused. Required the loading of the full channel data, so not very convenient. + stat.mNumThreadMsgsNew = s.mNumberOfNewPulses; + stat.mNumThreadMsgsUnread = s.mNumberOfUnreadPulses; + stat.mNumChildMsgsNew = 0; + stat.mNumChildMsgsUnread = 0; + + return true; +} + +//GxsGroupDialog *WireDialog::createNewGroupDialog() +//{ +// return new WireGroupDialog(this); +//} + +//GxsGroupDialog *WireDialog::createGroupDialog(GxsGroupDialog::Mode mode, RsGxsGroupId groupId) +//{ +// return new WireGroupDialog(mode, groupId, this); +//} + +//int WireDialog::shareKeyType() +//{ +// return GroupShareKey::NO_KEY_SHARE; +//} + +//GxsMessageFrameWidget *WireDialog::createMessageFrameWidget(const RsGxsGroupId &groupId) +//{ +// // to do +//// return new WireListWidgetWithModel(groupId); +//} + void WireDialog::processSettings(bool load) { Settings->beginGroup("WireDialog"); @@ -475,13 +643,13 @@ bool WireDialog::loadGroupData(const uint32_t &token) std::cerr << "WireDialog::loadGroupData()"; std::cerr << std::endl; - std::vector groups; - rsWire->getGroupData(token, groups); + std::vector groups; + rsWire->getGroupData(token, groups); - // save list of groups. - updateGroups(groups); - showGroups(); - return true; + // save list of groups. + updateGroups(groups); + showGroups(); + return true; } rstime_t WireDialog::getFilterTimestamp() @@ -689,7 +857,6 @@ void WireDialog::PVHrate(const RsGxsId &authorId) void WireDialog::postTestTwitterView() { clearTwitterView(); - std::cerr << "WireDialog::postTestTwitterView()" << std::endl; addTwitterView(new PulseTopLevel(NULL,RsWirePulseSPtr())); addTwitterView(new PulseReply(NULL,RsWirePulseSPtr())); @@ -846,7 +1013,6 @@ void WireDialog::requestPulseFocus(const RsGxsGroupId groupId, const RsGxsMessag void WireDialog::showPulseFocus(const RsGxsGroupId groupId, const RsGxsMessageId msgId) { clearTwitterView(); - std::cerr << "WireDialog::showPulseFocus()" << std::endl; // background thread for loading. RsThread::async([this, groupId, msgId]() @@ -876,8 +1042,6 @@ void WireDialog::showPulseFocus(const RsGxsGroupId groupId, const RsGxsMessageId void WireDialog::postPulseFocus(RsWirePulseSPtr pPulse) { clearTwitterView(); - std::cerr << "WireDialog::postPulseFocus()" << std::endl; - if (!pPulse) { std::cerr << "WireDialog::postPulseFocus() Invalid pulse"; @@ -950,7 +1114,7 @@ void WireDialog::requestGroupFocus(const RsGxsGroupId groupId) void WireDialog::showGroupFocus(const RsGxsGroupId groupId) { clearTwitterView(); - std::cerr << "WireDialog::showGroupFocus()" << std::endl; + // background thread for loading. RsThread::async([this, groupId]() { @@ -980,6 +1144,8 @@ void WireDialog::showGroupFocus(const RsGxsGroupId groupId) void WireDialog::postGroupFocus(RsWireGroupSPtr group, std::list pulses) { + clearTwitterView(); + std::cerr << "WireDialog::postGroupFocus()"; std::cerr << std::endl; @@ -1027,7 +1193,6 @@ void WireDialog::requestGroupsPulses(const std::list& groupIds) void WireDialog::showGroupsPulses(const std::list& groupIds) { clearTwitterView(); - std::cerr << "WireDialog::showGroupPulses()" << std::endl; // background thread for loading. RsThread::async([this, groupIds]() @@ -1054,6 +1219,7 @@ void WireDialog::showGroupsPulses(const std::list& groupIds) void WireDialog::postGroupsPulses(std::list pulses) { + clearTwitterView(); std::cerr << "WireDialog::postGroupsPulses()"; std::cerr << std::endl; @@ -1077,3 +1243,187 @@ void WireDialog::postGroupsPulses(std::list pulses) } } + +void WireDialog::getServiceStatistics(GxsServiceStatistic& stats) const +{ + std::cout<<"inside the getServiceStatics *********"<beginGroup(mSettingsName); + Settings->setValue("NumMsgs", stats.mNumMsgs ); + Settings->setValue("NumGrps", stats.mNumGrps ); + Settings->setValue("SizeOfMessages", stats.mSizeOfMsgs ); + Settings->setValue("NumThreadMsgsNew", stats.mNumThreadMsgsNew ); + Settings->setValue("NumThreadMsgsUnread",stats.mNumThreadMsgsUnread); + Settings->setValue("NumChildMsgsNew", stats.mNumChildMsgsNew ); + Settings->setValue("NumChildMsgsUnread", stats.mNumChildMsgsUnread ); + Settings->endGroup(); + } + else // Get statistics from settings if no cache is already present: allows to display at start. + { + Settings->beginGroup(mSettingsName); + + stats.mNumMsgs = Settings->value("NumMsgs",QVariant(0)).toInt(); + stats.mNumGrps = Settings->value("NumGrps",QVariant(0)).toInt(); + stats.mSizeOfMsgs = Settings->value("SizeOfMessages",QVariant(0)).toInt(); + stats.mNumThreadMsgsNew = Settings->value("NumThreadMsgsNew",QVariant(0)).toInt(); + stats.mNumThreadMsgsUnread = Settings->value("NumThreadMsgsUnread",QVariant(0)).toInt(); + stats.mNumChildMsgsNew = Settings->value("NumChildMsgsNew",QVariant(0)).toInt(); + stats.mNumChildMsgsUnread = Settings->value("NumChildMsgsUnread",QVariant(0)).toInt(); + + Settings->endGroup(); + } +} + +void WireDialog::updateGroupStatistics(const RsGxsGroupId &groupId) +{ + mGroupStatisticsToUpdate.insert(groupId); + mShouldUpdateGroupStatistics = true; +} + +void WireDialog::updateGroupStatisticsReal(const RsGxsGroupId &groupId) +{ + RsThread::async([this,groupId]() + { + GxsGroupStatistic stats; + + if(! getGroupStatistics(groupId, stats)) + { + std::cerr << __PRETTY_FUNCTION__ << " failed to collect group statistics for group " << groupId << std::endl; + return; + } + + RsQThreadUtils::postToObject( [this,stats, groupId]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete, note that + * Qt::QueuedConnection is important! + */ + +// QTreeWidgetItem *item = ui.scrollAreaWidgetContents->getItemFromId(QString::fromStdString(stats.mGrpId.toStdString())); + +// if (item) +// ui.scrollAreaWidgetContents->setUnreadCount(item, mCountChildMsgs ? (stats.mNumThreadMsgsUnread + stats.mNumChildMsgsUnread) : stats.mNumThreadMsgsUnread); + + mCachedGroupStats[groupId] = stats; + + getUserNotify()->updateIcon(); + + }, this ); + }); +} + +bool WireDialog::navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msgId) +{ + if (groupId.isNull()) { + return false; + } + +// if (mStateHelper->isLoading(TOKEN_TYPE_GROUP_SUMMARY)) { +// mNavigatePendingGroupId = groupId; +// mNavigatePendingMsgId = msgId; + +// /* No information if group is available */ +// return true; +// } + +// QString groupIdString = QString::fromStdString(groupId.toStdString()); +// if (ui.groupTreeWidget->activateId(groupIdString, msgId.isNull()) == NULL) { +// return false; +// } + +// changedCurrentGroup(groupIdString); + + /* search exisiting tab */ +// GxsMessageFrameWidget *msgWidget = messageWidget(mGroupId); +// if (!msgWidget) { +// return false; +// } + +// if (msgId.isNull()) { +// return true; +// } + +// return msgWidget->navigate(msgId); + return true; +} + +GxsMessageFrameWidget *WireDialog::messageWidget(const RsGxsGroupId &groupId) +{ +// int tabCount = ui.tabWidget->count(); + +// for (int index = 0; index < tabCount; ++index) +// { +// GxsMessageFrameWidget *childWidget = dynamic_cast(ui.tabWidget->widget(index)); + +// if (childWidget && childWidget->groupId() == groupId) +// return childWidget; +// } + + return NULL; +} + +//void GxsGroupFrameDialog::changedCurrentGroup(const QString& groupId) +//{ +// if (mInFill) { +// return; +// } + +// if (groupId.isEmpty()) +// { +// auto w = currentWidget(); + +// if(w) +// w->setGroupId(RsGxsGroupId()); + +// return; +// } + +// mGroupId = RsGxsGroupId(groupId.toStdString()); + +// if (mGroupId.isNull()) +// return; + +// /* search exisiting tab */ +// GxsMessageFrameWidget *msgWidget = messageWidget(mGroupId); + +// // check that we have at least one tab + +// if(msgWidget) +// ui.messageTabWidget->setCurrentWidget(msgWidget); +// else +// { +// if(useTabs() || ui.messageTabWidget->count()==0) +// { +// msgWidget = createMessageWidget(RsGxsGroupId(groupId.toStdString())); +// ui.messageTabWidget->setCurrentWidget(msgWidget); +// } +// else +// currentWidget()->setGroupId(mGroupId); +// } +//} diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.h b/retroshare-gui/src/gui/TheWire/WireDialog.h index fcd33ad37..9ce11ca52 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.h +++ b/retroshare-gui/src/gui/TheWire/WireDialog.h @@ -34,7 +34,7 @@ #include "gui/TheWire/PulseViewItem.h" #include "gui/TheWire/PulseTopLevel.h" #include "gui/TheWire/PulseReply.h" - +#include "gui/gxs/GxsStatisticsProvider.h" #include "util/TokenQueue.h" @@ -68,7 +68,7 @@ public: }; //--------------------------------------------------------- -class WireDialog : public MainPage, public TokenResponse, public WireGroupHolder, public PulseViewHolder +class WireDialog : public GxsStatisticsProvider, public TokenResponse, public WireGroupHolder, public PulseViewHolder { Q_OBJECT @@ -118,6 +118,17 @@ public: void showGroupsPulses(const std::list& groupIds); void postGroupsPulses(std::list pulses); + void getServiceStatistics(GxsServiceStatistic& stats) const ; + + virtual bool navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msgId) override; + +protected: + + bool getGroupStatistics(const RsGxsGroupId& groupId,GxsGroupStatistic& stat) override; + UserNotify *createUserNotify(QObject *parent) override; + virtual void updateGroupStatistics(const RsGxsGroupId &groupId) override; + virtual void updateGroupStatisticsReal(const RsGxsGroupId &groupId) override; + private slots: void createGroup(); @@ -150,11 +161,14 @@ private: // Loading Data. void requestGroupData(); - bool loadGroupData(const uint32_t &token); + bool loadGroupData(const uint32_t &token); void acknowledgeGroup(const uint32_t &token, const uint32_t &userType); virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req) override; + virtual QString settingsGroupName() override{ return "PostedDialog"; } + virtual GxsMessageFrameWidget *messageWidget(const RsGxsGroupId &groupId) override; + int mGroupSet; PulseAddDialog *mAddDialog; diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.ui b/retroshare-gui/src/gui/TheWire/WireDialog.ui index 4cdf4a174..ad28fba5e 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.ui +++ b/retroshare-gui/src/gui/TheWire/WireDialog.ui @@ -224,7 +224,7 @@
    - + 3 @@ -432,6 +432,12 @@ QComboBox
    gui/common/RSComboBox.h
    + + RSTabWidget + QTabWidget +
    gui/common/RSTabWidget.h
    + 1 +
    diff --git a/retroshare-gui/src/gui/TheWire/WireUserNotify.cpp b/retroshare-gui/src/gui/TheWire/WireUserNotify.cpp new file mode 100644 index 000000000..c3e0e1c03 --- /dev/null +++ b/retroshare-gui/src/gui/TheWire/WireUserNotify.cpp @@ -0,0 +1,62 @@ +/******************************************************************************* + * retroshare-gui/src/gui/TheWire/WireUserNotify.cpp * + * * + * Copyright (C) 2014 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 . * + * * + *******************************************************************************/ + +#include "retroshare/rswire.h" +#include "WireUserNotify.h" +#include "gui/MainWindow.h" +#include "gui/common/FilesDefs.h" + +WireUserNotify::WireUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsStatisticsProvider *g, QObject *parent) : + GxsUserNotify(ifaceImpl, g, parent) +{ +} + +bool WireUserNotify::hasSetting(QString *name, QString *group) +{ + if (name) *name = tr("Wire Post"); + if (group) *group = "Wire"; + + return true; +} + +QIcon WireUserNotify::getIcon() +{ + return FilesDefs::getIconFromQtResourcePath(":/icons/png/wire-circle.png"); +} + +QIcon WireUserNotify::getMainIcon(bool hasNew) +{ + return hasNew ? FilesDefs::getIconFromQtResourcePath(":/icons/png/wire-notify.png") : FilesDefs::getIconFromQtResourcePath(":/icons/png/wire-circle.png"); +} + +//QString PostedUserNotify::getTrayMessage(bool plural) +//{ +// return plural ? tr("You have %1 new board posts") : tr("You have %1 new board post"); +//} + +//QString PostedUserNotify::getNotifyMessage(bool plural) +//{ +// return plural ? tr("%1 new board post") : tr("%1 new board post"); +//} + +void WireUserNotify::iconClicked() +{ + MainWindow::showWindow(MainWindow::Wire); +} \ No newline at end of file diff --git a/retroshare-gui/src/gui/TheWire/WireUserNotify.h b/retroshare-gui/src/gui/TheWire/WireUserNotify.h new file mode 100644 index 000000000..d3a44fd7e --- /dev/null +++ b/retroshare-gui/src/gui/TheWire/WireUserNotify.h @@ -0,0 +1,42 @@ +/******************************************************************************* + * retroshare-gui/src/gui/TheWire/WireUserNotify.h * + * * + * Copyright (C) 2014 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 WIREUSERNOTIFY_H +#define WIREUSERNOTIFY_H + +#include "gui/gxs/GxsUserNotify.h" + +class WireUserNotify : public GxsUserNotify +{ + Q_OBJECT + +public: + explicit WireUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsStatisticsProvider *g, QObject *parent = 0); + + virtual bool hasSetting(QString *name, QString *group) override; + +private: + virtual QIcon getIcon() override; + virtual QIcon getMainIcon(bool hasNew) override; + + virtual void iconClicked() override; +}; + +#endif // WIREUSERNOTIFY_H \ No newline at end of file diff --git a/retroshare-gui/src/gui/common/NotifyWidget.cpp b/retroshare-gui/src/gui/common/NotifyWidget.cpp new file mode 100644 index 000000000..9fe2f4abf --- /dev/null +++ b/retroshare-gui/src/gui/common/NotifyWidget.cpp @@ -0,0 +1,65 @@ +#include "NotifyWidget.h" +#include "ui_NotifyWidget.h" +#include "RSTreeWidgetItem.h" + +#define ROLE_ID Qt::UserRole +#define ROLE_NAME Qt::UserRole + 1 +#define ROLE_DESCRIPTION Qt::UserRole + 2 +#define ROLE_SUBSCRIBE_FLAGS Qt::UserRole + 3 +#define ROLE_COLOR Qt::UserRole + 4 +#define ROLE_REQUEST_ID Qt::UserRole + 5 +#define ROLE_SORT Qt::UserRole + 6 + +NotifyWidget::NotifyWidget(QWidget *parent) : + QWidget(parent), + ui(new Ui::NotifyWidget) +{ + ui->setupUi(this); +} + +NotifyWidget::~NotifyWidget() +{ + delete ui; +} + +void NotifyWidget::setUnreadCount(QTreeWidgetItem *item, int unreadCount) +{ + if (item == NULL) { + return; + } + + QFont itFont = item->font(GTW_COLUMN_NAME); + + if (unreadCount) { + item->setText(GTW_COLUMN_UNREAD, QString::number(unreadCount)); + itFont.setBold(true); + } else { + item->setText(GTW_COLUMN_UNREAD, ""); + itFont.setBold(false); + } + item->setData(GTW_COLUMN_UNREAD, ROLE_SORT, unreadCount); + + item->setFont(GTW_COLUMN_NAME, itFont); +} + +QTreeWidgetItem *NotifyWidget::getItemFromId(const QString &id) +{ + if (id.isEmpty()) { + return NULL; + } + + /* Search exisiting item */ + QTreeWidgetItemIterator itemIterator(ui->treeWidget); + QTreeWidgetItem *item; + while ((item = *itemIterator) != NULL) { + ++itemIterator; + + if (item->parent() == NULL) { + continue; + } + if (item->data(GTW_COLUMN_DATA, ROLE_ID).toString() == id) { + return item; + } + } + return NULL ; +} diff --git a/retroshare-gui/src/gui/common/NotifyWidget.h b/retroshare-gui/src/gui/common/NotifyWidget.h new file mode 100644 index 000000000..55c536439 --- /dev/null +++ b/retroshare-gui/src/gui/common/NotifyWidget.h @@ -0,0 +1,83 @@ +/******************************************************************************* + * gui/common/NotifyWidget.h * + * * + * Copyright (C) 2010, 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 NOTIFYWIDGET_H +#define NOTIFYWIDGET_H + +#include +#include +#include + +#include + +#define GTW_COLUMN_NAME 0 +#define GTW_COLUMN_UNREAD 1 +#define GTW_COLUMN_POSTS 2 +#define GTW_COLUMN_POPULARITY 3 +#define GTW_COLUMN_LAST_POST 4 +#define GTW_COLUMN_SEARCH_SCORE 5 +#define GTW_COLUMN_DESCRIPTION 6 +#define GTW_COLUMN_COUNT 7 +#define GTW_COLUMN_DATA GTW_COLUMN_NAME + +namespace Ui { +class NotifyWidget; +} + +//class GroupItemInfo +//{ +//public: +// GroupItemInfo() +// : popularity(0), publishKey(false), adminKey(false) +// , subscribeFlags(0), max_visible_posts(0) +// {} + +//public: +// QString id; +// QString name; +// QString description; +// int popularity; +// QDateTime lastpost; +// QIcon icon; +// bool publishKey; +// bool adminKey; +// quint32 subscribeFlags; +// quint32 max_visible_posts ; +// std::set context_strings; +//}; + +class NotifyWidget : public QWidget +{ + Q_OBJECT + +public: + NotifyWidget(QWidget *parent = nullptr); + ~NotifyWidget(); + + // Set the unread count of an item + void setUnreadCount(QTreeWidgetItem *item, int unreadCount); + QTreeWidgetItem *getItemFromId(const QString &id); + +private: + Ui::NotifyWidget *ui; + +}; + +#endif // NOTIFYWIDGET_H diff --git a/retroshare-gui/src/gui/common/NotifyWidget.ui b/retroshare-gui/src/gui/common/NotifyWidget.ui new file mode 100644 index 000000000..6429f4258 --- /dev/null +++ b/retroshare-gui/src/gui/common/NotifyWidget.ui @@ -0,0 +1,66 @@ + + + NotifyWidget + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + true + + + + 0 + 0 + + + + + 11 + + + + Qt::CustomContextMenu + + + QAbstractItemView::NoEditTriggers + + + + 19 + 19 + + + + true + + + + 1 + + + + + + + + + RSTreeWidget + QTreeWidget +
    gui/common/RSTreeWidget.h
    +
    +
    + + +
    diff --git a/retroshare-gui/src/gui/feeds/FeedItem.h b/retroshare-gui/src/gui/feeds/FeedItem.h index f11424520..0d3876da6 100644 --- a/retroshare-gui/src/gui/feeds/FeedItem.h +++ b/retroshare-gui/src/gui/feeds/FeedItem.h @@ -38,6 +38,9 @@ enum class RsFeedTypeFlags: uint32_t { RS_FEED_TYPE_POSTED = 0x1000, RS_FEED_TYPE_SECURITY_IP = 0x2000, RS_FEED_TYPE_CIRCLE = 0x4000, +#ifdef RS_USE_WIRE + RS_FEED_TYPE_WIRE = 0x8000, +#endif RS_FEED_ITEM_PEER_CONNECT = RS_FEED_TYPE_PEER | 0x0001, RS_FEED_ITEM_PEER_DISCONNECT = RS_FEED_TYPE_PEER | 0x0002, diff --git a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp new file mode 100644 index 000000000..f8885d2f4 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp @@ -0,0 +1,265 @@ +/******************************************************************************* + * gui/feeds/WireNotifyGroupItem.cpp * + * * + * Copyright (c) 2014, 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 "WireNotifyGroupItem.h" +#include "ui_WireNotifyGroupItem.h" + +#include "FeedHolder.h" +#include "util/qtthreadsutils.h" +#include "gui/common/FilesDefs.h" +#include "gui/RetroShareLink.h" +#include "gui/gxs/GxsIdDetails.h" +#include "util/DateTime.h" + +/**** + * #define DEBUG_ITEM 1 + ****/ + +WireNotifyGroupItem::WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, bool autoUpdate) : + GxsGroupFeedItem(feedHolder, feedId, groupId, isHome, rsWire, autoUpdate) +{ + setup(); + requestGroup(); + addEventHandler(); +} + +WireNotifyGroupItem::WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate) : + GxsGroupFeedItem(feedHolder, feedId, group.mMeta.mGroupId, isHome, rsWire, autoUpdate) +{ + setup(); + setGroup(group); + addEventHandler(); +} + +void WireNotifyGroupItem::addEventHandler() +{ + mEventHandlerId = 0; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) + { + RsQThreadUtils::postToObject([=]() + { + const auto *e = dynamic_cast(event.get()); + + if(!e || e->mWireGroupId != this->groupId()) + return; + + switch(e->mWireEventCode) + { + case RsWireEventCode::FOLLOW_STATUS_CHANGED: + case RsWireEventCode::WIRE_UPDATED: + break; + default: + break; + } + }, this ); + }, mEventHandlerId, RsEventType::WIRE ); +} + +WireNotifyGroupItem::~WireNotifyGroupItem() +{ + rsEvents->unregisterEventsHandler(mEventHandlerId); + delete(ui); +} + +void WireNotifyGroupItem::setup() +{ + /* Invoke the Qt Designer generated object setup routine */ + ui = new(Ui::WireNotifyGroupItem); + ui->setupUi(this); + + setAttribute(Qt::WA_DeleteOnClose, true); + + /* clear ui */ + ui->nameLabel->setText(tr("Loading...")); + ui->titleLabel->clear(); + ui->descLabel->clear(); + + /* general ones */ + connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(toggle())); + connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(removeItem())); + + /* specific */ + connect(ui->subscribeButton, SIGNAL(clicked()), this, SLOT(subscribeWire())); + connect(ui->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyGroupLink())); + + //ui->copyLinkButton->hide(); // No link type at this moment + ui->nameLabel->setEnabled(false); + ui->expandFrame->hide(); +} + +bool WireNotifyGroupItem::setGroup(const RsWireGroup &group) +{ + if (groupId() != group.mMeta.mGroupId) { + std::cerr << "WireNotifyGroupItem::setContent() - Wrong id, cannot set post"; + std::cerr << std::endl; + return false; + } + mGroup = group; + fill(); + + return true; +} + +void WireNotifyGroupItem::loadGroup() +{ + RsThread::async([this]() + { + // 1 - get group data + +#ifdef DEBUG_ITEM + std::cerr << "Retrieving post data for post " << mThreadId << std::endl; +#endif + + std::vector groups; + const std::list groupIds = { groupId() }; + + if(!rsWire->getGroups(groupIds,groups)) + { + RsErr() << "WireNotifyGroupItem::loadGroup() ERROR getting data" << std::endl; + return; + } + + if (groups.size() != 1) + { + std::cerr << "WireNotifyGroupItem::loadGroup() Wrong number of Items"; + std::cerr << std::endl; + return; + } + RsWireGroup group(groups[0]); + + RsQThreadUtils::postToObject( [group,this]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete */ + + setGroup(group); + + }, this ); + }); +} + +QString WireNotifyGroupItem::groupName() +{ + return QString::fromUtf8(mGroup.mMeta.mGroupName.c_str()); +} + +void WireNotifyGroupItem::fill() +{ + /* fill in */ + +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyGroupItem::fill()"; + std::cerr << std::endl; +#endif + + // No link type at this moment + RetroShareLink link = RetroShareLink::createGxsGroupLink(RetroShareLink::TYPE_WIRE, mGroup.mMeta.mGroupId, groupName()); + ui->nameLabel->setText(link.toHtml()); + + ui->descLabel->setText(QString::fromUtf8(mGroup.mTagline.c_str())); + + if (mGroup.mHeadshot.mData != NULL) { + QPixmap wireImage; + GxsIdDetails::loadPixmapFromData(mGroup.mHeadshot.mData, mGroup.mHeadshot.mSize, wireImage,GxsIdDetails::ORIGINAL); + ui->logoLabel->setPixmap(QPixmap(wireImage)); + } else { + ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png")); + } + + //TODO - nice icon for subscribed group +// if (IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) { +// ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png")); +// } else { +// ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png")); +// } + + if (IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags)) { + ui->subscribeButton->setEnabled(false); + } else { + ui->subscribeButton->setEnabled(true); + } + + if(mGroup.mMeta.mLastPost==0) + ui->infoLastPost->setText(tr("Never")); + else + ui->infoLastPost->setText(DateTime::formatLongDateTime(mGroup.mMeta.mLastPost)); + +// if (mIsNew) +// { + ui->titleLabel->setText(tr("New Wire")); +// } +// else +// { +// ui->titleLabel->setText(tr("Updated Wire")); +// } + + if (mIsHome) + { + /* disable buttons */ + ui->clearButton->setEnabled(false); + } +} + +void WireNotifyGroupItem::toggle() +{ + expand(ui->expandFrame->isHidden()); +} + +void WireNotifyGroupItem::doExpand(bool open) +{ + if (mFeedHolder) + { + mFeedHolder->lockLayout(this, true); + } + + if (open) + { + ui->expandFrame->show(); + ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/up-arrow.png"))); + ui->expandButton->setToolTip(tr("Hide")); + } + else + { + ui->expandFrame->hide(); + ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/down-arrow.png"))); + ui->expandButton->setToolTip(tr("Expand")); + } + + emit sizeChanged(this); + + if (mFeedHolder) + { + mFeedHolder->lockLayout(this, false); + } +} + +void WireNotifyGroupItem::subscribeWire() +{ +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyGroupItem::subscribeWire()"; + std::cerr << std::endl; +#endif + + //subscribe(); does not work for wire, bug? -> GxsGroupFeedItem::subscribe() + + uint32_t token; + rsWire->subscribeToGroup(token, mGroup.mMeta.mGroupId, true); +} diff --git a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h new file mode 100644 index 000000000..0bbee742c --- /dev/null +++ b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h @@ -0,0 +1,73 @@ +/******************************************************************************* + * gui/feeds/WireNotifyGroupItem.h * + * * + * Copyright (c) 2014, 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 WIRENOTIFYGROUPITEM_H +#define WIRENOTIFYGROUPITEM_H + +#include +#include "gui/feeds/GxsGroupFeedItem.h" + +namespace Ui { +class WireNotifyGroupItem; +} + +class FeedHolder; + +class WireNotifyGroupItem : public GxsGroupFeedItem +{ + Q_OBJECT + +public: + /** Default Constructor */ + WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, bool autoUpdate); + WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate); + ~WireNotifyGroupItem(); + + bool setGroup(const RsWireGroup &group); + + uint64_t uniqueIdentifier() const override { return hash_64bits("WireNotifyGroupItem " + groupId().toStdString()) ; } + +protected: + /* FeedItem */ + virtual void doExpand(bool open); + + /* GxsGroupFeedItem */ + virtual QString groupName(); + virtual void loadGroup() override; + virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_WIRE; } + +private slots: + void toggle() override; + void subscribeWire(); + +private: + void fill(); + void setup(); + void addEventHandler(); + +private: + RsWireGroup mGroup; + + /** Qt Designer generated object */ + Ui::WireNotifyGroupItem *ui; + RsEventsHandlerId_t mEventHandlerId; +}; + +#endif // WIRENOTIFYGROUPITEM_H \ No newline at end of file diff --git a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.ui b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.ui new file mode 100644 index 000000000..7c3548c12 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.ui @@ -0,0 +1,403 @@ + + + WireNotifyGroupItem + + + + 0 + 0 + 618 + 191 + + + + + 1 + + + 1 + + + 1 + + + 1 + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 215 + 215 + 215 + + + + + + + 215 + 215 + 215 + + + + + + + + + 0 + 0 + 0 + + + + + + + 215 + 215 + 215 + + + + + + + 215 + 215 + 215 + + + + + + + + + 154 + 154 + 154 + + + + + + + 215 + 215 + 215 + + + + + + + 215 + 215 + 215 + + + + + + + + true + + + QFrame::Box + + + QFrame::Sunken + + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + + + + :/icons/png/posted.png + + + true + + + + + + + + + + 0 + 0 + + + + + 11 + 75 + true + true + + + + Wire + + + + + + + + 11 + 75 + true + true + + + + name + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 75 + true + + + + Last activity + + + + + + + + 75 + true + true + + + + TextLabel + + + + + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + <html><head/><body><p>Follow to User</p></body></html> + + + Follow + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 254 + 28 + + + + + + + + Qt::NoFocus + + + Copy RetroShare Link + + + + :/icons/png/copy.png:/icons/png/copy.png + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + Expand + + + + :/icons/png/down-arrow.png:/icons/png/down-arrow.png + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + Remove Item + + + + :/icons/png/exit2.png:/icons/png/exit2.png + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Wire Description + + + + + + + + + :/images/contacts24.png + + + + + + + + 0 + 0 + + + + Description + of Wire + + + + + + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp new file mode 100644 index 000000000..b4970e3d3 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp @@ -0,0 +1,786 @@ +/******************************************************************************* + * gui/feeds/WireNotifyPostItem.cpp * + * * + * Copyright (c) 2012, Robert Fernie * + * * + * 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 "WireNotifyPostItem.h" +#include "ui_WireNotifyPostItem.h" + +#include "FeedHolder.h" +#include "util/qtthreadsutils.h" +#include "gui/RetroShareLink.h" +#include "gui/common/FilesDefs.h" +#include "gui/gxs/GxsIdDetails.h" +#include "util/stringutil.h" +#include "util/DateTime.h" +#include "util/misc.h" + +#include +#include + +WireNotifyPostItem::WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGroupMetaData& group_meta, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate,const std::set& older_versions) : + GxsFeedItem(feedHolder, feedId, group_meta.mGroupId, messageId, isHome, rsWire, autoUpdate), + mGroupMeta(group_meta) +{ + mLoadingGroup = false; + mLoadingMessage = false; + mLoadingComment = false; + + mPulse.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded + mPulse.mMeta.mGroupId = mGroupMeta.mGroupId; + + QVector v; + //bool self = false; + + for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) + v.push_back(*it) ; + + if(older_versions.find(messageId) == older_versions.end()) + v.push_back(messageId); + + setMessageVersions(v) ; + setup(); + + // no call to loadGroup() here because we have it already. +} + +WireNotifyPostItem::WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set &older_versions) : + GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsWire, autoUpdate) // this one should be in GxsFeedItem +{ + mPulse.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded + + QVector v; + //bool self = false; + + for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) + v.push_back(*it) ; + + if(older_versions.find(messageId) == older_versions.end()) + v.push_back(messageId); + + setMessageVersions(v) ; + setup(); + + loadGroup(); +} + +void WireNotifyPostItem::paintEvent(QPaintEvent *e) +{ + /* This method employs a trick to trigger a deferred loading. The post and group is requested only + * when actually displayed on the screen. */ + + if(!mLoaded) + { + mLoaded = true ; + + std::set older_versions; // not so nice. We need to use std::set everywhere + for(auto& m:messageVersions()) + older_versions.insert(m); + + fill(); + requestMessage(); + requestComment(); + } + + GxsFeedItem::paintEvent(e) ; +} + +WireNotifyPostItem::~WireNotifyPostItem() +{ + auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(300); + + while( (mLoadingGroup || mLoadingMessage || mLoadingComment) + && std::chrono::steady_clock::now() < timeout) + { + RsDbg() << __PRETTY_FUNCTION__ << " is Waiting for " + << (mLoadingGroup ? "Group " : "") + << (mLoadingMessage ? "Message " : "") + << (mLoadingComment ? "Comment " : "") + << "loading." << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + delete ui; +} + +bool WireNotifyPostItem::isUnread() const +{ + return IS_MSG_UNREAD(mPulse.mMeta.mMsgStatus) ; +} + +void WireNotifyPostItem::setup() +{ + /* Invoke the Qt Designer generated object setup routine */ + + ui = new Ui::WireNotifyPostItem; + ui->setupUi(this); + + // Manually set icons to allow to use clever resource sharing that is missing in Qt for Icons loaded from Qt resource file. + // This is particularly important here because a wire may contain many posts, so duplicating the QImages here is deadly for the + // memory. + +// ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/thumb-default-video.png")); + //ui->warn_image_label->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/status_unknown.png")); + ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); +// ui->voteUpButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/vote_up.png")); +// ui->voteDownButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/vote_down.png")); +// ui->downloadButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/download.png")); +// ui->playButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/play.png")); + ui->commentButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/comment.png")); + //ui->editButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/pencil-edit-button.png")); +// ui->copyLinkButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/copy.png")); +// ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/down-arrow.png")); +// ui->readAndClearButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/correct.png")); +// ui->clearButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/exit2.png")); + + setAttribute(Qt::WA_DeleteOnClose, true); + + mInFill = false; + mCloseOnRead = false; + mLoaded = false; + + /* clear ui */ + ui->titleLabel->setText(tr("Loading...")); + ui->titleLabel->setOpenExternalLinks(false); //To get linkActivated working + connect(ui->titleLabel, SIGNAL(linkActivated(QString)), this, SLOT(on_linkActivated(QString))); + ui->datetimelabel->clear(); + ui->filelabel->clear(); +// ui->newCommentLabel->hide(); +// ui->commLabel->hide(); + + /* general ones */ + connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(toggle())); + connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(removeItem())); + + /* specific */ + connect(ui->readAndClearButton, SIGNAL(clicked()), this, SLOT(readAndClearItem())); + connect(ui->unsubscribeButton, SIGNAL(clicked()), this, SLOT(unsubscribeChannel())); + + connect(ui->downloadButton, SIGNAL(clicked()), this, SLOT(download())); + // HACK FOR NOW. + ui->commentButton->hide();// hidden until properly enabled. + connect(ui->commentButton, SIGNAL(clicked()), this, SLOT(loadComments())); + + connect(ui->playButton, SIGNAL(clicked()), this, SLOT(play(void))); + //connect(ui->editButton, SIGNAL(clicked()), this, SLOT(edit(void))); + connect(ui->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyMessageLink())); + + connect(ui->readButton, SIGNAL(toggled(bool)), this, SLOT(readToggled(bool))); + + // hide voting buttons, backend is not implemented yet + ui->voteUpButton->hide(); + ui->voteDownButton->hide(); + //connect(ui-> voteUpButton, SIGNAL(clicked()), this, SLOT(makeUpVote())); + //connect(ui->voteDownButton, SIGNAL(clicked()), this, SLOT(makeDownVote())); + + ui->scoreLabel->hide(); + + // hide unsubscribe button not necessary + ui->unsubscribeButton->hide(); + + ui->downloadButton->hide(); + ui->playButton->hide(); + //ui->warn_image_label->hide(); + //ui->warning_label->hide(); + + ui->titleLabel->setMinimumWidth(100); + ui->subjectLabel->setMinimumWidth(100); + //ui->warning_label->setMinimumWidth(100); + ui->titleLabel->setEnabled(false); + + ui->feedFrame->setProperty("new", false); + ui->feedFrame->style()->unpolish(ui->feedFrame); + ui->feedFrame->style()->polish( ui->feedFrame); + + ui->expandFrame->hide(); +} + +bool WireNotifyPostItem::setPost(const RsWirePulse &pulse, bool doFill) +{ + if (groupId() != pulse.mMeta.mGroupId || messageId() != pulse.mMeta.mMsgId) { + std::cerr << "WireNotifyPostItem::setPost() - Wrong id, cannot set post"; + std::cerr << std::endl; + return false; + } + + mPulse = pulse; + + if (doFill) { + fill(); + std::cout<<"filling needs to be implemented"< groupIds; + std::list pulses; +// std::vector comments; +// std::vector votes; + groupIds.push_back(groupId()); + if(! rsWire->getPulsesForGroups(groupIds, pulses)) + { + RsErr() << "WireNotifyPostItem::loadGroup() ERROR getting data" << std::endl; + return; + } + + if (pulses.size() == 1) + { +#ifdef DEBUG_ITEM + std::cerr << (void*)this << ": Obtained post, with msgId = " << pulses[0].mMeta.mMsgId << std::endl; +#endif + const RsWirePulse& pulse(*pulses.front()); + + RsQThreadUtils::postToObject( [pulse,this]() + { + setPost(pulse); + mLoadingMessage = false; + }, this ); + } +// else if(comments.size() == 1) +// { +// const RsGxsComment& cmt = comments[0]; +//#ifdef DEBUG_ITEM +// std::cerr << (void*)this << ": Obtained comment, setting messageId to threadID = " << cmt.mMeta.mThreadId << std::endl; +//#endif + +// RsQThreadUtils::postToObject( [cmt,this]() +// { +// 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(); + +// mLoadingMessage = false; +// }, this ); + +// } +// else +// { +//#ifdef DEBUG_ITEM +// std::cerr << "WireNotifyPostItem::loadMessage() Wrong number of Items. Remove It."; +// std::cerr << std::endl; +//#endif + +// RsQThreadUtils::postToObject( [this]() +// { +// removeItem(); +// mLoadingMessage = false; +// }, this ); +// } + }); +} + +void WireNotifyPostItem::loadComment() +{ +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyPostItem::loadComment()"; + std::cerr << std::endl; +#endif +// mLoadingComment = true; + +// RsThread::async([this]() +// { +// // 1 - get group data + +// std::set msgIds; + +// for(auto MsgId: messageVersions()) +// msgIds.insert(MsgId); + +// std::vector posts; +// std::vector comments; + +// if(! rsGxsChannels->getChannelComments( groupId(),msgIds,comments)) +// { +// RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; +// return; +// } + +// int comNb = comments.size(); + +// RsQThreadUtils::postToObject( [comNb,this]() +// { +// 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); +// mLoadingComment = false; + +// }, this ); +// }); +} + +void WireNotifyPostItem::loadGroup() +{ +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyGroupItem::loadGroup()"; + std::cerr << std::endl; +#endif + mLoadingGroup = true; + + RsThread::async([this]() + { + // 1 - get group data + +// std::vector groups; +// std::list> groups; + const std::list groupIds = { groupId() }; + std::vector groups; + if(!rsWire->getGroups(groupIds,groups)) // would be better to call channel Summaries for a single group + { + RsErr() << "WireNotifyPostItem::loadGroup() ERROR getting data" << std::endl; + return; + } + + if (groups.size() != 1) + { + std::cerr << "WireNotifyPostItem::loadGroup() Wrong number of Items"; + std::cerr << std::endl; + return; + } + RsWireGroup group = groups[0]; + + RsQThreadUtils::postToObject( [group,this]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete */ + + mGroupMeta = group.mMeta; + mLoadingGroup = false; + setGroup(group); + + }, this ); + }); +} + +//void WireNotifyPostItem::updateItem() +//{ +// /* fill in */ + +//#ifdef DEBUG_ITEM +// std::cerr << "WireNotifyPostItem::updateItem()"; +// std::cerr << std::endl; +//#endif + +// int msec_rate = 10000; + +// int downloadCount = 0; +// int downloadStartable = 0; +// int playCount = 0; +// int playStartable = 0; +// bool startable; +// bool loopAgain = false; + +// /* Very slow Tick to check when all files are downloaded */ +// std::list::iterator it; +// for(it = mFileItems.begin(); it != mFileItems.end(); ++it) +// { +// SubFileItem *item = *it; + +// if (item->isDownloadable(startable)) { +// ++downloadCount; +// if (startable) { +// ++downloadStartable; +// } +// } +// if (item->isPlayable(startable)) { +// ++playCount; +// if (startable) { +// ++playStartable; +// } +// } + +// if (!item->done()) +// { +// /* loop again */ +// loopAgain = true; +// } +// } + +// if (downloadCount) { +// ui->downloadButton->show(); + +// if (downloadStartable) { +// ui->downloadButton->setEnabled(true); +// } else { +// ui->downloadButton->setEnabled(false); +// } +// } else { +// ui->downloadButton->hide(); +// } +// if (playCount) { +// /* one file is playable */ +// ui->playButton->show(); + +// if (playStartable == 1) { +// ui->playButton->setEnabled(true); +// } else { +// ui->playButton->setEnabled(false); +// } +// } else { +// ui->playButton->hide(); +// } + +// if (loopAgain) { +// QTimer::singleShot( msec_rate, this, SLOT(updateItem(void))); +// } + +// // HACK TO DISPLAY COMMENT BUTTON FOR NOW. +// //downloadButton->show(); +// //downloadButton->setEnabled(true); +//} + +QString WireNotifyPostItem::groupName() +{ + return QString::fromUtf8(mGroupMeta.mGroupName.c_str()); +} + +void WireNotifyPostItem::doExpand(bool open) +{ + if (mFeedHolder) + { + mFeedHolder->lockLayout(this, true); + } + + if (open) + { + ui->expandFrame->show(); + ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/up-arrow.png"))); + ui->expandButton->setToolTip(tr("Hide")); + +// readToggled(false); + } + else + { + ui->expandFrame->hide(); + ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/down-arrow.png"))); + ui->expandButton->setToolTip(tr("Expand")); + } + + emit sizeChanged(this); + + if (mFeedHolder) + { + mFeedHolder->lockLayout(this, false); + } +} + +void WireNotifyPostItem::fill() +{ + /* fill in */ + +// if (isLoading()) { + // /* Wait for all requests */ + //return; +// } + +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyPostItem::fill()"; + std::cerr << std::endl; +#endif + + std::cout<<"*************************************************filling************************************"<subjectLabel->setText(msgText); + + ui->pulseMessage->setText(QString::fromUtf8(mPulse.mPulseText.c_str())); + ui->datetimelabel->setText(DateTime::formatLongDateTime(mPulse.mRefPublishTs)); + + if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) + { + ui->unsubscribeButton->setEnabled(true); + } + else + { + ui->unsubscribeButton->setEnabled(false); + } + ui->readButton->hide(); + ui->newLabel->hide(); + ui->copyLinkButton->hide(); + + if (IS_MSG_NEW(mPulse.mMeta.mMsgStatus)) { + mCloseOnRead = true; + } + } + else + { + + /* disable buttons: deletion facility not enabled with cache services yet */ + ui->clearButton->setEnabled(false); + ui->unsubscribeButton->setEnabled(false); + ui->clearButton->hide(); + ui->readAndClearButton->hide(); + ui->unsubscribeButton->hide(); + ui->copyLinkButton->show(); + + if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) + { + ui->readButton->setVisible(true); + + setReadStatus(IS_MSG_NEW(mPulse.mMeta.mMsgStatus), IS_MSG_UNREAD(mPulse.mMeta.mMsgStatus) || IS_MSG_NEW(mPulse.mMeta.mMsgStatus)); + } + else + { + ui->readButton->setVisible(false); + ui->newLabel->setVisible(false); + } + + mCloseOnRead = false; + } + + // differences between Feed or Top of Comment. + if (mFeedHolder) + { + if (mIsHome) { + ui->commentButton->show(); + } else if (ui->commentButton->icon().isNull()){ + //Icon is seted if a comment received. + ui->commentButton->hide(); + } + +// THIS CODE IS doesn't compile - disabling until fixed. +#if 0 + if (post.mComments) + { + QString commentText = QString::number(post.mComments); + commentText += " "; + commentText += tr("Comments"); + ui->commentButton->setText(commentText); + } + else + { + ui->commentButton->setText(tr("Comment")); + } +#endif + + } + else + { + ui->commentButton->hide(); + } + + // disable voting buttons - if they have already voted. + /*if (post.mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) + { + voteUpButton->setEnabled(false); + voteDownButton->setEnabled(false); + }*/ + +// { +// QTextDocument doc; +// doc.setHtml( QString::fromUtf8(mPulse.mMsg.c_str()) ); + +// ui->msgFrame->setVisible(doc.toPlainText().length() > 0); +// } + +// if (wasExpanded() || ui->expandFrame->isVisible()) { +// fillExpandFrame(); +// } + +// if ( (mPulse.mAttachmentCount != 0) || (mPulse.mSize != 0) ) { +// ui->filelabel->setVisible(true); +// ui->filelabel->setText(QString("(%1 %2) %3").arg(mPulse.mAttachmentCount).arg( (mPulse.mAttachmentCount > 1)?tr("Files"):tr("File")).arg(misc::friendlyUnit(mPulse.mSize))); +// } else { +// ui->filelabel->setVisible(false); +// } + +// if (mFileItems.empty() == false) { +// std::list::iterator it; +// for(it = mFileItems.begin(); it != mFileItems.end(); ++it) +// { +// delete(*it); +// } +// mFileItems.clear(); +// } + +// std::list::const_iterator it; +// for(it = mPulse.mFiles.begin(); it != mPulse.mFiles.end(); ++it) +// { +// /* add file */ +// std::string path; +// SubFileItem *fi = new SubFileItem(it->mHash, it->mName, path, it->mSize, SFI_STATE_REMOTE | SFI_TYPE_CHANNEL, RsPeerId()); +// mFileItems.push_back(fi); + +// /* check if the file is a media file */ +// if (!misc::isPreviewable(QFileInfo(QString::fromUtf8(it->mName.c_str())).suffix())) +// { +// fi->mediatype(); +// /* check if the file is not a media file and change text */ +// ui->playButton->setText(tr("Open")); +// ui->playButton->setToolTip(tr("Open File")); +// } else { +// ui->playButton->setText(tr("Play")); +// ui->playButton->setToolTip(tr("Play Media")); +// } + +// QLayout *layout = ui->expandFrame->layout(); +// layout->addWidget(fi); +// } + + mInFill = false; +} + +void WireNotifyPostItem::setReadStatus(bool isNew, bool isUnread) +{ + if (isNew) + mPulse.mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_NEW; + else + mPulse.mMeta.mMsgStatus &= ~GXS_SERV::GXS_MSG_STATUS_GUI_NEW; + + if (isUnread) + { + mPulse.mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; + whileBlocking(ui->readButton)->setChecked(true); + ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); + } + else + { + mPulse.mMeta.mMsgStatus &= ~GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; + whileBlocking(ui->readButton)->setChecked(false); + ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-read.png")); + } + + //ui->newLabel->setVisible(isNew); + + //ui->feedFrame->setProperty("new", isNew); + //ui->feedFrame->style()->unpolish(ui->feedFrame); + //ui->feedFrame->style()->polish( ui->feedFrame); +} + +void WireNotifyPostItem::setGroup(const RsWireGroup &group) +{ + ui->groupName->setText(QString::fromStdString(group.mMeta.mGroupName)); + ui->groupName->setToolTip(QString::fromStdString(group.mMeta.mGroupName) + "@" + QString::fromStdString(group.mMeta.mAuthorId.toStdString())); + + QString title; + + title = tr("Wire Feed") + ": "; + RetroShareLink link = RetroShareLink::createGxsGroupLink(RetroShareLink::TYPE_WIRE, group.mMeta.mGroupId, groupName()); + title += link.toHtml(); + ui->titleLabel->setText(title); + + if (group.mHeadshot.mData ) + { + QPixmap pixmap; + if (GxsIdDetails::loadPixmapFromData( + group.mHeadshot.mData, + group.mHeadshot.mSize, + pixmap,GxsIdDetails::ORIGINAL)) + { + ui->logoLabel->setPixmap(pixmap); + } + } + else + { + // default. + QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png"); + ui->logoLabel->setPixmap(pixmap); + } + +} + +/*********** SPECIFIC FUNCTIONS ***********************/ + +void WireNotifyPostItem::readAndClearItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyPostItem::readAndClearItem()"; + std::cerr << std::endl; +#endif + readToggled(false); + removeItem(); +} + +void WireNotifyPostItem::readToggled(bool /*checked*/) +{ + if (mInFill) { + return; + } + + mCloseOnRead = false; + + RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); + + //rsWire->setMessageReadStatus(msgPair, isUnread()); + + //setReadStatus(false, checked); // Updated by events +} + +void WireNotifyPostItem::on_linkActivated(QString link) +{ + RetroShareLink rsLink(link); + + if (rsLink.valid() ) { + QList rsLinks; + rsLinks.append(rsLink); + RetroShareLink::process(rsLinks); + removeItem(); + return; + } +} diff --git a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.h b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.h new file mode 100644 index 000000000..8633985ae --- /dev/null +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.h @@ -0,0 +1,108 @@ +/******************************************************************************* + * gui/feeds/WireNotifyPostItem.h * + * * + * Copyright (c) 2012, Robert Fernie * + * * + * 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 WIRENOTIFYPOSTITEM_H +#define WIRENOTIFYPOSTITEM_H + +#include +#include +#include +#include "gui/feeds/GxsFeedItem.h" +#include "gui/feeds/GxsGroupFeedItem.h" + +namespace Ui { +class WireNotifyPostItem; +} + +class FeedHolder; +class SubFileItem; + +class WireNotifyPostItem : public GxsFeedItem +{ + Q_OBJECT + +public: + // This one is used in NewFeed for incoming Wire posts. Only the group and msg ids are known at this point. + // It can be used for all apparences of wire posts. But in rder to merge comments from the previous versions of the post, the list of + // previous posts should be supplied. It's optional. If not supplied only the comments of the new version will be displayed. + WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); + WireNotifyPostItem(FeedHolder *parent, uint32_t feedId, const RsGroupMetaData& group_meta, const RsGxsMessageId& messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); + //WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate); + + virtual ~WireNotifyPostItem(); + + uint64_t uniqueIdentifier() const override { return hash_64bits("WireNotifyPostItem " + messageId().toStdString()); } + + bool setPost(const RsWirePulse& pulse, bool doFill = true); + void setGroup(const RsWireGroup &group); + + bool isLoaded() const {return mLoaded;}; + bool isUnread() const ; + void setReadStatus(bool isNew, bool isUnread); + +protected: + + /* FeedItem */ + virtual void doExpand(bool open); + virtual void expandFill(bool first); + + virtual void paintEvent(QPaintEvent *) override; + + /* GxsGroupFeedItem */ + virtual QString groupName(); + virtual void loadGroup() override; + virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_WIRE; } + + /* GxsFeedItem */ +// virtual QString messageName(); + virtual void loadMessage(); + virtual void loadComment(); + virtual QString messageName() override; + +private slots: + /* default stuff */ + //void toggle() override; + void readAndClearItem(); + void readToggled(bool checked); + + void on_linkActivated(QString link); +private: + void setup(); + void fill(); + +private: + bool mInFill; + bool mCloseOnRead; + bool mLoaded; + + bool mLoadingMessage; + bool mLoadingGroup; + bool mLoadingComment; + + + RsGroupMetaData mGroupMeta; + RsWirePulse mPulse; + + /** Qt Designer generated object */ + Ui::WireNotifyPostItem *ui; +}; + +Q_DECLARE_METATYPE(RsWirePulse) + +#endif // WIRENOTIFYPOSTITEM_H diff --git a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.ui b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.ui new file mode 100644 index 000000000..95bf55f45 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.ui @@ -0,0 +1,492 @@ + + + WireNotifyPostItem + + + + 0 + 0 + 822 + 175 + + + + + 1 + + + 1 + + + 1 + + + 1 + + + 6 + + + 1 + + + + + + 0 + 0 + + + + true + + + QFrame::Box + + + QFrame::Sunken + + + + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + TextLabel + + + + + + + Qt::Vertical + + + + 20 + 20 + + + + + + + + + + + + + + + 12 + 75 + true + true + + + + TextLabel + + + + + + + + 0 + 0 + + + + + 11 + 75 + true + true + + + + Wire Subject + + + false + + + true + + + + + + + + 75 + true + + + + DateTime + + + + + + + New + + + + + + + + + + 11 + + + + TextLabel + + + + + + + + 11 + 75 + false + true + + + + TextLabel + + + true + + + + + + + 8 + + + + + + 24 + 16777215 + + + + Qt::NoFocus + + + Toggle Message Read Status + + + true + + + false + + + false + + + + + + + + 75 + true + + + + 0 + + + + + + + I like this + + + + + + + + + + I dislike this + + + + + + + + + + Qt::NoFocus + + + Download + + + false + + + + + + + Qt::NoFocus + + + Play + + + + + + + Comments + + + + + + + fileLabel + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + Unsubscribe From Wire + + + Unsubscribe + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + Copy RetroShare Link + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + Expand + + + + :/icons/png/down-arrow.png:/icons/png/down-arrow.png + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + Set as read and remove item + + + + :/icons/png/correct.png:/icons/png/correct.png + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + Remove Item + + + + :/icons/png/exit2.png:/icons/png/exit2.png + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::Box + + + QFrame::Sunken + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + 0 + + + + true + + + 6 + + + -1 + + + true + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 0 + + + + + + + + + + + + + + diff --git a/retroshare-gui/src/gui/feeds/WirePostItem.cpp b/retroshare-gui/src/gui/feeds/WirePostItem.cpp new file mode 100644 index 000000000..6e4ba6dc1 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/WirePostItem.cpp @@ -0,0 +1,695 @@ +/******************************************************************************* + * gui/feeds/WirePostItem.cpp * + * * + * Copyright (c) 2012, Robert Fernie * + * * + * 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 "WirePostItem.h" +#include "ui_WirePostItem.h" + +#include "FeedHolder.h" +#include "util/qtthreadsutils.h" +#include "gui/RetroShareLink.h" +#include "gui/common/FilesDefs.h" +#include "gui/gxs/GxsIdDetails.h" +#include "util/stringutil.h" +#include "util/DateTime.h" +#include "util/misc.h" + +#include +#include + +/**** + * #define DEBUG_ITEM 1 + ****/ + +WirePostItem::WirePostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set &older_versions) : + GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsWire, autoUpdate) // this one should be in GxsFeedItem +{ + QVector v; + //bool self = false; + + for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) + v.push_back(*it) ; + + if(older_versions.find(messageId) == older_versions.end()) + v.push_back(messageId); + + mLoadingStatus = LOADING_STATUS_NO_DATA; + mLoadingMessage = false; + mLoadingGroup = false; + mLoadingComment = false; + + setMessageVersions(v) ; + setup(); +} + +void WirePostItem::paintEvent(QPaintEvent *e) +{ + /* This method employs a trick to trigger a deferred loading. The post and group is requested only + * when actually displayed on the screen. */ + + if(mLoadingStatus != LOADING_STATUS_FILLED && !mGroupMeta.mGroupId.isNull() && !mPulse.mMeta.mMsgId.isNull() ) + mLoadingStatus = LOADING_STATUS_HAS_DATA; + + if(mGroupMeta.mGroupId.isNull() && !mLoadingGroup) + requestGroup(); + + if(mPulse.mMeta.mMsgId.isNull() && !mLoadingMessage) + requestMessage(); + + switch(mLoadingStatus) + { + case LOADING_STATUS_FILLED: + case LOADING_STATUS_NO_DATA: + default: + break; + + case LOADING_STATUS_HAS_DATA: + fill(); + mLoadingStatus = LOADING_STATUS_FILLED; + break; + } + + GxsFeedItem::paintEvent(e) ; +} + +WirePostItem::~WirePostItem() +{ + auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(GROUP_ITEM_LOADING_TIMEOUT_ms); + + while( (mLoadingGroup || mLoadingMessage) + && std::chrono::steady_clock::now() < timeout) + { + RsDbg() << __PRETTY_FUNCTION__ << " is Waiting for " + << (mLoadingGroup ? "Group " : "") + << (mLoadingMessage ? "Message " : "") + << "loading." << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + delete ui; +} + +bool WirePostItem::isUnread() const +{ + return IS_MSG_UNREAD(mPulse.mMeta.mMsgStatus) ; +} + +void WirePostItem::setup() +{ + /* Invoke the Qt Designer generated object setup routine */ + + ui = new Ui::WirePostItem; + ui->setupUi(this); + + // Manually set icons to allow to use clever resource sharing that is missing in Qt for Icons loaded from Qt resource file. + // This is particularly important here because a wire may contain many posts, so duplicating the QImages here is deadly for the + // memory. + +// ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/thumb-default-video.png")); + //ui->warn_image_label->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/status_unknown.png")); + ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); +// ui->voteUpButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/vote_up.png")); +// ui->voteDownButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/vote_down.png")); +// ui->downloadButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/download.png")); +// ui->playButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/play.png")); + ui->commentButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/comment.png")); + //ui->editButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/pencil-edit-button.png")); +// ui->copyLinkButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/copy.png")); +// ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/down-arrow.png")); +// ui->readAndClearButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/correct.png")); +// ui->clearButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/exit2.png")); + + setAttribute(Qt::WA_DeleteOnClose, true); + + mCloseOnRead = false; + + /* clear ui */ + ui->titleLabel->setText(tr("Loading...")); + ui->titleLabel->setOpenExternalLinks(false); //To get linkActivated working + connect(ui->titleLabel, SIGNAL(linkActivated(QString)), this, SLOT(on_linkActivated(QString))); + ui->datetimelabel->clear(); + ui->filelabel->clear(); +// ui->newCommentLabel->hide(); +// ui->commLabel->hide(); + + /* general ones */ + connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(toggle())); + connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(removeItem())); + + /* specific */ + connect(ui->readAndClearButton, SIGNAL(clicked()), this, SLOT(readAndClearItem())); + connect(ui->unsubscribeButton, SIGNAL(clicked()), this, SLOT(unsubscribeChannel())); + + connect(ui->downloadButton, SIGNAL(clicked()), this, SLOT(download())); + // HACK FOR NOW. + ui->commentButton->hide();// hidden until properly enabled. + connect(ui->commentButton, SIGNAL(clicked()), this, SLOT(loadComments())); + + connect(ui->playButton, SIGNAL(clicked()), this, SLOT(play(void))); + //connect(ui->editButton, SIGNAL(clicked()), this, SLOT(edit(void))); + connect(ui->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyMessageLink())); + + connect(ui->readButton, SIGNAL(toggled(bool)), this, SLOT(readToggled(bool))); + + // hide voting buttons, backend is not implemented yet + ui->voteUpButton->hide(); + ui->voteDownButton->hide(); + + ui->scoreLabel->hide(); + + // hide unsubscribe button not necessary + ui->unsubscribeButton->hide(); + + ui->downloadButton->hide(); + ui->playButton->hide(); + //ui->warn_image_label->hide(); + //ui->warning_label->hide(); + + ui->titleLabel->setMinimumWidth(100); + ui->subjectLabel->setMinimumWidth(100); + //ui->warning_label->setMinimumWidth(100); + ui->titleLabel->setEnabled(false); + + ui->feedFrame->setProperty("new", false); + ui->feedFrame->style()->unpolish(ui->feedFrame); + ui->feedFrame->style()->polish( ui->feedFrame); + + ui->expandFrame->hide(); +} + +QString WirePostItem::groupName() +{ + return QString::fromUtf8(mGroupMeta.mGroupName.c_str()); +} + +void WirePostItem::loadGroup() +{ +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyGroupItem::loadGroup()"; + std::cerr << std::endl; +#endif + + mLoadingGroup = true; + + RsThread::async([this]() + { + // 1 - get group data + + std::vector groups; + const std::list groupIds = { groupId() }; + + if(!rsWire->getGroups(groupIds,groups)) // would be better to call channel Summaries for a single group + { + RsErr() << "WirePostItem::loadGroup() ERROR getting data" << std::endl; + mLoadingGroup = false; + return; + } + + if (groups.size() != 1) + { + std::cerr << "WirePostItem::loadGroup() Wrong number of Items"; + std::cerr << std::endl; + mLoadingGroup = false; + return; + } + + RsWireGroup group(groups[0]); + + RsQThreadUtils::postToObject( [group,this]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete */ + + mGroupMeta = group.mMeta; + mLoadingGroup = false; + + update(); // this triggers a paintEvent if needed. + + }, this ); + }); +} + +void WirePostItem::loadMessage() +{ +#ifdef DEBUG_ITEM + std::cerr << "WirePostItem::loadMessage()"; + std::cerr << std::endl; +#endif + mLoadingMessage = true; + + RsThread::async([this]() + { + // 1 - get group data + + std::list groupIds; + std::list pulses; +// std::vector comments; +// std::vector votes; + //groupIds.push_back(groupId()); + + if(! rsWire->getPulsesForGroups(groupIds, pulses)) + { + RsErr() << "WirePostItem::loadMessage() ERROR getting data" << std::endl; + mLoadingMessage = false; + return; + } + + if (pulses.size() == 1) + { +#ifdef DEBUG_ITEM + std::cerr << (void*)this << ": Obtained post, with msgId = " << pulses[0].mMeta.mMsgId << std::endl; +#endif + const RsWirePulse& pulse(*pulses.front()); + + RsQThreadUtils::postToObject( [pulse,this]() + { + mPulse = pulse; + mLoadingMessage = false; + update(); // this triggers a paintEvent if needed. + }, this ); + } + +// else if(comments.size() == 1) +// { +// const RsGxsComment& cmt = comments[0]; +//#ifdef DEBUG_ITEM +// std::cerr << (void*)this << ": Obtained comment, setting messageId to threadID = " << cmt.mMeta.mThreadId << std::endl; +//#endif + +// RsQThreadUtils::postToObject( [cmt,this]() +// { +// 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(); + +// mLoadingMessage = false; +// }, this ); + +// } +// else +// { +//#ifdef DEBUG_ITEM +// std::cerr << "WirePostItem::loadMessage() Wrong number of Items. Remove It."; +// std::cerr << std::endl; +//#endif + +// RsQThreadUtils::postToObject( [this]() +// { +// removeItem(); +// mLoadingMessage = false; +// }, this ); +// } + }); +} + +void WirePostItem::loadComment() +{ +#ifdef DEBUG_ITEM + std::cerr << "WirePostItem::loadComment()"; + std::cerr << std::endl; +#endif +// mLoadingComment = true; + +// RsThread::async([this]() +// { +// // 1 - get group data + +// std::set msgIds; + +// for(auto MsgId: messageVersions()) +// msgIds.insert(MsgId); + +// std::vector posts; +// std::vector comments; + +// if(! rsGxsChannels->getChannelComments( groupId(),msgIds,comments)) +// { +// RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; +// return; +// } + +// int comNb = comments.size(); + +// RsQThreadUtils::postToObject( [comNb,this]() +// { +// 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); +// mLoadingComment = false; + +// }, this ); +// }); +} + + +void WirePostItem::fill() +{ +#ifdef DEBUG_ITEM + std::cerr << "WirePostItem::fill()"; + std::cerr << std::endl; +#endif + + std::cout<<"*************************************************filling************************************"<groupName->setText(QString::fromStdString(mGroup.mMeta.mGroupName)); + ui->groupName->setToolTip(QString::fromStdString(mGroup.mMeta.mGroupName) + "@" + QString::fromStdString(mGroup.mMeta.mAuthorId.toStdString())); + + if (mGroup.mHeadshot.mData ) + { + QPixmap pixmap; + if (GxsIdDetails::loadPixmapFromData( + mGroup.mHeadshot.mData, + mGroup.mHeadshot.mSize, + pixmap,GxsIdDetails::ORIGINAL)) + { + ui->logoLabel->setPixmap(pixmap); + } + } + else{ + // default. + QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png"); + ui->logoLabel->setPixmap(pixmap); + } + + if (!mIsHome) + { + if (mCloseOnRead && !IS_MSG_NEW(mPulse.mMeta.mMsgStatus)) { + removeItem(); + } + + title = tr("Wire Feed") + ": "; + RetroShareLink link = RetroShareLink::createGxsGroupLink(RetroShareLink::TYPE_WIRE, mGroup.mMeta.mGroupId, groupName()); + title += link.toHtml(); + ui->titleLabel->setText(title); + + msgText = tr("Pulse") + ": "; + RetroShareLink msgLink = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_WIRE, mPulse.mMeta.mGroupId, mPulse.mMeta.mMsgId, messageName()); + msgText += msgLink.toHtml(); + ui->subjectLabel->setText(msgText); + + ui->pulseMessage->setText(QString::fromUtf8(mPulse.mPulseText.c_str())); + ui->datetimelabel->setText(DateTime::formatLongDateTime(mPulse.mRefPublishTs)); + + if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) + { + ui->unsubscribeButton->setEnabled(true); + } + else + { + ui->unsubscribeButton->setEnabled(false); + } + ui->readButton->hide(); + ui->newLabel->hide(); + ui->copyLinkButton->hide(); + + if (IS_MSG_NEW(mPulse.mMeta.mMsgStatus)) { + mCloseOnRead = true; + } + } + else + { + + /* disable buttons: deletion facility not enabled with cache services yet */ + ui->clearButton->setEnabled(false); + ui->unsubscribeButton->setEnabled(false); + ui->clearButton->hide(); + ui->readAndClearButton->hide(); + ui->unsubscribeButton->hide(); + ui->copyLinkButton->show(); + + if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) + { + ui->readButton->setVisible(true); + + setReadStatus(IS_MSG_NEW(mPulse.mMeta.mMsgStatus), IS_MSG_UNREAD(mPulse.mMeta.mMsgStatus) || IS_MSG_NEW(mPulse.mMeta.mMsgStatus)); + } + else + { + ui->readButton->setVisible(false); + ui->newLabel->setVisible(false); + } + + mCloseOnRead = false; + } + + // differences between Feed or Top of Comment. + if (mFeedHolder) + { + if (mIsHome) { + ui->commentButton->show(); + } else if (ui->commentButton->icon().isNull()){ + //Icon is seted if a comment received. + ui->commentButton->hide(); + } + +// THIS CODE IS doesn't compile - disabling until fixed. +#if 0 + if (post.mComments) + { + QString commentText = QString::number(post.mComments); + commentText += " "; + commentText += tr("Comments"); + ui->commentButton->setText(commentText); + } + else + { + ui->commentButton->setText(tr("Comment")); + } +#endif + + } + else + { + ui->commentButton->hide(); + } + + // disable voting buttons - if they have already voted. + /*if (post.mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) + { + voteUpButton->setEnabled(false); + voteDownButton->setEnabled(false); + }*/ + +// { +// QTextDocument doc; +// doc.setHtml( QString::fromUtf8(mPulse.mMsg.c_str()) ); + +// ui->msgFrame->setVisible(doc.toPlainText().length() > 0); +// } + +// if (wasExpanded() || ui->expandFrame->isVisible()) { +// fillExpandFrame(); +// } + +// if ( (mPulse.mAttachmentCount != 0) || (mPulse.mSize != 0) ) { +// ui->filelabel->setVisible(true); +// ui->filelabel->setText(QString("(%1 %2) %3").arg(mPulse.mAttachmentCount).arg( (mPulse.mAttachmentCount > 1)?tr("Files"):tr("File")).arg(misc::friendlyUnit(mPulse.mSize))); +// } else { +// ui->filelabel->setVisible(false); +// } + +// if (mFileItems.empty() == false) { +// std::list::iterator it; +// for(it = mFileItems.begin(); it != mFileItems.end(); ++it) +// { +// delete(*it); +// } +// mFileItems.clear(); +// } + +// std::list::const_iterator it; +// for(it = mPulse.mFiles.begin(); it != mPulse.mFiles.end(); ++it) +// { +// /* add file */ +// std::string path; +// SubFileItem *fi = new SubFileItem(it->mHash, it->mName, path, it->mSize, SFI_STATE_REMOTE | SFI_TYPE_CHANNEL, RsPeerId()); +// mFileItems.push_back(fi); + +// /* check if the file is a media file */ +// if (!misc::isPreviewable(QFileInfo(QString::fromUtf8(it->mName.c_str())).suffix())) +// { +// fi->mediatype(); +// /* check if the file is not a media file and change text */ +// ui->playButton->setText(tr("Open")); +// ui->playButton->setToolTip(tr("Open File")); +// } else { +// ui->playButton->setText(tr("Play")); +// ui->playButton->setToolTip(tr("Play Media")); +// } + +// QLayout *layout = ui->expandFrame->layout(); +// layout->addWidget(fi); +// } + +} + +QString WirePostItem::messageName() +{ + return QString::fromUtf8(mPulse.mMeta.mMsgName.c_str()); +} + + +void WirePostItem::doExpand(bool open) +{ + if (mFeedHolder) + { + mFeedHolder->lockLayout(this, true); + } + + if (open) + { + ui->expandFrame->show(); + ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/up-arrow.png"))); + ui->expandButton->setToolTip(tr("Hide")); + +// readToggled(false); + } + else + { + ui->expandFrame->hide(); + ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/down-arrow.png"))); + ui->expandButton->setToolTip(tr("Expand")); + } + + emit sizeChanged(this); + + if (mFeedHolder) + { + mFeedHolder->lockLayout(this, false); + } +} + + +void WirePostItem::setReadStatus(bool isNew, bool isUnread) +{ + if (isNew) + mPulse.mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_NEW; + else + mPulse.mMeta.mMsgStatus &= ~GXS_SERV::GXS_MSG_STATUS_GUI_NEW; + + if (isUnread) + { + mPulse.mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; + whileBlocking(ui->readButton)->setChecked(true); + ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); + } + else + { + mPulse.mMeta.mMsgStatus &= ~GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; + whileBlocking(ui->readButton)->setChecked(false); + ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-read.png")); + } + + //ui->newLabel->setVisible(isNew); + + //ui->feedFrame->setProperty("new", isNew); + //ui->feedFrame->style()->unpolish(ui->feedFrame); + //ui->feedFrame->style()->polish( ui->feedFrame); +} + +/*void WirePostItem::setGroup(const RsWireGroup &group) +{ + ui->groupName->setText(QString::fromStdString(group.mMeta.mGroupName)); + ui->groupName->setToolTip(QString::fromStdString(group.mMeta.mGroupName) + "@" + QString::fromStdString(group.mMeta.mAuthorId.toStdString())); + + QString title; + + title = tr("Wire Feed") + ": "; + RetroShareLink link = RetroShareLink::createGxsGroupLink(RetroShareLink::TYPE_WIRE, group.mMeta.mGroupId, groupName()); + title += link.toHtml(); + ui->titleLabel->setText(title); + + if (group.mHeadshot.mData ) + { + QPixmap pixmap; + if (GxsIdDetails::loadPixmapFromData( + group.mHeadshot.mData, + group.mHeadshot.mSize, + pixmap,GxsIdDetails::ORIGINAL)) + { + ui->logoLabel->setPixmap(pixmap); + } + } + else + { + // default. + QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png"); + ui->logoLabel->setPixmap(pixmap); + } + +}*/ + +void WirePostItem::expandFill(bool first) +{ + GxsFeedItem::expandFill(first); + + if (first) { +// fillExpandFrame(); + } +} + +/*********** SPECIFIC FUNCTIONS ***********************/ + +void WirePostItem::readAndClearItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "WirePostItem::readAndClearItem()"; + std::cerr << std::endl; +#endif + readToggled(false); + removeItem(); +} + +void WirePostItem::readToggled(bool /*checked*/) +{ + mCloseOnRead = false; + + RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); + + //rsWire->setMessageReadStatus(msgPair, isUnread()); + + //setReadStatus(false, checked); // Updated by events +} + +void WirePostItem::on_linkActivated(QString link) +{ + RetroShareLink rsLink(link); + + if (rsLink.valid() ) { + QList rsLinks; + rsLinks.append(rsLink); + RetroShareLink::process(rsLinks); + removeItem(); + return; + } +} diff --git a/retroshare-gui/src/gui/feeds/WirePostItem.h b/retroshare-gui/src/gui/feeds/WirePostItem.h new file mode 100644 index 000000000..f0c295935 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/WirePostItem.h @@ -0,0 +1,108 @@ +/******************************************************************************* + * gui/feeds/WirePostItem.h * + * * + * Copyright (c) 2012, Robert Fernie * + * * + * 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 WirePostItem_H +#define WirePostItem_H + +#include +#include + +#include +#include "gui/gxs/GxsFeedItem.h" +#include "gui/gxs/GxsGroupFeedItem.h" + +namespace Ui { +class WirePostItem; +} + +class FeedHolder; +class SubFileItem; + +class WirePostItem : public GxsFeedItem +{ + Q_OBJECT + +public: + // This one is used in NewFeed for incoming Wire posts. Only the group and msg ids are known at this point. + // It can be used for all apparences of wire posts. But in rder to merge comments from the previous versions of the post, the list of + // previous posts should be supplied. It's optional. If not supplied only the comments of the new version will be displayed. + WirePostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); + +#ifdef UNUSED + WirePostItem(FeedHolder *parent, uint32_t feedId, const RsGroupMetaData& group_meta, const RsGxsMessageId& messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); + //WirePostItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate); +#endif + + virtual ~WirePostItem(); + + uint64_t uniqueIdentifier() const override { return hash_64bits("WirePostItem " + messageId().toStdString()); } + + bool isUnread() const ; + void setReadStatus(bool isNew, bool isUnread); + +protected: + + /* FeedItem */ + virtual void doExpand(bool open); + virtual void expandFill(bool first); + + virtual void paintEvent(QPaintEvent *) override; + + /* GxsGroupFeedItem */ + virtual QString groupName(); + virtual void loadGroup() override; + virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_WIRE; } + + /* GxsFeedItem */ +// virtual QString messageName(); + virtual void loadMessage(); + virtual void loadComment(); + virtual QString messageName() override; + +private slots: + /* default stuff */ + //void toggle() override; + void readAndClearItem(); + void readToggled(bool checked); + + void on_linkActivated(QString link); +private: + void setup(); + void fill(); + +private: + bool mCloseOnRead; + + LoadingStatus mLoadingStatus; + + bool mLoadingMessage; + bool mLoadingGroup; + bool mLoadingComment; + + RsGroupMetaData mGroupMeta; + RsWirePulse mPulse; + RsWireGroup mGroup; + + /** Qt Designer generated object */ + Ui::WirePostItem *ui; +}; + +Q_DECLARE_METATYPE(RsWirePulse) + +#endif // WirePostItem_H diff --git a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp index 2a57147b6..4f8f9d509 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp @@ -33,7 +33,6 @@ #include "gui/common/RSTreeWidget.h" #include "gui/common/UIStateHelper.h" #include "gui/common/UserNotify.h" -#include "gui/RsGUIEventManager.h" #include "util/qtthreadsutils.h" #include "retroshare/rsgxsifacetypes.h" #include "GxsCommentDialog.h" @@ -72,7 +71,7 @@ static const uint32_t DELAY_BETWEEN_GROUP_STATISTICS_UPDATE = 120; // do not upd /** Constructor */ GxsGroupFrameDialog::GxsGroupFrameDialog(RsGxsIfaceHelper *ifaceImpl,const QString& settings_name, QWidget *parent,bool allow_dist_sync) -: MainPage(parent),mSettingsName(settings_name) +: GxsStatisticsProvider(ifaceImpl,settings_name,parent) { /* Invoke the Qt Designer generated object setup routine */ ui = new Ui::GxsGroupFrameDialog(); @@ -173,7 +172,7 @@ void GxsGroupFrameDialog::initUi() processSettings(true); if (groupFrameSettingsType() != GroupFrameSettings::Nothing) { - connect(RsGUIEventManager::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); + //connect(NotifyQt::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); settingsChanged(); } @@ -470,9 +469,7 @@ void GxsGroupFrameDialog::groupTreeCustomPopupMenu(QPoint point) uint32_t current_store_time = checkDelay(mInterface->getStoragePeriod(mGroupId))/86400 ; uint32_t current_sync_time = checkDelay(mInterface->getSyncPeriod(mGroupId))/86400 ; -#ifdef DEBUG_GROUPFRAMEDIALOG std::cerr << "Got sync=" << current_sync_time << ". store=" << current_store_time << std::endl; -#endif QAction *actnn = NULL; QMenu *ctxMenu2 = contextMnu.addMenu(tr("Synchronise posts of last...")) ; @@ -1159,45 +1156,6 @@ void GxsGroupFrameDialog::updateGroupSummary() /*********************** **** **** **** ***********************/ /*********************** **** **** **** ***********************/ -void GxsGroupFrameDialog::updateGroupStatistics(const RsGxsGroupId &groupId) -{ - mGroupStatisticsToUpdate.insert(groupId); - mShouldUpdateGroupStatistics = true; -} - -void GxsGroupFrameDialog::updateGroupStatisticsReal(const RsGxsGroupId &groupId) -{ - RsThread::async([this,groupId]() - { - GxsGroupStatistic stats; - - if(! getGroupStatistics(groupId, stats)) - { - std::cerr << __PRETTY_FUNCTION__ << " failed to collect group statistics for group " << groupId << std::endl; - return; - } - - RsQThreadUtils::postToObject( [this,stats, groupId]() - { - /* Here it goes any code you want to be executed on the Qt Gui - * thread, for example to update the data model with new information - * after a blocking call to RetroShare API complete, note that - * Qt::QueuedConnection is important! - */ - - QTreeWidgetItem *item = ui->groupTreeWidget->getItemFromId(QString::fromStdString(stats.mGrpId.toStdString())); - - if (item) - ui->groupTreeWidget->setUnreadCount(item, mCountChildMsgs ? (stats.mNumThreadMsgsUnread + stats.mNumChildMsgsUnread) : stats.mNumThreadMsgsUnread); - - mCachedGroupStats[groupId] = stats; - - getUserNotify()->updateIcon(); - - }, this ); - }); -} - void GxsGroupFrameDialog::getServiceStatistics(GxsServiceStatistic& stats) const { if(!mCachedGroupStats.empty()) @@ -1282,3 +1240,41 @@ void GxsGroupFrameDialog::distantRequestGroupData() checkRequestGroup(group_id) ; } +void GxsGroupFrameDialog::updateGroupStatistics(const RsGxsGroupId &groupId) +{ + mGroupStatisticsToUpdate.insert(groupId); + mShouldUpdateGroupStatistics = true; +} + +void GxsGroupFrameDialog::updateGroupStatisticsReal(const RsGxsGroupId &groupId) +{ + RsThread::async([this,groupId]() + { + GxsGroupStatistic stats; + + if(! getGroupStatistics(groupId, stats)) + { + std::cerr << __PRETTY_FUNCTION__ << " failed to collect group statistics for group " << groupId << std::endl; + return; + } + + RsQThreadUtils::postToObject( [this,stats, groupId]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete, note that + * Qt::QueuedConnection is important! + */ + + QTreeWidgetItem *item = ui->groupTreeWidget->getItemFromId(QString::fromStdString(stats.mGrpId.toStdString())); + + if (item) + ui->groupTreeWidget->setUnreadCount(item, mCountChildMsgs ? (stats.mNumThreadMsgsUnread + stats.mNumChildMsgsUnread) : stats.mNumThreadMsgsUnread); + + mCachedGroupStats[groupId] = stats; + + getUserNotify()->updateIcon(); + + }, this ); + }); +} diff --git a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.h b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.h index 81bba553d..055be83da 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.h +++ b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.h @@ -27,6 +27,7 @@ #include "gui/RetroShareLink.h" #include "gui/settings/rsharesettings.h" #include "util/RsUserdata.h" +#include "GxsStatisticsProvider.h" #include @@ -44,7 +45,7 @@ class UIStateHelper; struct RsGxsCommentService; class GxsCommentDialog; -class GxsGroupFrameDialog : public MainPage +class GxsGroupFrameDialog : public GxsStatisticsProvider { Q_OBJECT @@ -74,7 +75,7 @@ public: GxsGroupFrameDialog(RsGxsIfaceHelper *ifaceImpl, const QString& settings_name,QWidget *parent = 0,bool allow_dist_sync=false); virtual ~GxsGroupFrameDialog(); - bool navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msgId); + virtual bool navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msgId) override; virtual QString getHelpString() const =0; @@ -99,17 +100,13 @@ protected: virtual void checkRequestGroup(const RsGxsGroupId& /* grpId */) {} // overload this one in order to retrieve full group data when the group is browsed void updateMessageSummaryList(RsGxsGroupId groupId); - void updateGroupStatistics(const RsGxsGroupId &groupId); virtual const std::set getSearchRequests() const { return std::set(); } // overload this for subclasses that provide distant search - // These two need to be overloaded by subsclasses, possibly calling the blocking API, since they are used asynchroneously. + // This needs to be overloaded by subsclasses, possibly calling the blocking API, since it is used asynchroneously. + virtual bool getGroupData(std::list& groupInfo) =0; - virtual bool getGroupData(std::list& groupInfo) =0; - virtual bool getGroupStatistics(const RsGxsGroupId& groupId,GxsGroupStatistic& stat) =0; - - void updateGroupStatisticsReal(const RsGxsGroupId &groupId); - void updateMessageSummaryListReal(RsGxsGroupId groupId); + void updateMessageSummaryListReal(RsGxsGroupId groupId); private slots: void todo(); @@ -154,7 +151,6 @@ private slots: private: virtual QString text(TextType type) = 0; virtual QString icon(IconType type) = 0; - virtual QString settingsGroupName() = 0; virtual TurtleRequestId distantSearch(const QString& search_string) ; virtual GxsGroupDialog *createNewGroupDialog() = 0; @@ -186,16 +182,17 @@ private: // subscribe/unsubscribe ack. - GxsMessageFrameWidget *messageWidget(const RsGxsGroupId &groupId); + virtual GxsMessageFrameWidget *messageWidget(const RsGxsGroupId &groupId) override; GxsMessageFrameWidget *createMessageWidget(const RsGxsGroupId &groupId); GxsCommentDialog *commentWidget(const RsGxsMessageId &msgId); protected: + void updateSearchResults(const TurtleRequestId &sid); void updateSearchResults(); // update all searches - - bool mCountChildMsgs; // Count unread child messages? + virtual void updateGroupStatistics(const RsGxsGroupId &groupId) override; + virtual void updateGroupStatisticsReal(const RsGxsGroupId &groupId) override; private: GxsMessageFrameWidget *currentWidget() const; @@ -203,36 +200,26 @@ private: bool mInitialized; bool mInFill; - bool mDistSyncAllowed; - QString mSettingsName; + RsGxsGroupId mGroupId; - RsGxsIfaceHelper *mInterface; QTreeWidgetItem *mYourGroups; QTreeWidgetItem *mSubscribedGroups; QTreeWidgetItem *mPopularGroups; QTreeWidgetItem *mOtherGroups; - RsGxsGroupId mNavigatePendingGroupId; - RsGxsMessageId mNavigatePendingMsgId; - // Message summary list update bool mShouldUpdateMessageSummaryList ; // whether we should update the counting for groups. This takes some CPU so we only do it when needed. std::set mGroupIdsSummaryToUpdate; // GroupStatistics update - bool mShouldUpdateGroupStatistics; rstime_t mLastGroupStatisticsUpdateTs; - std::set mGroupStatisticsToUpdate; - - UIStateHelper *mStateHelper; /** Qt Designer generated object */ Ui::GxsGroupFrameDialog *ui; std::map mCachedGroupMetas; - std::map mCachedGroupStats; std::map mSearchGroupsItems ; std::map > mKnownGroups; diff --git a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.ui b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.ui index 8cb249020..d73871619 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.ui +++ b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.ui @@ -62,7 +62,7 @@
    - :/images/konversation.png + :/images/konversation.png true @@ -74,7 +74,6 @@ 12 - 75 true diff --git a/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.cpp b/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.cpp new file mode 100644 index 000000000..54766a251 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.cpp @@ -0,0 +1,60 @@ +/******************************************************************************* + * retroshare-gui/src/gui/gxs/GxsStatisticsProvider.cpp * + * * + * Copyright 2012-2013 by Robert Fernie * + * * + * 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 "GxsStatisticsProvider.h" + +#include "gui/common/UserNotify.h" +#include "util/qtthreadsutils.h" +#include "retroshare/rsgxsifacetypes.h" + +#define TOKEN_TYPE_GROUP_SUMMARY 1 +//#define TOKEN_TYPE_SUBSCRIBE_CHANGE 2 +//#define TOKEN_TYPE_CURRENTGROUP 3 +#define TOKEN_TYPE_STATISTICS 4 + +#define MAX_COMMENT_TITLE 32 + +static const uint32_t DELAY_BETWEEN_GROUP_STATISTICS_UPDATE = 120; // do not update group statistics more often than once every 2 mins + +/* + * Transformation Notes: + * there are still a couple of things that the new groups differ from Old version. + * these will need to be addressed in the future. + * -> Child TS (for sorting) is not handled by GXS, this will probably have to be done in the GUI. + * -> Need to handle IDs properly. + * -> Much more to do. + */ + +/** Constructor */ +GxsStatisticsProvider::GxsStatisticsProvider(RsGxsIfaceHelper *ifaceImpl,const QString& settings_name, QWidget *parent,bool allow_dist_sync) +: MainPage(parent),mSettingsName(settings_name) +{ + mDistSyncAllowed = allow_dist_sync; + mInterface = ifaceImpl; + mShouldUpdateGroupStatistics = false; +} + +GxsStatisticsProvider::~GxsStatisticsProvider() +{ +} diff --git a/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.h b/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.h new file mode 100644 index 000000000..ade29b1e8 --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.h @@ -0,0 +1,78 @@ +/******************************************************************************* + * retroshare-gui/src/gui/gxs/GxsStatisticsProvider.h * + * * + * Copyright 2012-2013 by Robert Fernie * + * * + * 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 GXSSTATISTICSPROVIDER_H +#define GXSSTATISTICSPROVIDER_H + +#include + +#include "gui/gxs/RsGxsUpdateBroadcastPage.h" +#include "gui/RetroShareLink.h" +#include "gui/settings/rsharesettings.h" +#include "util/RsUserdata.h" + +#include + +#include "GxsIdTreeWidgetItem.h" +#include "GxsGroupDialog.h" + +class GroupTreeWidget; +class GroupItemInfo; +class GxsMessageFrameWidget; +class UIStateHelper; +struct RsGxsCommentService; +class GxsCommentDialog; + +class GxsStatisticsProvider : public MainPage +{ + Q_OBJECT + +public: + GxsStatisticsProvider(RsGxsIfaceHelper *ifaceImpl, const QString& settings_name,QWidget *parent = 0,bool allow_dist_sync=false); + virtual ~GxsStatisticsProvider(); + + virtual void getServiceStatistics(GxsServiceStatistic& stats) const = 0; + virtual bool navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msgId) = 0; + +protected: + virtual void updateGroupStatistics(const RsGxsGroupId &groupId) = 0; + virtual void updateGroupStatisticsReal(const RsGxsGroupId &groupId) = 0; + + // This needs to be overloaded by subsclasses, possibly calling the blocking API, since it is used asynchroneously. + virtual bool getGroupStatistics(const RsGxsGroupId& groupId,GxsGroupStatistic& stat) = 0; + + virtual GxsMessageFrameWidget *messageWidget(const RsGxsGroupId &groupId) = 0; + + QString mSettingsName; + RsGxsIfaceHelper *mInterface; + bool mDistSyncAllowed; + std::map mCachedGroupStats; + bool mShouldUpdateGroupStatistics; + std::set mGroupStatisticsToUpdate; + bool mCountChildMsgs; // Count unread child messages? + + RsGxsGroupId mNavigatePendingGroupId; + RsGxsMessageId mNavigatePendingMsgId; + UIStateHelper *mStateHelper; + +private: + virtual QString settingsGroupName() = 0; +}; +#endif // GXSSTATISTICSPROVIDER_H diff --git a/retroshare-gui/src/gui/gxs/GxsUserNotify.cpp b/retroshare-gui/src/gui/gxs/GxsUserNotify.cpp index 1784a6f8c..a8dc5a3b5 100644 --- a/retroshare-gui/src/gui/gxs/GxsUserNotify.cpp +++ b/retroshare-gui/src/gui/gxs/GxsUserNotify.cpp @@ -26,7 +26,7 @@ #define TOKEN_TYPE_STATISTICS 1 -GxsUserNotify::GxsUserNotify(RsGxsIfaceHelper */*ifaceImpl*/, const GxsGroupFrameDialog *g,QObject *parent) : UserNotify(parent), mGroupFrameDialog(g) +GxsUserNotify::GxsUserNotify(RsGxsIfaceHelper */*ifaceImpl*/, const GxsStatisticsProvider *g,QObject *parent) : UserNotify(parent), mGxsStatisticsProvider(g) { mNewThreadMessageCount = 0; mNewChildMessageCount = 0; @@ -37,12 +37,13 @@ GxsUserNotify::~GxsUserNotify() {} void GxsUserNotify::startUpdate() { + std::cout<<"inside the gxs user notify startUpdate function"<getServiceStatistics(stats); + mGxsStatisticsProvider->getServiceStatistics(stats); /* Here it goes any code you want to be executed on the Qt Gui * thread, for example to update the data model with new information diff --git a/retroshare-gui/src/gui/gxs/GxsUserNotify.h b/retroshare-gui/src/gui/gxs/GxsUserNotify.h index 66890a1c3..a42ec69c4 100644 --- a/retroshare-gui/src/gui/gxs/GxsUserNotify.h +++ b/retroshare-gui/src/gui/gxs/GxsUserNotify.h @@ -23,6 +23,7 @@ #include #include "gui/common/UserNotify.h" +#include "gui/gxs/GxsStatisticsProvider.h" #include "gui/gxs/GxsGroupFrameDialog.h" class RsGxsIfaceHelper; @@ -33,7 +34,7 @@ class GxsUserNotify : public UserNotify Q_OBJECT public: - GxsUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsGroupFrameDialog *g, QObject *parent = 0); + GxsUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsStatisticsProvider *g, QObject *parent = 0); virtual ~GxsUserNotify(); protected: @@ -46,7 +47,8 @@ protected: bool mCountChildMsgs; // Count new child messages? private: - const GxsGroupFrameDialog *mGroupFrameDialog; + + const GxsStatisticsProvider *mGxsStatisticsProvider; unsigned int mNewThreadMessageCount; unsigned int mNewChildMessageCount; diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumUserNotify.cpp b/retroshare-gui/src/gui/gxsforums/GxsForumUserNotify.cpp index b2e5bcc8e..ef890f350 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumUserNotify.cpp +++ b/retroshare-gui/src/gui/gxsforums/GxsForumUserNotify.cpp @@ -23,7 +23,7 @@ #include "GxsForumUserNotify.h" #include "gui/MainWindow.h" -GxsForumUserNotify::GxsForumUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsGroupFrameDialog *g, QObject *parent) : +GxsForumUserNotify::GxsForumUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsStatisticsProvider *g, QObject *parent) : GxsUserNotify(ifaceImpl, g, parent) { mCountChildMsgs = true; diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumUserNotify.h b/retroshare-gui/src/gui/gxsforums/GxsForumUserNotify.h index 4d681767f..69cca1960 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumUserNotify.h +++ b/retroshare-gui/src/gui/gxsforums/GxsForumUserNotify.h @@ -28,7 +28,7 @@ class GxsForumUserNotify : public GxsUserNotify Q_OBJECT public: - explicit GxsForumUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsGroupFrameDialog *g, QObject *parent = 0); + explicit GxsForumUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsStatisticsProvider *g, QObject *parent = 0); virtual bool hasSetting(QString *name, QString *group) override; diff --git a/retroshare-gui/src/gui/icons.qrc b/retroshare-gui/src/gui/icons.qrc index 58819ecdc..092d134bc 100644 --- a/retroshare-gui/src/gui/icons.qrc +++ b/retroshare-gui/src/gui/icons.qrc @@ -354,7 +354,8 @@ icons/fullscreen-exit.png icons/notification.png icons/wire.png - icons/wire-circle.png + icons/png/wire-notify.png + icons/png/wire-circle.png icons/folder-account.svg icons/notification.svg icons/groups/blue.svg diff --git a/retroshare-gui/src/gui/icons/png/wire-circle.png b/retroshare-gui/src/gui/icons/png/wire-circle.png new file mode 100644 index 0000000000000000000000000000000000000000..1281591506a5ff9dbc422cb10eaff98d81610c55 GIT binary patch literal 5041 zcmV;i6He@jP)JQ&A{T#BdWv6NWG*kN}y_ zIs5%V0wH9&_ns+ue}CoPd-hr@XRou*IeV|Qws4`Ll(4v9h;B-*LK~uKWGlrWpqGM7 zflMF?NB~kBTU7z|K&^sufpXx82>WcC64B&SOEZg@Il34T<~X z5MhFXD}YfzHR2UuL3WLVYLp_m3tRdA7?<_K&D zwF1RTvo`Tv?jKR-r#+Fc4VSm0$%v9NwlUf6GA+9Hq+U@QnvRGNGb)GY+m#t2!9 zsGnH(<}C}_Lu7DHu2Q1s7fn~99v8U8Z*$y0!9N9_v}Wc0IVg@02nWy?hNmI?0JzL= zTf9Lwin1Rw=ZsqAyCuGAe_`85-LjrVxW!jH{Nrt1L@5M6t{aZf8hF+ zsON9J-9q~?-uazJV6-J{&=+mJ%L835u~g|sW%wC|Jm8v+&j13?nx(l9Ghb|%j3!$eKfS?0+%`}H%=3qEYrN1d1H?_CD1tsc)loGH|)27;f~3Sa~>k>G#j)j%*!cp zM4l5u_}$K4hE@N8f{~8Mi_;OiErW^7%sUjTpx9pnm+VZ}tooJl&i9mInklPTyt#X< zf?{)krQrmPo-HAZhpc%A2VCdMKsdIy-VG`*4~z>TpO5GMwNNqSQKODt7- zv?8K*0Hc5SS>VgjwvXcw!gQk|{B-oqqd;F2z5~S{qE#BlaTIWyH9POkNE=4%015d8 zV=T0ffRsqv#&MN$OSi{y&**)TG>YsNu(&wML|a0<^MgpHZfmcwU}GqfMiDuH-cbEB zfzgrK6~{9aR~dTB403Z!B+uU>X%oj6lqhYIIVb16&K%si&RnoDMc0x)0fxn5 zSsZT=MWLx`F6m5WQl|nk8v{5U>3m(l3PePF>ERNKe zd|X~jS*_){T}sH+B;^4ce%8^k9ghI{1vxs}79gUBi?;abRegA)>x8Dm}%EJ1Y2Rnd8g(?NM!sS?7x&=7F_{cXi|$(ZxV)A}HymNr{! zxV#f@7NVwv7H(~IG;h@bl&A+|Gw&=9jLsy~&JdbvXuLUPApKH;kt2FpRx&@jvbW!6 zv`f9M_|jYZSa+oJ50WQmH>kHut0HSC+{%K2^Ct7oa{xoLXW`I%|83dno$l1JnMo|4I*9a; ze|e*K49{R(Ru0Z#|@s^T*fa7%3~GN*U*!1X#T~yBY+aea`|rP zpW5oHUuPJWp1?=bhcZ3et%9HDGh=8_OAo?t3Xk#qP0l0(DfmkB&u1NAad8rgFFK+H zxVB&9SATQTLmID49>_1h(3cd${pW(~qZqBc;19bhdEld%^FPj_n9kDhnc?-!nKi8H z>zu5>c}1_-AEpHO&%B;&ylp7g^m8u?Ej^@haR7(^WqVI@@B0U^on1cfZdAxMO&`u) zTBmF8I)b4I<1&+-630au39Pv#n?GJZfWc9&#I?tWjKsi&IlXtVim$HTkLhsl10d?m z>h4(w5a%2qJ1s=A;ruC`F*Kc`8N>O_#C~LVbIuX^24oVdIdeWZNUd9uGtDmc(+=?b z_WnvS!YTQK9qgQzBs8weZ=W%O*KQohlmThPI&YKeg0seon{!c0$YnucKWGdI(+z8) zlM1q37^YjI3*0)m8@CSb#-SRM*Nac^=AP4$Mm1(+S5Cbf!)%PW?UK6K<1Kj2IIT>L zck&cuCV4xg_DweUW^PZuncI^(OYx7RHEcLqL&33H!pG}4P-Swcrmf{tXmF+aPHdd0 zch@LEn?RETD2LYln{ea)-&qoM;p)CAT;2EFw}yIKaiZSlM1zG=ryo?)Lz?gF4{cFV z?{1)s5_Khj!F;7bp`*zjsUEzyM@oVwWF_fjbr8fE1nMm1-UHxSMxm5w3@985q&X=$ zcz4vUh1*wuBN@CI0r7jsm1;oZdy-an>H{n(5zuvnJAT@7PFm%>mvjt)euS?#SicXe@;2bO#M^?UD1<=n@z{v#i?Z>HQy|&UFVk>O+m3uF8^K zo)^rh(*W1T={ifXq?M`_an2`vypAoM$@F!WDow#LH#PjG@E8pN47my#{}V&XSF|Wa zxh6=Nn@WmLHt?bk|6EtXv=x8ye)va(G7Xfg4gm1<$7R%AD8&I?VA5$7>(^kbh*Bk*ZBycfvZpp5^=y%&E3snVDK;MUXWHBrtwa;- zVlR}{S&I8VJm_?uTbJjl%}0IHt%)kuEJGD~rEqm=70-O)&u|w+-Y%{3bzgy~i>YRdb)5g=yD}=1@%b=~t>bUBSPkGnd zXc$ki72Ngi0S;9AGUa;?nmXIpXC1&+zBvG#&L+Bf#a@28rR;*)Q>ZyV+e4EH=;MrE3o6WXK4|)Ib_BS8 zL>;Jz_nviwwTG%1^~!F(yY3JtyLhH?_;?*(U9&$pQ{al%nUQzq>N+MDwF%x z9%T4SJNe0$vMv*2c(}%7+KN3K48TKQGY*+%-8;>{IIozGv8eFJN~!O8XH#T^G-2w% zG`>DOgDC^jNb|A0d|Oo1Tim#O51YN+C$K{Vo-$|WJ=Ws87Ay)6*A+Wj{ViZ5Xu|kD zDLi&*7T3jCo7gEzt4wZQxrgv^k1~8akFs=YIQNYCwE36kUp}+)c7cC$0+Ep2EyOo+ zd&FFr+9`@E>bUwZ#X;@m@K|DB%LU?B5;KlcU17L4-W-57gAVn z&C2_HYd^JF(o^6`;0@P|>LlqQja#$3ap&;v+|WN5Lwyr9rs6y64zXz4alcJzA0^16Mk3PzR)kG^PzoWBTB9ZXT2t$ikBa$7;EKO{sU~T%u=#H7oZjL|UCl zX}74aDD}7!S=rt(PLQApm-kBM>b@yl+b@M{`=yc?q%po34YuM}TaPh+(~&MQIVJGl zZFPR*@9m@KhyRL04}>X(#(-3V0jVMKdL)w9BazWPlNi%8$=CYAo#nlQReWphAqs<%Q5s+Fj}UT7Cqav`nMJ9bh}|ky&}WM5$j!qIvn=QA|pcZ#RVO zES7>b2Tt+(9hJOVe4;C-wA%vLnX~gg==jhGJJVPc{-siUJ36~gEBkz(6mB1u&WxcM zfvDa8$+23N?5yOa-Iaj|*NPQ^r_I@Uk4A8O1U$DhQA?^{FT&V}Eo*@;a8>UVrVUJE z+Q2l%^h|PfqogK|)mglMu$p%dR`GUeRabbAkA!uWU2{!mhW;iZKII7u!+Dml9&mJ8 zE+awX%3djazIQU0WF?W)J&~c^LKrc4MOm%Ij>ymXs@PIq8=UAIXDPEV z$1!{C{zw`{b$0cIg|{Kx2ECIE(i1e2bRkLCNYsVOdW%yH zHm6LRQw=sJ>TUK{HL#?a%v~DD_j~TM5U462*_K(wr~5(fQy(_K&f!aIzA$1nA?o zt_zGZkh`qexy#*D;!Pl4{+0o{7=J=B(Gz`LpMO}U_7&#kl(?J83hFz+}GJi9;fg;P|uu`^PXLL z)h-eO zcMM}d@5u_jf?_(*-EWiH;5hJxDD|>=;OJ`RPYQgZ zLDz7A<}3{-7?pA@qNZXqRSCI%nxi1B!Ag{@G`p+!n-^j13UoaOXvyMmU%f$15VQ$O z)Rn*}Aj2hXl?Vl5%LXOZ-z`|{RA7c*bbSYCjpvK9b=}TU$Pi6bwt_(@dMlAkL1h9d zoKB7J*4W}CU;@<&DHo;6(bQp4vd>0}HBrSTQsiVHMo{>FFuR=4W~NZx00000NkvXX Hu0mjfH4xCi literal 0 HcmV?d00001 diff --git a/retroshare-gui/src/gui/icons/png/wire-notify.png b/retroshare-gui/src/gui/icons/png/wire-notify.png new file mode 100644 index 0000000000000000000000000000000000000000..c241bf55ffa02c674770fedaca285d799068be72 GIT binary patch literal 4639 zcmV+)65#ELP) zK~#90?VWpcROPk6fBQ^GLXrvL{SbL5NI^tx@d+vjB4}H%Rk*@xtq%xjORL^%Yjs)F zyK23Pw~MtXB&b+xy-F3eh@wT&0s^9iihzJX5F|VTgiJ!-XWu_g!XqS^Gc)HgL*}>E zERvb??Y+sj=R4nHpS^`M3{`|VZF-Yp4#1S&7}^WyfzlCZU-wD}Qi066W@SJXPyrmW zUUC4@-I!8_S>c=IEwHVDhr_GeaWTTZ-c@S*AAd_v-@J`ohUy8I{R%;gzN`>6(L`y zly3Cfn5KwJ2hhCWP?TRI+(?|-7!krsOr9h+^me>WBID+dtBNo$I1ZIZKriy!9(T}x zq4F5Hp})tABgBORXnyt>R38Vv=eI2$@fjiy%aoG${5Hf_2hcwS`w?I!aHF4g_=haT zH1CyZrC<7HfgegWuUiHZdK_gskm838aYQxnzm$b$$bFQ1t=w}5(EQAisF4Sp(S8nNOA7S1v% zTaAZk+gyv)v+@(##%os^s8IGkGOf7431N;nfIgqqk!o2E^m9U9lCW&2#vCg5l8IivdYuVmN8R zS9Ae^Xaz(+0(8xq33^M^?UOjgIF1B=A8q5PCV`rlJrVS;(JD>iIEr$UObxviX~T#e zz&hBGRUjFWwoT$Hhp4H!Snes`9Z92zZUH)a%a36;fAaR`dHLeanB@J6Wh{27tUkl^DG z`iG-kv#9)YGb6ru(`1JpYYWSc2&eLV!+uW;k=2^^9Bf{hi_9;4uvb>+hy?W zM{wv%Jo+*yqQhlM>Bn|1w&eht*DV7=UjXNZy*Q8#*S`YYuZ7AZuwXEhAGD(;4iV_} zeYoUdXxl$FQRN4$FT~yzuzw8{ZvnH$88c636NE0Z^JJ1e2gnc3M7b~Qg<`*w04)30xp1xAYXH%_g4 zGA@vQ(rBcx_A$`oVFM3HZs@6SW`uPBotM=gQ~nJ$CKs3gHw>D7`up#UgFT+cI>yFX z!(il#*8M$ESaBb0diJC@^caDZ0diOIuI8GBUj>-*40bxd$MrDi7ma^5JRdT;h7}PP z^tloF!BX3B3hw% zPmk+iSiUuhO%zIZ!_wPM9{Nw9+^lmmo4toM=>Vz-s*l<-V(`O|-l6$xx?BO5+7sss z?asI6FGd1Ar&4(YmW;RN4NW1&W6g5qm{MH>Ul%tZJlP&FRV3oB2X2A zcW;6NpGDqQ^|y_^eVPO4-0Z%9y{~8A7{dNjTEnQn!ob|^ z|I=tCjMcn0r|smPJ_3l|g`FM3>|U{Nk4gZpd-2&nrvj&#_G?vZ> z5HRm(_~t1NP?5~I-hjlhqh!$0CHS>44}^~FkwA> z??Efr!VS{eLVA05WIM%%+175KlL+H<0mt{cPmBPS*~74#fwOf-Yxm4eT4h=eFkw9m zxXW5KI7#PAot5V_RUz1z=Z54QiZidS|K)@Oh&jf#hzxtv1V_l|3`3uRNn7BGKR}K{ zse#WL=8PP-*!7O(1a6?l@dLh-<^W>f0n*w!YL7jgIdH+K^(@p8e`#J^cQm#W^+sy-h9+wJqyUKb2gm%I1rBJv64y=XHH_bQC>JHaF?~fDP zrMeV$f8eHu0h*W5RdSCNT4$dUh-^U|Pe-P~o-p7}>jl=#`N&sLvICCpfXc(x`>i`d zhl{KbFQ?}dPP1!?6*A@~Vq6KlUgrQ@8ByaJmyL^s^!Ctoi1kWTzIn%e9V$bB*X!m0 z68_x(WZd@7mQLX(?&}aP1u%3526i9zsHftP8zv(*7~K@}Qhpeka}J^LIWvhz?c z3~Z_FUE!6cHawTp!=OeZKhmozac_;<(%I+1@L!K<4loeu9aZDvEe>0g1c)x!BU;q# zWgyx!s>Vk)J8Vr7s>|T$*B&aA-UiSksq8$yaQmT=2c#{>Ip2RuqhIu}EP;WqIEtfm9*GP z#%y2cfFViPx5gK>2GB@8k_aeR3?)0Av8KhMJ}s-YGIj^hTKICVGxoGpinscdNJ}aW zpe$xNTmAx7M`O3ArLu38Uz*Dd;Bd@hs!L(>3o(mnvA7%m*Bplogl6)KM8JmG$t7Vl z)K22g)G>2opyg0bk69;%$zJYZ2^P?4NGY z0s~VD9200(!RiMc6L-c_TL}doL;yF578n@n>>~b~_pQg8l7wgb!sb)Fxs4h-4Qh-{ zjtliqy*ZRer#4LqIv+ z*C!mnFx(IEE!_ieT^Aoipx12pla=!?E-;tW|8&9uDoQ>A+&|Q>EQWV(vQ7`rw3>oV zvHw$8V=w!@2Nct;Yt6|lH@czUEE-7b|ibK{)$P8P-%_|nl z_!CiJ4N}F*0#8jTSPXx=1h&4+895qgt+gXs_O0KRoP_b}DZicaSz*b0K%tlBP;nSO znhI|WgT1zjT_y;1lfL-c2-^oom!15^DGners6lwqTbt@QxDMX_0lYO5b}WpiAu~Ew zKLlU-^QUYYd9GnK(bMVz=(E{D0EL*2btZ#Uy z!HH9%wISsPt&N>6FZv(KWf$dsnHqW~+-3G0;2Bzz8T>MY{!Q;-)%FSY zv}*da>1*xeB|2s`Y@BCBHz(HP?;9a>al>uj#;`pG>%6RMF=grTHs|~ZhUd9oJaPy4WKf9N;KI>5>96^U5?IlKwBy#imokl5Kz zmDNb-YCA)JJrPgCH9zZoRMr4Z@5yHOf*xa_=V<79ReTkhs;BH**ty8s!SgRgi<1;# z)Lbl+%Oe`PqFRS(e()xg*KM_L-4VK7W32=_Uk2?j@W&x)%B@UXdzZtvAJ^^PoiR~J ziZD*5gd$Ge8udb4^MX$Uksp1fWYjGW2V1L!w*9Ps({iFU<#cMwt;t*QR%>|Qx60~p zGq!|iaf|YVObtbKMjpKb%)p>)_R9^cQAbVdj+P^2bheh2>Fw&4nC+V$F{+M2d65-( zS$Wu6uNQBtdkX1{`F4jvUZJpLlFT5g4T_ky;xvy|Xx1V`u8&1dk|@)`YLJ)d-nZ>geOet{lkg0#Z4W{b$f-gAtP0W+ADeNpd@mSM7Es z3`fROMPbP#;D2a23vxG5lqV<*-Qq^)g9jlwnx8omHC_TbyRGXCqX?DTWNL}4SvNh2 z$ENd_C!b_!i%UePjZiL_uH7Jh-(L^M`w^im+X;)7Io#$N40ANfXkdWPCT#?kAm$Qs z%KmwB62?Rz;T)hLIyh<8Tqx)U{al45LjG7uwP_setChecked(!!(newsflags & RsFeedTypeFlags::RS_FEED_TYPE_FORUM)); whileBlocking(ui.notify_Posted )->setChecked(!!(newsflags & RsFeedTypeFlags::RS_FEED_TYPE_POSTED)); #if 0 - whileBlocking(ui.notify_Blogs)->setChecked(newsflags & RS_FEED_TYPE_BLOG); + whileBlocking(ui.notify_Blogs)->setChecked(newsflags & RsFeedTypeFlags::RS_FEED_TYPE_BLOG); #endif + +#ifdef RS_USE_WIRE + whileBlocking(ui.notify_Wire)->setChecked(!!(newsflags & RsFeedTypeFlags::RS_FEED_TYPE_WIRE)); +#endif + whileBlocking(ui.notify_Chat )->setChecked(!!(newsflags & RsFeedTypeFlags::RS_FEED_TYPE_CHAT)); whileBlocking(ui.notify_Messages )->setChecked(!!(newsflags & RsFeedTypeFlags::RS_FEED_TYPE_MSG)); whileBlocking(ui.notify_Chat )->setChecked(!!(newsflags & RsFeedTypeFlags::RS_FEED_TYPE_CHAT)); diff --git a/retroshare-gui/src/gui/settings/NotifyPage.ui b/retroshare-gui/src/gui/settings/NotifyPage.ui index fba357bcf..6eda7d5a3 100755 --- a/retroshare-gui/src/gui/settings/NotifyPage.ui +++ b/retroshare-gui/src/gui/settings/NotifyPage.ui @@ -7,7 +7,7 @@ 0 0 569 - 512 + 526 @@ -86,6 +86,13 @@
    + + + + Wire + + + @@ -471,6 +478,13 @@
    + + + RSComboBox + QComboBox +
    gui/common/RSComboBox.h
    +
    +
    notify_Peers notify_Channels @@ -495,13 +509,6 @@ systray_ChatLobby pushButtonDisableAll - - - RSComboBox - QComboBox -
    gui/common/RSComboBox.h
    -
    -
    diff --git a/retroshare-gui/src/gui/settings/rsharesettings.cpp b/retroshare-gui/src/gui/settings/rsharesettings.cpp index 32d3a4764..bb69af532 100644 --- a/retroshare-gui/src/gui/settings/rsharesettings.cpp +++ b/retroshare-gui/src/gui/settings/rsharesettings.cpp @@ -143,6 +143,10 @@ void RshareSettings::initSettings() RsNotifyPopupFlags defNotify = (RsNotifyPopupFlags::RS_POPUP_CONNECT | RsNotifyPopupFlags::RS_POPUP_MSG); RsFeedTypeFlags defNewsFeed = (RsFeedTypeFlags::RS_FEED_TYPE_MSG | RsFeedTypeFlags::RS_FEED_TYPE_FILES | RsFeedTypeFlags::RS_FEED_TYPE_SECURITY | RsFeedTypeFlags::RS_FEED_TYPE_SECURITY_IP | RsFeedTypeFlags::RS_FEED_TYPE_CIRCLE | RsFeedTypeFlags::RS_FEED_TYPE_CHANNEL |RsFeedTypeFlags::RS_FEED_TYPE_FORUM | RsFeedTypeFlags::RS_FEED_TYPE_POSTED); +#ifdef RS_USE_WIRE + defNewsFeed = (defNewsFeed | RsFeedTypeFlags::RS_FEED_TYPE_WIRE); +#endif + setDefault(SETTING_NEWSFEED_FLAGS, (int)defNewsFeed); setDefault(SETTING_CHAT_FLAGS, defChat); setDefault(SETTING_NOTIFY_FLAGS, (int)defNotify); @@ -1114,6 +1118,10 @@ static QString groupFrameSettingsTypeToString(GroupFrameSettings::Type type) return "Channel"; case GroupFrameSettings::Posted: return "Posted"; +#ifdef RS_USE_WIRE + case GroupFrameSettings::Wire: + return "Wire" ; +#endif } return ""; diff --git a/retroshare-gui/src/gui/settings/rsharesettings.h b/retroshare-gui/src/gui/settings/rsharesettings.h index 3c87e6aaf..77c7e625e 100644 --- a/retroshare-gui/src/gui/settings/rsharesettings.h +++ b/retroshare-gui/src/gui/settings/rsharesettings.h @@ -44,7 +44,7 @@ class QMainWindow; class GroupFrameSettings { public: - enum Type { Nothing, Forum, Channel, Posted }; + enum Type { Nothing, Forum, Channel, Posted, Wire }; public: GroupFrameSettings() diff --git a/retroshare.pri b/retroshare.pri index 983fda4e9..a92414f26 100644 --- a/retroshare.pri +++ b/retroshare.pri @@ -33,6 +33,9 @@ CONFIG *= retroshare_gui no_retroshare_gui:CONFIG -= retroshare_gui +# Enable TheWire - RsWire - is intended to be a Twitter clone +CONFIG *= gxsthewire + # Enable GXS distant syncronization CONFIG *= gxsdistsync From b4fbdca4e8713147b5e06a232725f2dddaa24708 Mon Sep 17 00:00:00 2001 From: defnax <9952056+defnax@users.noreply.github.com> Date: Thu, 11 Dec 2025 16:53:33 +0100 Subject: [PATCH 02/13] update project file --- retroshare-gui/src/retroshare-gui.pro | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index 6fd08381d..8c1c6c63d 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -117,7 +117,7 @@ CONFIG += gxscircles ## To enable unfinished services #CONFIG += wikipoos -#CONFIG += gxsthewire +CONFIG += gxsthewire #CONFIG += gxsphotoshare DEFINES += RS_RELEASE_VERSION @@ -621,6 +621,7 @@ HEADERS += rshare.h \ gui/NetworkDialog/pgpid_item_model.h \ gui/NetworkDialog/pgpid_item_proxy.h \ gui/common/RsCollection.h \ + gui/common/NotifyWidget.h \ util/retroshareWin32.h FORMS += gui/StartDialog.ui \ @@ -714,6 +715,7 @@ FORMS += gui/StartDialog.ui \ gui/common/RsCollectionDialog.ui \ gui/common/HeaderFrame.ui \ gui/common/RSFeedWidget.ui \ + gui/common/NotifyWidget.ui \ gui/style/StyleDialog.ui \ gui/statistics/BandwidthGraphWindow.ui \ gui/statistics/BandwidthStatsWidget.ui \ @@ -889,6 +891,7 @@ SOURCES += main.cpp \ gui/common/FlowLayout.cpp \ gui/common/PictureFlow.cpp \ gui/common/ToasterNotify.cpp \ + gui/common/NotifyWidget.cpp \ gui/style/RSStyle.cpp \ gui/style/StyleDialog.cpp \ gui/settings/RSPermissionMatrixWidget.cpp \ @@ -1222,7 +1225,10 @@ gxsthewire { gui/TheWire/PulseReply.h \ gui/TheWire/PulseReplySeperator.h \ gui/TheWire/PulseMessage.h \ - gui/TheWire/CustomFrame.h \ + gui/TheWire/CustomFrame.h \ + gui/TheWire/WireUserNotify.h \ + gui/feeds/WireNotifyGroupItem.h \ + gui/feeds/WireNotifyPostItem.h \ FORMS += gui/TheWire/WireDialog.ui \ gui/TheWire/WireGroupItem.ui \ @@ -1233,7 +1239,9 @@ gxsthewire { gui/TheWire/PulseReply.ui \ gui/TheWire/PulseReplySeperator.ui \ gui/TheWire/PulseMessage.ui \ - + gui/feeds/WireNotifyGroupItem.ui \ + gui/feeds/WireNotifyPostItem.ui \ + SOURCES += gui/TheWire/WireDialog.cpp \ gui/TheWire/WireGroupItem.cpp \ gui/TheWire/WireGroupDialog.cpp \ @@ -1245,7 +1253,10 @@ gxsthewire { gui/TheWire/PulseReply.cpp \ gui/TheWire/PulseReplySeperator.cpp \ gui/TheWire/PulseMessage.cpp \ - gui/TheWire/CustomFrame.cpp \ + gui/TheWire/CustomFrame.cpp \ + gui/TheWire/WireUserNotify.cpp \ + gui/feeds/WireNotifyGroupItem.cpp \ + gui/feeds/WireNotifyPostItem.cpp \ RESOURCES += gui/TheWire/TheWire_images.qrc } @@ -1439,7 +1450,7 @@ gxsgui { # gui/gxs/GxsFeedWidget.h \ util/TokenQueue.h \ util/RsGxsUpdateBroadcast.h \ - + gui/gxs/GxsStatisticsProvider.h \ # gui/gxs/GxsMsgDialog.h \ FORMS += gui/gxs/GxsGroupDialog.ui \ @@ -1470,7 +1481,7 @@ gxsgui { # gui/gxs/GxsFeedWidget.cpp \ util/TokenQueue.cpp \ util/RsGxsUpdateBroadcast.cpp \ - + gui/gxs/GxsStatisticsProvider.cpp \ # gui/gxs/GxsMsgDialog.cpp \ From 4d1de119055d576ffc17103aeaf1eb5824bfd7cf Mon Sep 17 00:00:00 2001 From: defnax <9952056+defnax@users.noreply.github.com> Date: Sat, 13 Dec 2025 15:36:20 +0100 Subject: [PATCH 03/13] Disabled hide function --- retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp index d3b666a7e..722f43fe9 100644 --- a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp @@ -54,7 +54,7 @@ PulseAddDialog::PulseAddDialog(QWidget *parent) ui.pushButton_remove->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/mail/delete.png"))); ui.frame_picture->hide(); - ui.pushButton_picture->hide(); + //ui.pushButton_picture->hide(); // initially hiding the browse button as the attach image button is not pressed //ui.frame_PictureBrowse->hide(); From bcaca4ca2de6ef18bee03c541fb753e6a4bcb9c2 Mon Sep 17 00:00:00 2001 From: defnax <9952056+defnax@users.noreply.github.com> Date: Mon, 12 Jan 2026 21:51:33 +0100 Subject: [PATCH 04/13] Fixed Wire counts to use own Wire Page * Disabled unfinished feeds --- retroshare-gui/src/gui/NewsFeed.cpp | 16 ++++++++-------- retroshare-gui/src/gui/TheWire/WireDialog.h | 2 +- .../src/gui/TheWire/WireUserNotify.cpp | 10 +++++----- retroshare-gui/src/gui/TheWire/WireUserNotify.h | 3 +++ 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/retroshare-gui/src/gui/NewsFeed.cpp b/retroshare-gui/src/gui/NewsFeed.cpp index ebfd0d81e..16a35dc29 100644 --- a/retroshare-gui/src/gui/NewsFeed.cpp +++ b/retroshare-gui/src/gui/NewsFeed.cpp @@ -531,14 +531,14 @@ void NewsFeed::handleWireEvent(std::shared_ptr event) case RsWireEventCode::NEW_POST: addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); break; - case RsWireEventCode::NEW_REPLY: - addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); - break; - case RsWireEventCode::NEW_REPUBLISH: - addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); - break; - case RsWireEventCode::NEW_LIKE: - addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); +// case RsWireEventCode::NEW_REPLY: +// addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); +// break; +// case RsWireEventCode::NEW_REPUBLISH: +// addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); +// break; +// case RsWireEventCode::NEW_LIKE: +// addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); break; case RsWireEventCode::WIRE_UPDATED: addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true)); diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.h b/retroshare-gui/src/gui/TheWire/WireDialog.h index 9ce11ca52..a3baf3987 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.h +++ b/retroshare-gui/src/gui/TheWire/WireDialog.h @@ -166,7 +166,7 @@ private: virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req) override; - virtual QString settingsGroupName() override{ return "PostedDialog"; } + virtual QString settingsGroupName() override{ return "WireDialog"; } virtual GxsMessageFrameWidget *messageWidget(const RsGxsGroupId &groupId) override; int mGroupSet; diff --git a/retroshare-gui/src/gui/TheWire/WireUserNotify.cpp b/retroshare-gui/src/gui/TheWire/WireUserNotify.cpp index c3e0e1c03..59db49d00 100644 --- a/retroshare-gui/src/gui/TheWire/WireUserNotify.cpp +++ b/retroshare-gui/src/gui/TheWire/WireUserNotify.cpp @@ -46,17 +46,17 @@ QIcon WireUserNotify::getMainIcon(bool hasNew) return hasNew ? FilesDefs::getIconFromQtResourcePath(":/icons/png/wire-notify.png") : FilesDefs::getIconFromQtResourcePath(":/icons/png/wire-circle.png"); } -//QString PostedUserNotify::getTrayMessage(bool plural) +//QString WireUserNotify::getTrayMessage(bool plural) //{ -// return plural ? tr("You have %1 new board posts") : tr("You have %1 new board post"); +// return plural ? tr("You have %1 new wire pulse") : tr("You have %1 new wire pulse"); //} -//QString PostedUserNotify::getNotifyMessage(bool plural) +//QString WireUserNotify::getNotifyMessage(bool plural) //{ -// return plural ? tr("%1 new board post") : tr("%1 new board post"); +// return plural ? tr("%1 new wire pulse") : tr("%1 new wire pulse"); //} void WireUserNotify::iconClicked() { MainWindow::showWindow(MainWindow::Wire); -} \ No newline at end of file +} diff --git a/retroshare-gui/src/gui/TheWire/WireUserNotify.h b/retroshare-gui/src/gui/TheWire/WireUserNotify.h index d3a44fd7e..bf160bec2 100644 --- a/retroshare-gui/src/gui/TheWire/WireUserNotify.h +++ b/retroshare-gui/src/gui/TheWire/WireUserNotify.h @@ -36,6 +36,9 @@ private: virtual QIcon getIcon() override; virtual QIcon getMainIcon(bool hasNew) override; + //virtual QString getTrayMessage(bool plural) override; + //virtual QString getNotifyMessage(bool plural) override; + virtual void iconClicked() override; }; From 384e00868ed5c40ff8afce6e4a355443338eb2a8 Mon Sep 17 00:00:00 2001 From: defnax <9952056+defnax@users.noreply.github.com> Date: Mon, 12 Jan 2026 22:49:10 +0100 Subject: [PATCH 05/13] Added missed wire flag --- retroshare-gui/src/gui/settings/NotifyPage.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/retroshare-gui/src/gui/settings/NotifyPage.cpp b/retroshare-gui/src/gui/settings/NotifyPage.cpp index 35d93958d..568804e24 100755 --- a/retroshare-gui/src/gui/settings/NotifyPage.cpp +++ b/retroshare-gui/src/gui/settings/NotifyPage.cpp @@ -211,6 +211,11 @@ RsFeedTypeFlags NotifyPage::getNewsFlags() if (ui.notify_SecurityIp->isChecked()) newsFlags |= RsFeedTypeFlags::RS_FEED_TYPE_SECURITY_IP; +#ifdef RS_USE_WIRE + if (ui.notify_Wire->isChecked()) + newsFlags |= RsFeedTypeFlags::RS_FEED_TYPE_WIRE; +#endif + return newsFlags; } From 29d5ce631b0c8aa7904e1d4642b4d0e05b154043 Mon Sep 17 00:00:00 2001 From: saurabh Date: Mon, 26 Jan 2026 12:45:21 +0530 Subject: [PATCH 06/13] Wire notify improvements and bug fixes - Enable wire events for replies, republishes and likes - Fix pulse notifications to load data correctly - Add home button and search filter - Add copy link for pulses and profiles - Fix identity selector in account creation --- retroshare-gui/src/gui/NewsFeed.cpp | 16 ++-- retroshare-gui/src/gui/TheWire/PulseReply.cpp | 20 +---- .../src/gui/TheWire/PulseTopLevel.cpp | 1 + .../src/gui/TheWire/PulseTopLevel.ui | 47 ++++++++++++ .../src/gui/TheWire/PulseViewGroup.cpp | 27 +++++++ .../src/gui/TheWire/PulseViewGroup.h | 1 + .../src/gui/TheWire/PulseViewGroup.ui | 55 ++++++++++++++ .../src/gui/TheWire/PulseViewItem.cpp | 32 ++++++-- .../src/gui/TheWire/PulseViewItem.h | 1 + retroshare-gui/src/gui/TheWire/WireDialog.cpp | 33 ++++++++- retroshare-gui/src/gui/TheWire/WireDialog.h | 2 + retroshare-gui/src/gui/TheWire/WireDialog.ui | 24 ++++++ .../src/gui/TheWire/WireGroupDialog.cpp | 2 +- .../src/gui/TheWire/WireGroupItem.cpp | 9 +++ .../src/gui/TheWire/WireGroupItem.h | 1 + .../src/gui/feeds/WireNotifyPostItem.cpp | 73 ++++++------------- retroshare-gui/src/gui/gxs/GxsUserNotify.cpp | 1 - 17 files changed, 257 insertions(+), 88 deletions(-) diff --git a/retroshare-gui/src/gui/NewsFeed.cpp b/retroshare-gui/src/gui/NewsFeed.cpp index 16a35dc29..ebfd0d81e 100644 --- a/retroshare-gui/src/gui/NewsFeed.cpp +++ b/retroshare-gui/src/gui/NewsFeed.cpp @@ -531,14 +531,14 @@ void NewsFeed::handleWireEvent(std::shared_ptr event) case RsWireEventCode::NEW_POST: addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); break; -// case RsWireEventCode::NEW_REPLY: -// addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); -// break; -// case RsWireEventCode::NEW_REPUBLISH: -// addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); -// break; -// case RsWireEventCode::NEW_LIKE: -// addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); + case RsWireEventCode::NEW_REPLY: + addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); + break; + case RsWireEventCode::NEW_REPUBLISH: + addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); + break; + case RsWireEventCode::NEW_LIKE: + addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); break; case RsWireEventCode::WIRE_UPDATED: addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true)); diff --git a/retroshare-gui/src/gui/TheWire/PulseReply.cpp b/retroshare-gui/src/gui/TheWire/PulseReply.cpp index ca65570c1..0ad0c2419 100644 --- a/retroshare-gui/src/gui/TheWire/PulseReply.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseReply.cpp @@ -152,30 +152,12 @@ void PulseReply::setReferenceString(QString ref) void PulseReply::mousePressEvent(QMouseEvent *event) { - // Check if the event is a left mouse button press -// if (event->button() == Qt::LeftButton && (IS_MSG_UNREAD(mPulse->mMeta.mMsgStatus) || IS_MSG_NEW(mPulse->mMeta.mMsgStatus))) - if (event->button() == Qt::LeftButton && (IS_MSG_UNPROCESSED(mPulse->mMeta.mMsgStatus))) - + if (event->button() == Qt::LeftButton && IS_MSG_UNPROCESSED(mPulse->mMeta.mMsgStatus)) { uint32_t token; - // Perform some action when the left mouse button is pressed RsGxsGrpMsgIdPair msgPair = std::make_pair(mPulse->mMeta.mGroupId, mPulse->mMeta.mMsgId); - rsWire->setMessageReadStatus(token, msgPair, true); - std::cout << "Left mouse button pressed on PulseReply!" <button() == Qt::LeftButton; - std::cout << "the first condition:"<< one <mMeta.mMsgStatus); - std::cout << "the second condition:"<< one <mMeta.mMsgStatus); - std::cout << "the third condition:"<< one <mMeta.mMsgStatus); - std::cout << "the fourth condition:"<< one < + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + COPY LINK + + + + :/images/link.svg:/images/link.svg + + + Qt::ToolButtonTextBesideIcon + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp b/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp index 475c74034..f2b8df7db 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp @@ -28,6 +28,7 @@ #include "WireGroupDialog.h" #include "gui/gxs/GxsIdDetails.h" +#include "gui/RetroShareLink.h" #include "gui/common/FilesDefs.h" #include "util/DateTime.h" @@ -50,6 +51,7 @@ void PulseViewGroup::setup() { if (mGroup) { connect(followButton, SIGNAL(clicked()), this, SLOT(actionFollow())); + connect(toolButton_copyProfileLink, SIGNAL(clicked()), this, SLOT(actionCopyProfileLink())); label_groupName->setText("@" + QString::fromStdString(mGroup->mMeta.mGroupName)); label_authorName->setText(BoldString(QString::fromStdString(mGroup->mMeta.mAuthorId.toStdString()))); @@ -110,11 +112,13 @@ void PulseViewGroup::setup() uint32_t replies = mGroup->mRefReplies; uint32_t republishes = mGroup->mRefRepublishes; uint32_t likes = mGroup->mRefLikes; + // uint32_t following = mGroup->mGroupFollowing; // TODO: field not yet in RsWireGroup label_extra_pulses->setText(BoldString(ToNumberUnits(pulses))); label_extra_replies->setText(BoldString(ToNumberUnits(replies))); label_extra_republishes->setText(BoldString(ToNumberUnits(republishes))); label_extra_likes->setText(BoldString(ToNumberUnits(likes))); + // label_extra_following->setText(BoldString(ToNumberUnits(following))); // TODO: enable when mGroupFollowing added // hide follow. widget_actions->setVisible(false); @@ -156,6 +160,29 @@ void PulseViewGroup::actionFollow() } } +void PulseViewGroup::actionCopyProfileLink() +{ + std::cerr << "PulseViewGroup::actionCopyProfileLink()"; + std::cerr << std::endl; + + if (!mGroup) { + std::cerr << "PulseViewGroup::actionCopyProfileLink() GROUP invalid"; + std::cerr << std::endl; + return; + } + + RetroShareLink link = RetroShareLink::createGxsGroupLink( + RetroShareLink::TYPE_WIRE, + mGroup->mMeta.mGroupId, + QString::fromStdString(mGroup->mMeta.mGroupName)); + + if (link.valid()) { + QList urls; + urls.push_back(link); + RSLinkClipboard::copyLinks(urls); + } +} + void PulseViewGroup::editProfile() { RsGxsGroupId groupId = mGroup->mMeta.mGroupId; diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.h b/retroshare-gui/src/gui/TheWire/PulseViewGroup.h index 62da0a228..4a4b4fd53 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.h +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.h @@ -35,6 +35,7 @@ public: private slots: void actionFollow(); + void actionCopyProfileLink(); void editProfile(); protected: diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui b/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui index 9faac4ab0..8e389af5c 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui @@ -493,6 +493,40 @@ + + + + + + <html><head/><body><p><span style=" font-weight:600;">0</span></p></body></html> + + + + + + + <html><head/><body><p><span style=" color:#2e3436;">Following</span></p></body></html> + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 40 + 20 + + + + + + @@ -561,6 +595,27 @@ + + + + + 12 + 75 + true + + + + COPY LINK + + + + :/images/link.svg:/images/link.svg + + + Qt::ToolButtonTextBesideIcon + + + diff --git a/retroshare-gui/src/gui/TheWire/PulseViewItem.cpp b/retroshare-gui/src/gui/TheWire/PulseViewItem.cpp index 3df22aebb..d56c140b8 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewItem.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseViewItem.cpp @@ -27,6 +27,7 @@ #include "gui/gxs/GxsIdDetails.h" #include "gui/common/FilesDefs.h" +#include "gui/RetroShareLink.h" #include "util/DateTime.h" /** Constructor */ @@ -238,6 +239,30 @@ void PulseDataItem::actionRate() } } +void PulseDataItem::actionCopyLink() +{ + std::cerr << "PulseDataItem::actionCopyLink()"; + std::cerr << std::endl; + + if (!mPulse) { + std::cerr << "PulseDataItem::actionCopyLink() PULSE invalid"; + std::cerr << std::endl; + return; + } + + RetroShareLink link = RetroShareLink::createGxsMessageLink( + RetroShareLink::TYPE_WIRE, + mPulse->mMeta.mGroupId, + mPulse->mMeta.mMsgId, + QString::fromStdString(mPulse->mMeta.mMsgName)); + + if (link.valid()) { + QList urls; + urls.push_back(link); + RSLinkClipboard::copyLinks(urls); + } +} + void PulseDataItem::showPulse() @@ -465,14 +490,9 @@ QString ToNumberUnits(uint32_t count) void PulseDataItem::mousePressEvent(QMouseEvent *event) { - // Check if the event is a left mouse button press if (event->button() == Qt::LeftButton) { - // Perform some action when the left mouse button is pressed - std::cout << "Left mouse button pressed on PulseViewItem!" <setCurrentIndex(GROUP_SET_SUBSCRIBED); + mGroupSelected = nullptr; + showGroups(); +} + +void WireDialog::filterUsers(const QString &text) +{ + QLayout *alayout = ui.groupsWidget->layout(); + QString filterText = text.toLower(); + + for (int i = 0; i < alayout->count(); ++i) + { + QLayoutItem *item = alayout->itemAt(i); + QWidget *widget = item->widget(); + WireGroupItem *groupItem = dynamic_cast(widget); + + if (groupItem) + { + bool visible = filterText.isEmpty() || groupItem->matchesFilter(filterText); + groupItem->setVisible(visible); + } + } +} + void WireDialog::addGroup(QWidget *item) { QLayout *alayout = ui.groupsWidget->layout(); @@ -592,7 +621,6 @@ void WireDialog::showGroups() std::list allGroupIds; - /* depends on the comboBox */ for (auto &it : mAllGroups) { bool add = (mGroupSet == GROUP_SET_ALL); @@ -614,9 +642,6 @@ void WireDialog::showGroups() if (add) { addGroup(it.second); - // request data. - std::list grpIds; - grpIds.push_back(it.second.mMeta.mGroupId); allGroupIds.push_back(it.second.mMeta.mGroupId); } } diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.h b/retroshare-gui/src/gui/TheWire/WireDialog.h index a3baf3987..89cd5823e 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.h +++ b/retroshare-gui/src/gui/TheWire/WireDialog.h @@ -133,6 +133,8 @@ private slots: void createGroup(); void createPulse(); + void showHomeFeed(); + void filterUsers(const QString &text); void checkUpdate(); void refreshGroups(); void selectGroupSet(int index); diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.ui b/retroshare-gui/src/gui/TheWire/WireDialog.ui index ad28fba5e..6e678774b 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.ui +++ b/retroshare-gui/src/gui/TheWire/WireDialog.ui @@ -87,6 +87,20 @@ + + + + Home + + + + :/icons/png/home.png:/icons/png/home.png + + + Qt::ToolButtonTextBesideIcon + + + @@ -177,6 +191,16 @@ + + + + Search... + + + true + + + diff --git a/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp b/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp index e832540de..586ea6e7d 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireGroupDialog.cpp @@ -34,7 +34,7 @@ const uint32_t WireCreateEnabledFlags = ( GXS_GROUP_FLAGS_DISTRIBUTION | // GXS_GROUP_FLAGS_PUBLISHSIGN | // GXS_GROUP_FLAGS_SHAREKEYS | // disabled because the UI doesn't handle it yet. - // GXS_GROUP_FLAGS_PERSONALSIGN | + GXS_GROUP_FLAGS_PERSONALSIGN | // GXS_GROUP_FLAGS_COMMENTS | GXS_GROUP_FLAGS_EXTRA | 0); diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp b/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp index 1759103f6..de4ac6061 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.cpp @@ -210,6 +210,15 @@ const QPixmap *WireGroupItem::getPixmap() return NULL; } +bool WireGroupItem::matchesFilter(const QString &filterText) const +{ + if (filterText.isEmpty()) + return true; + + QString groupName = QString::fromStdString(mGroup.mMeta.mGroupName).toLower(); + return groupName.contains(filterText); +} + void WireGroupItem::editGroupDetails() { RsGxsGroupId groupId = mGroup.mMeta.mGroupId; diff --git a/retroshare-gui/src/gui/TheWire/WireGroupItem.h b/retroshare-gui/src/gui/TheWire/WireGroupItem.h index a7ae14326..522a1ccc2 100644 --- a/retroshare-gui/src/gui/TheWire/WireGroupItem.h +++ b/retroshare-gui/src/gui/TheWire/WireGroupItem.h @@ -51,6 +51,7 @@ public: const QPixmap *getPixmap(); RsGxsGroupId &groupId(); + bool matchesFilter(const QString &filterText) const; private slots: void show(); diff --git a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp index b4970e3d3..11d5f257a 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp @@ -254,68 +254,43 @@ void WireNotifyPostItem::loadMessage() #endif mLoadingMessage = true; - RsThread::async([this]() - { - // 1 - get group data + RsGxsGroupId grpId = groupId(); + RsGxsMessageId msgId = messageId(); - std::list groupIds; - std::list pulses; -// std::vector comments; -// std::vector votes; - groupIds.push_back(groupId()); - if(! rsWire->getPulsesForGroups(groupIds, pulses)) + RsThread::async([this, grpId, msgId]() + { + RsWirePulseSPtr pPulse; + + if (!rsWire->getWirePulse(grpId, msgId, pPulse)) { - RsErr() << "WireNotifyPostItem::loadGroup() ERROR getting data" << std::endl; + RsErr() << "WireNotifyPostItem::loadMessage() ERROR getting pulse" << std::endl; + RsQThreadUtils::postToObject([this]() + { + mLoadingMessage = false; + }, this); return; } - if (pulses.size() == 1) + if (pPulse) { #ifdef DEBUG_ITEM - std::cerr << (void*)this << ": Obtained post, with msgId = " << pulses[0].mMeta.mMsgId << std::endl; + std::cerr << (void*)this << ": Obtained post, with msgId = " << pPulse->mMeta.mMsgId << std::endl; #endif - const RsWirePulse& pulse(*pulses.front()); + const RsWirePulse pulse(*pPulse); - RsQThreadUtils::postToObject( [pulse,this]() + RsQThreadUtils::postToObject([pulse, this]() { setPost(pulse); mLoadingMessage = false; - }, this ); + }, this); + } + else + { + RsQThreadUtils::postToObject([this]() + { + mLoadingMessage = false; + }, this); } -// else if(comments.size() == 1) -// { -// const RsGxsComment& cmt = comments[0]; -//#ifdef DEBUG_ITEM -// std::cerr << (void*)this << ": Obtained comment, setting messageId to threadID = " << cmt.mMeta.mThreadId << std::endl; -//#endif - -// RsQThreadUtils::postToObject( [cmt,this]() -// { -// 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(); - -// mLoadingMessage = false; -// }, this ); - -// } -// else -// { -//#ifdef DEBUG_ITEM -// std::cerr << "WireNotifyPostItem::loadMessage() Wrong number of Items. Remove It."; -// std::cerr << std::endl; -//#endif - -// RsQThreadUtils::postToObject( [this]() -// { -// removeItem(); -// mLoadingMessage = false; -// }, this ); -// } }); } diff --git a/retroshare-gui/src/gui/gxs/GxsUserNotify.cpp b/retroshare-gui/src/gui/gxs/GxsUserNotify.cpp index a8dc5a3b5..143a06ae5 100644 --- a/retroshare-gui/src/gui/gxs/GxsUserNotify.cpp +++ b/retroshare-gui/src/gui/gxs/GxsUserNotify.cpp @@ -37,7 +37,6 @@ GxsUserNotify::~GxsUserNotify() {} void GxsUserNotify::startUpdate() { - std::cout<<"inside the gxs user notify startUpdate function"< Date: Tue, 27 Jan 2026 04:08:09 +0530 Subject: [PATCH 07/13] Wire: Fix reply/like/republish bugs, read/unread marking, navigate links --- .../src/gui/TheWire/PulseAddDialog.cpp | 68 +++++++--- .../src/gui/TheWire/PulseAddDialog.h | 3 +- .../src/gui/TheWire/PulseViewItem.cpp | 15 ++- retroshare-gui/src/gui/TheWire/WireDialog.cpp | 127 ++++++++++++------ 4 files changed, 152 insertions(+), 61 deletions(-) diff --git a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp index 722f43fe9..77d0217ce 100644 --- a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp @@ -135,29 +135,35 @@ void PulseAddDialog::cleanup() std::cerr << "PulseAddDialog::cleanup() cleaning up old replyto"; std::cerr << std::endl; QLayout *layout = ui.widget_replyto->layout(); - // completely delete layout and sublayouts - QLayoutItem * item; - while ((item = layout->takeAt(0))) + if (layout) { - if (QWidget *widget = item->widget()) + // completely delete layout and sublayouts + QLayoutItem * item; + while ((item = layout->takeAt(0))) { - std::cerr << "PulseAddDialog::cleanup() removing widget"; - std::cerr << std::endl; - widget->hide(); - delete widget; - } - else - { - std::cerr << "PulseAddDialog::cleanup() removing item"; - std::cerr << std::endl; - delete item; + if (QWidget *widget = item->widget()) + { + std::cerr << "PulseAddDialog::cleanup() removing widget"; + std::cerr << std::endl; + widget->hide(); + delete widget; + } + else + { + std::cerr << "PulseAddDialog::cleanup() removing item"; + std::cerr << std::endl; + delete item; + } } + // then finally + delete layout; } - // then finally - delete layout; mIsReply = false; } + mReplyToPulse = RsWirePulse(); + mReplyType = 0; + ui.frame_reply->setVisible(false); ui.comboBox_sentiment->setCurrentIndex(0); ui.lineEdit_URL->setText(""); @@ -260,6 +266,13 @@ void PulseAddDialog::setReplyTo(const RsGxsGroupId &grpId, const RsGxsMessageId if(grpId.isNull()){ return; } + + mIsReply = true; + mReplyType = replyType; + ui.postButton->setEnabled(false); + ui.postButton->setText(tr("Loading...")); + show(); + /* fetch in the background */ RsThread::async([this,grpId,msgId,replyType](){ @@ -269,12 +282,14 @@ void PulseAddDialog::setReplyTo(const RsGxsGroupId &grpId, const RsGxsMessageId if(!rsWire->getWireGroup(grpId,pGroup)) { std::cerr << __PRETTY_FUNCTION__ << "PulseAddDialog::setRplyTo() failed to fetch group id: " << grpId << std::endl; + RsQThreadUtils::postToObject([this]() { hide(); }, this); return; } if (!rsWire->getWirePulse(grpId, msgId, pPulse)) { std::cerr << "PulseAddDialog::setRplyTo() failed to fetch pulse of group id: " << grpId << std::endl; + RsQThreadUtils::postToObject([this]() { hide(); }, this); return; } @@ -408,6 +423,21 @@ void PulseAddDialog::postReplyPulse() std::cerr << "PulseAddDialog::postReplyPulse()"; std::cerr << std::endl; + if (mReplyToPulse.mMeta.mGroupId.isNull()) { + std::cerr << "PulseAddDialog::postReplyPulse() reply data not ready yet"; + std::cerr << std::endl; + return; + } + + if (mGroup.mMeta.mGroupId.isNull()) { + std::cerr << "PulseAddDialog::postReplyPulse() group not set"; + std::cerr << std::endl; + return; + } + + ui.postButton->setEnabled(false); + setCursor(Qt::WaitCursor); + RsWirePulseSPtr pPulse(new RsWirePulse()); pPulse->mSentiment = toPulseSentiment(ui.comboBox_sentiment->currentIndex()); @@ -440,6 +470,11 @@ void PulseAddDialog::postReplyPulse() { std::cerr << "PulseAddDialog::postReplyPulse() FAILED"; std::cerr << std::endl; + RsQThreadUtils::postToObject([this]() + { + setCursor(Qt::ArrowCursor); + ui.postButton->setEnabled(true); + }, this); return; } @@ -451,6 +486,7 @@ void PulseAddDialog::postReplyPulse() * Qt::QueuedConnection is important! */ + setCursor(Qt::ArrowCursor); clearDialog(); hide(); }, this ); diff --git a/retroshare-gui/src/gui/TheWire/PulseAddDialog.h b/retroshare-gui/src/gui/TheWire/PulseAddDialog.h index b1e8eca47..8be4b6462 100644 --- a/retroshare-gui/src/gui/TheWire/PulseAddDialog.h +++ b/retroshare-gui/src/gui/TheWire/PulseAddDialog.h @@ -44,6 +44,7 @@ public: void setReplyTo(const RsGxsGroupId &grpId, const RsGxsMessageId &msgId, uint32_t replyType); void setGroup(const RsGxsGroupId &grpId); + void setGroup(RsWireGroup &group); private slots: void addURL(); @@ -57,8 +58,6 @@ private slots: void removePictures(); private: - // OLD VERSIONs, private now. - void setGroup(RsWireGroup &group); void setReplyTo(const RsWirePulse &pulse, RsWirePulseSPtr pPulse, std::string &groupName, uint32_t replyType); void postOriginalPulse(); diff --git a/retroshare-gui/src/gui/TheWire/PulseViewItem.cpp b/retroshare-gui/src/gui/TheWire/PulseViewItem.cpp index d56c140b8..1549d4008 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewItem.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseViewItem.cpp @@ -25,6 +25,8 @@ #include "PulseViewItem.h" +#include "retroshare/rsgxsflags.h" + #include "gui/gxs/GxsIdDetails.h" #include "gui/common/FilesDefs.h" #include "gui/RetroShareLink.h" @@ -250,11 +252,16 @@ void PulseDataItem::actionCopyLink() return; } + std::string linkName = mPulse->mMeta.mMsgName; + if (linkName.empty()) { + linkName = mPulse->mPulseText.substr(0, 50); + } + RetroShareLink link = RetroShareLink::createGxsMessageLink( RetroShareLink::TYPE_WIRE, mPulse->mMeta.mGroupId, mPulse->mMeta.mMsgId, - QString::fromStdString(mPulse->mMeta.mMsgName)); + QString::fromStdString(linkName)); if (link.valid()) { QList urls; @@ -490,9 +497,11 @@ QString ToNumberUnits(uint32_t count) void PulseDataItem::mousePressEvent(QMouseEvent *event) { - if (event->button() == Qt::LeftButton) + if (event->button() == Qt::LeftButton && IS_MSG_UNPROCESSED(mPulse->mMeta.mMsgStatus)) { - // Handle left click on pulse item + uint32_t token; + RsGxsGrpMsgIdPair msgPair = std::make_pair(mPulse->mMeta.mGroupId, mPulse->mMeta.mMsgId); + rsWire->setMessageReadStatus(token, msgPair, true); } QWidget::mousePressEvent(event); } diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.cpp b/retroshare-gui/src/gui/TheWire/WireDialog.cpp index 6443b8bf1..cb656898e 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireDialog.cpp @@ -78,6 +78,8 @@ WireDialog::WireDialog(QWidget *parent) connect(ui.comboBox_groupSet, SIGNAL(currentIndexChanged(int)), this, SLOT(selectGroupSet(int))); connect(ui.comboBox_filterTime, SIGNAL(currentIndexChanged(int)), this, SLOT(selectFilterTime(int))); + ui.comboBox_groupSet->hide(); + connect( ui.toolButton_back, SIGNAL(clicked()), this, SLOT(back())); connect( ui.toolButton_forward, SIGNAL(clicked()), this, SLOT(forward())); ui.toolButton_back->setEnabled(false); @@ -394,7 +396,7 @@ bool WireDialog::setupPulseAddDialog() mAddDialog->cleanup(); int idx = ui.groupChooser->currentIndex(); - if (idx < 0) { + if (idx < 0 || idx >= (int)mOwnGroups.size()) { std::cerr << "WireDialog::setupPulseAddDialog() ERROR GETTING AuthorId!"; std::cerr << std::endl; @@ -402,9 +404,8 @@ bool WireDialog::setupPulseAddDialog() return false; } - // publishing group. RsWireGroup group = mOwnGroups[idx]; - mAddDialog->setGroup(group.mMeta.mGroupId); + mAddDialog->setGroup(group); return true; } @@ -791,40 +792,106 @@ void WireDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) void WireDialog::PVHreply(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId) { std::cerr << "WireDialog::PVHreply() GroupId: " << groupId; - std::cerr << "MsgId: " << msgId; + std::cerr << " MsgId: " << msgId; std::cerr << std::endl; if (setupPulseAddDialog()) { mAddDialog->setReplyTo(groupId, msgId, WIRE_PULSE_TYPE_REPLY); - mAddDialog->show(); } } void WireDialog::PVHrepublish(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId) { std::cerr << "WireDialog::PVHrepublish() GroupId: " << groupId; - std::cerr << "MsgId: " << msgId; + std::cerr << " MsgId: " << msgId; std::cerr << std::endl; - if (setupPulseAddDialog()) - { - mAddDialog->setReplyTo(groupId, msgId, WIRE_PULSE_TYPE_REPUBLISH); - mAddDialog->show(); + int idx = ui.groupChooser->currentIndex(); + if (idx < 0 || idx >= (int)mOwnGroups.size()) { + std::cerr << "WireDialog::PVHrepublish() No own group selected"; + std::cerr << std::endl; + QMessageBox::warning(this, tr("RetroShare"), tr("Please select your Wire account first"), QMessageBox::Ok); + return; } + + RsGxsGroupId replyWith = mOwnGroups[idx].mMeta.mGroupId; + setCursor(Qt::WaitCursor); + + RsThread::async([this, groupId, msgId, replyWith]() + { + RsWirePulseSPtr origPulse; + if (!rsWire->getWirePulse(groupId, msgId, origPulse)) + { + std::cerr << "WireDialog::PVHrepublish() failed to fetch original pulse"; + std::cerr << std::endl; + RsQThreadUtils::postToObject([this]() + { + setCursor(Qt::ArrowCursor); + }, this); + return; + } + + RsWirePulseSPtr pPulse(new RsWirePulse()); + pPulse->mSentiment = origPulse->mSentiment; + pPulse->mPulseText = origPulse->mPulseText; + pPulse->mImage1 = origPulse->mImage1; + pPulse->mImage2 = origPulse->mImage2; + pPulse->mImage3 = origPulse->mImage3; + pPulse->mImage4 = origPulse->mImage4; + + RsGxsMessageId targetMsgId = origPulse->mMeta.mOrigMsgId; + if (targetMsgId.isNull()) { + targetMsgId = msgId; + } + + bool success = rsWire->createReplyPulse(groupId, targetMsgId, replyWith, + WIRE_PULSE_TYPE_REPUBLISH, pPulse); + + RsQThreadUtils::postToObject([this, success]() + { + setCursor(Qt::ArrowCursor); + if (!success) { + std::cerr << "WireDialog::PVHrepublish() FAILED" << std::endl; + } + }, this); + }); } void WireDialog::PVHlike(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId) { std::cerr << "WireDialog::PVHlike() GroupId: " << groupId; - std::cerr << "MsgId: " << msgId; + std::cerr << " MsgId: " << msgId; std::cerr << std::endl; - if (setupPulseAddDialog()) - { - mAddDialog->setReplyTo(groupId, msgId, WIRE_PULSE_TYPE_LIKE); - mAddDialog->show(); + int idx = ui.groupChooser->currentIndex(); + if (idx < 0 || idx >= (int)mOwnGroups.size()) { + std::cerr << "WireDialog::PVHlike() No own group selected"; + std::cerr << std::endl; + QMessageBox::warning(this, tr("RetroShare"), tr("Please select your Wire account first"), QMessageBox::Ok); + return; } + + RsGxsGroupId replyWith = mOwnGroups[idx].mMeta.mGroupId; + setCursor(Qt::WaitCursor); + + RsThread::async([this, groupId, msgId, replyWith]() + { + RsWirePulseSPtr pPulse(new RsWirePulse()); + pPulse->mSentiment = WIRE_PULSE_SENTIMENT_NO_SENTIMENT; + pPulse->mPulseText = ""; + + bool success = rsWire->createReplyPulse(groupId, msgId, replyWith, + WIRE_PULSE_TYPE_LIKE, pPulse); + + RsQThreadUtils::postToObject([this, success]() + { + setCursor(Qt::ArrowCursor); + if (!success) { + std::cerr << "WireDialog::PVHlike() FAILED" << std::endl; + } + }, this); + }); } void WireDialog::PVHviewGroup(const RsGxsGroupId &groupId) @@ -1369,32 +1436,12 @@ bool WireDialog::navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msg return false; } -// if (mStateHelper->isLoading(TOKEN_TYPE_GROUP_SUMMARY)) { -// mNavigatePendingGroupId = groupId; -// mNavigatePendingMsgId = msgId; + if (!msgId.isNull()) { + requestPulseFocus(groupId, msgId); + } else { + requestGroupFocus(groupId); + } -// /* No information if group is available */ -// return true; -// } - -// QString groupIdString = QString::fromStdString(groupId.toStdString()); -// if (ui.groupTreeWidget->activateId(groupIdString, msgId.isNull()) == NULL) { -// return false; -// } - -// changedCurrentGroup(groupIdString); - - /* search exisiting tab */ -// GxsMessageFrameWidget *msgWidget = messageWidget(mGroupId); -// if (!msgWidget) { -// return false; -// } - -// if (msgId.isNull()) { -// return true; -// } - -// return msgWidget->navigate(msgId); return true; } From e5e35da0bba898a28c298c13aca8e409885aad5a Mon Sep 17 00:00:00 2001 From: saurabh Date: Tue, 27 Jan 2026 17:35:21 +0530 Subject: [PATCH 08/13] Wire: Enable link clicks in notification items --- .../src/gui/feeds/WireNotifyGroupItem.cpp | 16 +++++++++++++++- .../src/gui/feeds/WireNotifyGroupItem.h | 1 + .../src/gui/feeds/WireNotifyPostItem.cpp | 1 - 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp index f8885d2f4..d69edfbae 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp +++ b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp @@ -26,6 +26,8 @@ #include "gui/common/FilesDefs.h" #include "gui/RetroShareLink.h" #include "gui/gxs/GxsIdDetails.h" +#include "gui/MainWindow.h" +#include "gui/TheWire/WireDialog.h" #include "util/DateTime.h" /**** @@ -99,8 +101,10 @@ void WireNotifyGroupItem::setup() connect(ui->subscribeButton, SIGNAL(clicked()), this, SLOT(subscribeWire())); connect(ui->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyGroupLink())); + ui->nameLabel->setOpenExternalLinks(false); + connect(ui->nameLabel, SIGNAL(linkActivated(QString)), this, SLOT(openWireGroup())); + //ui->copyLinkButton->hide(); // No link type at this moment - ui->nameLabel->setEnabled(false); ui->expandFrame->hide(); } @@ -263,3 +267,13 @@ void WireNotifyGroupItem::subscribeWire() uint32_t token; rsWire->subscribeToGroup(token, mGroup.mMeta.mGroupId, true); } + +void WireNotifyGroupItem::openWireGroup() +{ + MainWindow::showWindow(MainWindow::Wire); + WireDialog *wireDialog = dynamic_cast(MainWindow::getPage(MainWindow::Wire)); + if (wireDialog) { + wireDialog->navigate(mGroup.mMeta.mGroupId, RsGxsMessageId()); + } + removeItem(); +} diff --git a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h index 0bbee742c..ed99c2618 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h +++ b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h @@ -56,6 +56,7 @@ protected: private slots: void toggle() override; void subscribeWire(); + void openWireGroup(); private: void fill(); diff --git a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp index 11d5f257a..f5482216e 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp @@ -203,7 +203,6 @@ void WireNotifyPostItem::setup() ui->titleLabel->setMinimumWidth(100); ui->subjectLabel->setMinimumWidth(100); //ui->warning_label->setMinimumWidth(100); - ui->titleLabel->setEnabled(false); ui->feedFrame->setProperty("new", false); ui->feedFrame->style()->unpolish(ui->feedFrame); From 76845e50a7356ad1bc26e55acd765725560e53b8 Mon Sep 17 00:00:00 2001 From: saurabh Date: Tue, 3 Feb 2026 14:03:32 +0530 Subject: [PATCH 09/13] Fix Wire notification tray click not opening Wire page - Remove shadowed local variable in MainWindow.cpp that prevented wireDialog member from being set - Add pending navigation pattern in WireDialog for deferred navigation - Restore openWireGroup() in WireNotifyGroupItem --- retroshare-gui/src/gui/MainWindow.cpp | 1 - retroshare-gui/src/gui/TheWire/WireDialog.cpp | 40 +- retroshare-gui/src/gui/TheWire/WireDialog.h | 4 + .../src/gui/feeds/WireNotifyGroupItem.cpp | 557 +++--- .../src/gui/feeds/WireNotifyPostItem.cpp | 1524 +++++++++-------- .../src/gui/feeds/WireNotifyPostItem.ui | 982 ++++++----- 6 files changed, 1565 insertions(+), 1543 deletions(-) diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index a29f2e263..1a23518f6 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -462,7 +462,6 @@ void MainWindow::initStackedPage() #endif #ifdef RS_USE_WIRE - WireDialog *wireDialog = NULL; addPage(wireDialog = new WireDialog(ui->stackPages), grp, ¬ify); #endif diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.cpp b/retroshare-gui/src/gui/TheWire/WireDialog.cpp index cb656898e..a26cf3929 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireDialog.cpp @@ -75,10 +75,10 @@ WireDialog::WireDialog(QWidget *parent) connect( ui.toolButton_home, SIGNAL(clicked()), this, SLOT(showHomeFeed())); connect( ui.lineEdit_searchUsers, SIGNAL(textChanged(const QString&)), this, SLOT(filterUsers(const QString&))); + connect(ui.comboBox_groupSet, SIGNAL(currentIndexChanged(int)), this, SLOT(selectGroupSet(int))); connect(ui.comboBox_filterTime, SIGNAL(currentIndexChanged(int)), this, SLOT(selectFilterTime(int))); - - ui.comboBox_groupSet->hide(); + // ui.comboBox_groupSet->hide(); // <--- Re-enabled for testing as requested connect( ui.toolButton_back, SIGNAL(clicked()), this, SLOT(back())); connect( ui.toolButton_forward, SIGNAL(clicked()), this, SLOT(forward())); @@ -675,6 +675,17 @@ bool WireDialog::loadGroupData(const uint32_t &token) // save list of groups. updateGroups(groups); showGroups(); + + // check for pending navigation + if (!mNavigatePendingGroupId.isNull()) { + if (!mNavigatePendingMsgId.isNull()) { + requestPulseFocus(mNavigatePendingGroupId, mNavigatePendingMsgId); + } else { + requestGroupFocus(mNavigatePendingGroupId); + } + mNavigatePendingGroupId.clear(); + mNavigatePendingMsgId.clear(); + } return true; } @@ -1432,17 +1443,24 @@ void WireDialog::updateGroupStatisticsReal(const RsGxsGroupId &groupId) bool WireDialog::navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msgId) { - if (groupId.isNull()) { - return false; - } + if (groupId.isNull()) { + return false; + } - if (!msgId.isNull()) { - requestPulseFocus(groupId, msgId); - } else { - requestGroupFocus(groupId); - } + // if groups not loaded yet, save for later + if (mAllGroups.empty()) { + mNavigatePendingGroupId = groupId; + mNavigatePendingMsgId = msgId; + return true; + } - return true; + if (!msgId.isNull()) { + requestPulseFocus(groupId, msgId); + } else { + requestGroupFocus(groupId); + } + + return true; } GxsMessageFrameWidget *WireDialog::messageWidget(const RsGxsGroupId &groupId) diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.h b/retroshare-gui/src/gui/TheWire/WireDialog.h index 89cd5823e..598b79ec4 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.h +++ b/retroshare-gui/src/gui/TheWire/WireDialog.h @@ -187,6 +187,10 @@ private: int32_t mHistoryIndex; std::vector mHistory; + // pending navigation (for when navigate called before groups loaded) + RsGxsGroupId mNavigatePendingGroupId; + RsGxsMessageId mNavigatePendingMsgId; + /* UI - from Designer */ Ui::WireDialog ui; diff --git a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp index d69edfbae..0eeecf46c 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp +++ b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp @@ -1,279 +1,278 @@ -/******************************************************************************* - * gui/feeds/WireNotifyGroupItem.cpp * - * * - * Copyright (c) 2014, 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 "WireNotifyGroupItem.h" -#include "ui_WireNotifyGroupItem.h" - -#include "FeedHolder.h" -#include "util/qtthreadsutils.h" -#include "gui/common/FilesDefs.h" -#include "gui/RetroShareLink.h" -#include "gui/gxs/GxsIdDetails.h" -#include "gui/MainWindow.h" -#include "gui/TheWire/WireDialog.h" -#include "util/DateTime.h" - -/**** - * #define DEBUG_ITEM 1 - ****/ - -WireNotifyGroupItem::WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, bool autoUpdate) : - GxsGroupFeedItem(feedHolder, feedId, groupId, isHome, rsWire, autoUpdate) -{ - setup(); - requestGroup(); - addEventHandler(); -} - -WireNotifyGroupItem::WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate) : - GxsGroupFeedItem(feedHolder, feedId, group.mMeta.mGroupId, isHome, rsWire, autoUpdate) -{ - setup(); - setGroup(group); - addEventHandler(); -} - -void WireNotifyGroupItem::addEventHandler() -{ - mEventHandlerId = 0; - rsEvents->registerEventsHandler( [this](std::shared_ptr event) - { - RsQThreadUtils::postToObject([=]() - { - const auto *e = dynamic_cast(event.get()); - - if(!e || e->mWireGroupId != this->groupId()) - return; - - switch(e->mWireEventCode) - { - case RsWireEventCode::FOLLOW_STATUS_CHANGED: - case RsWireEventCode::WIRE_UPDATED: - break; - default: - break; - } - }, this ); - }, mEventHandlerId, RsEventType::WIRE ); -} - -WireNotifyGroupItem::~WireNotifyGroupItem() -{ - rsEvents->unregisterEventsHandler(mEventHandlerId); - delete(ui); -} - -void WireNotifyGroupItem::setup() -{ - /* Invoke the Qt Designer generated object setup routine */ - ui = new(Ui::WireNotifyGroupItem); - ui->setupUi(this); - - setAttribute(Qt::WA_DeleteOnClose, true); - - /* clear ui */ - ui->nameLabel->setText(tr("Loading...")); - ui->titleLabel->clear(); - ui->descLabel->clear(); - - /* general ones */ - connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(toggle())); - connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(removeItem())); - - /* specific */ - connect(ui->subscribeButton, SIGNAL(clicked()), this, SLOT(subscribeWire())); - connect(ui->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyGroupLink())); - - ui->nameLabel->setOpenExternalLinks(false); - connect(ui->nameLabel, SIGNAL(linkActivated(QString)), this, SLOT(openWireGroup())); - - //ui->copyLinkButton->hide(); // No link type at this moment - ui->expandFrame->hide(); -} - -bool WireNotifyGroupItem::setGroup(const RsWireGroup &group) -{ - if (groupId() != group.mMeta.mGroupId) { - std::cerr << "WireNotifyGroupItem::setContent() - Wrong id, cannot set post"; - std::cerr << std::endl; - return false; - } - mGroup = group; - fill(); - - return true; -} - -void WireNotifyGroupItem::loadGroup() -{ - RsThread::async([this]() - { - // 1 - get group data - -#ifdef DEBUG_ITEM - std::cerr << "Retrieving post data for post " << mThreadId << std::endl; -#endif - - std::vector groups; - const std::list groupIds = { groupId() }; - - if(!rsWire->getGroups(groupIds,groups)) - { - RsErr() << "WireNotifyGroupItem::loadGroup() ERROR getting data" << std::endl; - return; - } - - if (groups.size() != 1) - { - std::cerr << "WireNotifyGroupItem::loadGroup() Wrong number of Items"; - std::cerr << std::endl; - return; - } - RsWireGroup group(groups[0]); - - RsQThreadUtils::postToObject( [group,this]() - { - /* Here it goes any code you want to be executed on the Qt Gui - * thread, for example to update the data model with new information - * after a blocking call to RetroShare API complete */ - - setGroup(group); - - }, this ); - }); -} - -QString WireNotifyGroupItem::groupName() -{ - return QString::fromUtf8(mGroup.mMeta.mGroupName.c_str()); -} - -void WireNotifyGroupItem::fill() -{ - /* fill in */ - -#ifdef DEBUG_ITEM - std::cerr << "WireNotifyGroupItem::fill()"; - std::cerr << std::endl; -#endif - - // No link type at this moment - RetroShareLink link = RetroShareLink::createGxsGroupLink(RetroShareLink::TYPE_WIRE, mGroup.mMeta.mGroupId, groupName()); - ui->nameLabel->setText(link.toHtml()); - - ui->descLabel->setText(QString::fromUtf8(mGroup.mTagline.c_str())); - - if (mGroup.mHeadshot.mData != NULL) { - QPixmap wireImage; - GxsIdDetails::loadPixmapFromData(mGroup.mHeadshot.mData, mGroup.mHeadshot.mSize, wireImage,GxsIdDetails::ORIGINAL); - ui->logoLabel->setPixmap(QPixmap(wireImage)); - } else { - ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png")); - } - - //TODO - nice icon for subscribed group -// if (IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) { -// ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png")); -// } else { -// ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png")); -// } - - if (IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags)) { - ui->subscribeButton->setEnabled(false); - } else { - ui->subscribeButton->setEnabled(true); - } - - if(mGroup.mMeta.mLastPost==0) - ui->infoLastPost->setText(tr("Never")); - else - ui->infoLastPost->setText(DateTime::formatLongDateTime(mGroup.mMeta.mLastPost)); - -// if (mIsNew) -// { - ui->titleLabel->setText(tr("New Wire")); -// } -// else -// { -// ui->titleLabel->setText(tr("Updated Wire")); -// } - - if (mIsHome) - { - /* disable buttons */ - ui->clearButton->setEnabled(false); - } -} - -void WireNotifyGroupItem::toggle() -{ - expand(ui->expandFrame->isHidden()); -} - -void WireNotifyGroupItem::doExpand(bool open) -{ - if (mFeedHolder) - { - mFeedHolder->lockLayout(this, true); - } - - if (open) - { - ui->expandFrame->show(); - ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/up-arrow.png"))); - ui->expandButton->setToolTip(tr("Hide")); - } - else - { - ui->expandFrame->hide(); - ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/down-arrow.png"))); - ui->expandButton->setToolTip(tr("Expand")); - } - - emit sizeChanged(this); - - if (mFeedHolder) - { - mFeedHolder->lockLayout(this, false); - } -} - -void WireNotifyGroupItem::subscribeWire() -{ -#ifdef DEBUG_ITEM - std::cerr << "WireNotifyGroupItem::subscribeWire()"; - std::cerr << std::endl; -#endif - - //subscribe(); does not work for wire, bug? -> GxsGroupFeedItem::subscribe() - - uint32_t token; - rsWire->subscribeToGroup(token, mGroup.mMeta.mGroupId, true); -} - -void WireNotifyGroupItem::openWireGroup() -{ - MainWindow::showWindow(MainWindow::Wire); - WireDialog *wireDialog = dynamic_cast(MainWindow::getPage(MainWindow::Wire)); - if (wireDialog) { - wireDialog->navigate(mGroup.mMeta.mGroupId, RsGxsMessageId()); - } - removeItem(); -} +/******************************************************************************* + * gui/feeds/WireNotifyGroupItem.cpp * + * * + * Copyright (c) 2014, 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 "WireNotifyGroupItem.h" +#include "ui_WireNotifyGroupItem.h" + +#include "FeedHolder.h" +#include "util/qtthreadsutils.h" +#include "gui/common/FilesDefs.h" +#include "gui/RetroShareLink.h" +#include "gui/gxs/GxsIdDetails.h" +#include "gui/MainWindow.h" +#include "gui/TheWire/WireDialog.h" +#include "util/DateTime.h" + +/**** + * #define DEBUG_ITEM 1 + ****/ + +WireNotifyGroupItem::WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, bool autoUpdate) : + GxsGroupFeedItem(feedHolder, feedId, groupId, isHome, rsWire, autoUpdate) +{ + setup(); + requestGroup(); + addEventHandler(); +} + +WireNotifyGroupItem::WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate) : + GxsGroupFeedItem(feedHolder, feedId, group.mMeta.mGroupId, isHome, rsWire, autoUpdate) +{ + setup(); + setGroup(group); + addEventHandler(); +} + +void WireNotifyGroupItem::addEventHandler() +{ + mEventHandlerId = 0; + rsEvents->registerEventsHandler( [this](std::shared_ptr event) + { + RsQThreadUtils::postToObject([=]() + { + const auto *e = dynamic_cast(event.get()); + + if(!e || e->mWireGroupId != this->groupId()) + return; + + switch(e->mWireEventCode) + { + case RsWireEventCode::FOLLOW_STATUS_CHANGED: + case RsWireEventCode::WIRE_UPDATED: + break; + default: + break; + } + }, this ); + }, mEventHandlerId, RsEventType::WIRE ); +} + +WireNotifyGroupItem::~WireNotifyGroupItem() +{ + rsEvents->unregisterEventsHandler(mEventHandlerId); + delete(ui); +} + +void WireNotifyGroupItem::setup() +{ + /* Invoke the Qt Designer generated object setup routine */ + ui = new(Ui::WireNotifyGroupItem); + ui->setupUi(this); + + setAttribute(Qt::WA_DeleteOnClose, true); + + /* clear ui */ + ui->nameLabel->setText(tr("Loading...")); + ui->titleLabel->clear(); + ui->descLabel->clear(); + + /* general ones */ + connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(toggle())); + connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(removeItem())); + + /* specific */ + connect(ui->subscribeButton, SIGNAL(clicked()), this, SLOT(subscribeWire())); + connect(ui->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyGroupLink())); + connect(ui->nameLabel, SIGNAL(linkActivated(QString)), this, SLOT(openWireGroup())); + + //ui->copyLinkButton->hide(); // No link type at this moment + ui->expandFrame->hide(); +} + +bool WireNotifyGroupItem::setGroup(const RsWireGroup &group) +{ + if (groupId() != group.mMeta.mGroupId) { + std::cerr << "WireNotifyGroupItem::setContent() - Wrong id, cannot set post"; + std::cerr << std::endl; + return false; + } + mGroup = group; + fill(); + + return true; +} + +void WireNotifyGroupItem::loadGroup() +{ + RsThread::async([this]() + { + // 1 - get group data + +#ifdef DEBUG_ITEM + std::cerr << "Retrieving post data for post " << mThreadId << std::endl; +#endif + + std::vector groups; + const std::list groupIds = { groupId() }; + + if(!rsWire->getGroups(groupIds,groups)) + { + RsErr() << "WireNotifyGroupItem::loadGroup() ERROR getting data" << std::endl; + return; + } + + if (groups.size() != 1) + { + std::cerr << "WireNotifyGroupItem::loadGroup() Wrong number of Items"; + std::cerr << std::endl; + return; + } + RsWireGroup group(groups[0]); + + RsQThreadUtils::postToObject( [group,this]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete */ + + setGroup(group); + + }, this ); + }); +} + +QString WireNotifyGroupItem::groupName() +{ + return QString::fromUtf8(mGroup.mMeta.mGroupName.c_str()); +} + +void WireNotifyGroupItem::fill() +{ + /* fill in */ + +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyGroupItem::fill()"; + std::cerr << std::endl; +#endif + + // No link type at this moment + RetroShareLink link = RetroShareLink::createGxsGroupLink(RetroShareLink::TYPE_WIRE, mGroup.mMeta.mGroupId, groupName()); + ui->nameLabel->setText(link.toHtml()); + + ui->descLabel->setText(QString::fromUtf8(mGroup.mTagline.c_str())); + + if (mGroup.mHeadshot.mData != NULL) { + QPixmap wireImage; + GxsIdDetails::loadPixmapFromData(mGroup.mHeadshot.mData, mGroup.mHeadshot.mSize, wireImage,GxsIdDetails::ORIGINAL); + ui->logoLabel->setPixmap(QPixmap(wireImage)); + } else { + ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png")); + } + + //TODO - nice icon for subscribed group +// if (IS_GROUP_PUBLISHER(mGroup.mMeta.mSubscribeFlags)) { +// ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png")); +// } else { +// ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png")); +// } + + if (IS_GROUP_SUBSCRIBED(mGroup.mMeta.mSubscribeFlags)) { + ui->subscribeButton->setEnabled(false); + } else { + ui->subscribeButton->setEnabled(true); + } + + if(mGroup.mMeta.mLastPost==0) + ui->infoLastPost->setText(tr("Never")); + else + ui->infoLastPost->setText(DateTime::formatLongDateTime(mGroup.mMeta.mLastPost)); + +// if (mIsNew) +// { + ui->titleLabel->setText(tr("New Wire")); +// } +// else +// { +// ui->titleLabel->setText(tr("Updated Wire")); +// } + + if (mIsHome) + { + /* disable buttons */ + ui->clearButton->setEnabled(false); + } +} + +void WireNotifyGroupItem::toggle() +{ + expand(ui->expandFrame->isHidden()); +} + +void WireNotifyGroupItem::doExpand(bool open) +{ + if (mFeedHolder) + { + mFeedHolder->lockLayout(this, true); + } + + if (open) + { + ui->expandFrame->show(); + ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/up-arrow.png"))); + ui->expandButton->setToolTip(tr("Hide")); + } + else + { + ui->expandFrame->hide(); + ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/down-arrow.png"))); + ui->expandButton->setToolTip(tr("Expand")); + } + + emit sizeChanged(this); + + if (mFeedHolder) + { + mFeedHolder->lockLayout(this, false); + } +} + +void WireNotifyGroupItem::subscribeWire() +{ +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyGroupItem::subscribeWire()"; + std::cerr << std::endl; +#endif + + //subscribe(); does not work for wire, bug? -> GxsGroupFeedItem::subscribe() + + uint32_t token; + rsWire->subscribeToGroup(token, mGroup.mMeta.mGroupId, true); +} + +void WireNotifyGroupItem::openWireGroup() +{ + MainWindow::showWindow(MainWindow::Wire); + WireDialog *wireDialog = dynamic_cast(MainWindow::getPage(MainWindow::Wire)); + if (wireDialog) + { + wireDialog->navigate(mGroup.mMeta.mGroupId, RsGxsMessageId()); + } + removeItem(); +} \ No newline at end of file diff --git a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp index f5482216e..09d8a9727 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp @@ -1,760 +1,764 @@ -/******************************************************************************* - * gui/feeds/WireNotifyPostItem.cpp * - * * - * Copyright (c) 2012, Robert Fernie * - * * - * 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 "WireNotifyPostItem.h" -#include "ui_WireNotifyPostItem.h" - -#include "FeedHolder.h" -#include "util/qtthreadsutils.h" -#include "gui/RetroShareLink.h" -#include "gui/common/FilesDefs.h" -#include "gui/gxs/GxsIdDetails.h" -#include "util/stringutil.h" -#include "util/DateTime.h" -#include "util/misc.h" - -#include -#include - -WireNotifyPostItem::WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGroupMetaData& group_meta, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate,const std::set& older_versions) : - GxsFeedItem(feedHolder, feedId, group_meta.mGroupId, messageId, isHome, rsWire, autoUpdate), - mGroupMeta(group_meta) -{ - mLoadingGroup = false; - mLoadingMessage = false; - mLoadingComment = false; - - mPulse.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded - mPulse.mMeta.mGroupId = mGroupMeta.mGroupId; - - QVector v; - //bool self = false; - - for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) - v.push_back(*it) ; - - if(older_versions.find(messageId) == older_versions.end()) - v.push_back(messageId); - - setMessageVersions(v) ; - setup(); - - // no call to loadGroup() here because we have it already. -} - -WireNotifyPostItem::WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set &older_versions) : - GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsWire, autoUpdate) // this one should be in GxsFeedItem -{ - mPulse.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded - - QVector v; - //bool self = false; - - for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) - v.push_back(*it) ; - - if(older_versions.find(messageId) == older_versions.end()) - v.push_back(messageId); - - setMessageVersions(v) ; - setup(); - - loadGroup(); -} - -void WireNotifyPostItem::paintEvent(QPaintEvent *e) -{ - /* This method employs a trick to trigger a deferred loading. The post and group is requested only - * when actually displayed on the screen. */ - - if(!mLoaded) - { - mLoaded = true ; - - std::set older_versions; // not so nice. We need to use std::set everywhere - for(auto& m:messageVersions()) - older_versions.insert(m); - - fill(); - requestMessage(); - requestComment(); - } - - GxsFeedItem::paintEvent(e) ; -} - -WireNotifyPostItem::~WireNotifyPostItem() -{ - auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(300); - - while( (mLoadingGroup || mLoadingMessage || mLoadingComment) - && std::chrono::steady_clock::now() < timeout) - { - RsDbg() << __PRETTY_FUNCTION__ << " is Waiting for " - << (mLoadingGroup ? "Group " : "") - << (mLoadingMessage ? "Message " : "") - << (mLoadingComment ? "Comment " : "") - << "loading." << std::endl; - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } - - delete ui; -} - -bool WireNotifyPostItem::isUnread() const -{ - return IS_MSG_UNREAD(mPulse.mMeta.mMsgStatus) ; -} - -void WireNotifyPostItem::setup() -{ - /* Invoke the Qt Designer generated object setup routine */ - - ui = new Ui::WireNotifyPostItem; - ui->setupUi(this); - - // Manually set icons to allow to use clever resource sharing that is missing in Qt for Icons loaded from Qt resource file. - // This is particularly important here because a wire may contain many posts, so duplicating the QImages here is deadly for the - // memory. - -// ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/thumb-default-video.png")); - //ui->warn_image_label->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/status_unknown.png")); - ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); -// ui->voteUpButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/vote_up.png")); -// ui->voteDownButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/vote_down.png")); -// ui->downloadButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/download.png")); -// ui->playButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/play.png")); - ui->commentButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/comment.png")); - //ui->editButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/pencil-edit-button.png")); -// ui->copyLinkButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/copy.png")); -// ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/down-arrow.png")); -// ui->readAndClearButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/correct.png")); -// ui->clearButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/exit2.png")); - - setAttribute(Qt::WA_DeleteOnClose, true); - - mInFill = false; - mCloseOnRead = false; - mLoaded = false; - - /* clear ui */ - ui->titleLabel->setText(tr("Loading...")); - ui->titleLabel->setOpenExternalLinks(false); //To get linkActivated working - connect(ui->titleLabel, SIGNAL(linkActivated(QString)), this, SLOT(on_linkActivated(QString))); - ui->datetimelabel->clear(); - ui->filelabel->clear(); -// ui->newCommentLabel->hide(); -// ui->commLabel->hide(); - - /* general ones */ - connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(toggle())); - connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(removeItem())); - - /* specific */ - connect(ui->readAndClearButton, SIGNAL(clicked()), this, SLOT(readAndClearItem())); - connect(ui->unsubscribeButton, SIGNAL(clicked()), this, SLOT(unsubscribeChannel())); - - connect(ui->downloadButton, SIGNAL(clicked()), this, SLOT(download())); - // HACK FOR NOW. - ui->commentButton->hide();// hidden until properly enabled. - connect(ui->commentButton, SIGNAL(clicked()), this, SLOT(loadComments())); - - connect(ui->playButton, SIGNAL(clicked()), this, SLOT(play(void))); - //connect(ui->editButton, SIGNAL(clicked()), this, SLOT(edit(void))); - connect(ui->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyMessageLink())); - - connect(ui->readButton, SIGNAL(toggled(bool)), this, SLOT(readToggled(bool))); - - // hide voting buttons, backend is not implemented yet - ui->voteUpButton->hide(); - ui->voteDownButton->hide(); - //connect(ui-> voteUpButton, SIGNAL(clicked()), this, SLOT(makeUpVote())); - //connect(ui->voteDownButton, SIGNAL(clicked()), this, SLOT(makeDownVote())); - - ui->scoreLabel->hide(); - - // hide unsubscribe button not necessary - ui->unsubscribeButton->hide(); - - ui->downloadButton->hide(); - ui->playButton->hide(); - //ui->warn_image_label->hide(); - //ui->warning_label->hide(); - - ui->titleLabel->setMinimumWidth(100); - ui->subjectLabel->setMinimumWidth(100); - //ui->warning_label->setMinimumWidth(100); - - ui->feedFrame->setProperty("new", false); - ui->feedFrame->style()->unpolish(ui->feedFrame); - ui->feedFrame->style()->polish( ui->feedFrame); - - ui->expandFrame->hide(); -} - -bool WireNotifyPostItem::setPost(const RsWirePulse &pulse, bool doFill) -{ - if (groupId() != pulse.mMeta.mGroupId || messageId() != pulse.mMeta.mMsgId) { - std::cerr << "WireNotifyPostItem::setPost() - Wrong id, cannot set post"; - std::cerr << std::endl; - return false; - } - - mPulse = pulse; - - if (doFill) { - fill(); - std::cout<<"filling needs to be implemented"<getWirePulse(grpId, msgId, pPulse)) - { - RsErr() << "WireNotifyPostItem::loadMessage() ERROR getting pulse" << std::endl; - RsQThreadUtils::postToObject([this]() - { - mLoadingMessage = false; - }, this); - return; - } - - if (pPulse) - { -#ifdef DEBUG_ITEM - std::cerr << (void*)this << ": Obtained post, with msgId = " << pPulse->mMeta.mMsgId << std::endl; -#endif - const RsWirePulse pulse(*pPulse); - - RsQThreadUtils::postToObject([pulse, this]() - { - setPost(pulse); - mLoadingMessage = false; - }, this); - } - else - { - RsQThreadUtils::postToObject([this]() - { - mLoadingMessage = false; - }, this); - } - }); -} - -void WireNotifyPostItem::loadComment() -{ -#ifdef DEBUG_ITEM - std::cerr << "WireNotifyPostItem::loadComment()"; - std::cerr << std::endl; -#endif -// mLoadingComment = true; - -// RsThread::async([this]() -// { -// // 1 - get group data - -// std::set msgIds; - -// for(auto MsgId: messageVersions()) -// msgIds.insert(MsgId); - -// std::vector posts; -// std::vector comments; - -// if(! rsGxsChannels->getChannelComments( groupId(),msgIds,comments)) -// { -// RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; -// return; -// } - -// int comNb = comments.size(); - -// RsQThreadUtils::postToObject( [comNb,this]() -// { -// 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); -// mLoadingComment = false; - -// }, this ); -// }); -} - -void WireNotifyPostItem::loadGroup() -{ -#ifdef DEBUG_ITEM - std::cerr << "WireNotifyGroupItem::loadGroup()"; - std::cerr << std::endl; -#endif - mLoadingGroup = true; - - RsThread::async([this]() - { - // 1 - get group data - -// std::vector groups; -// std::list> groups; - const std::list groupIds = { groupId() }; - std::vector groups; - if(!rsWire->getGroups(groupIds,groups)) // would be better to call channel Summaries for a single group - { - RsErr() << "WireNotifyPostItem::loadGroup() ERROR getting data" << std::endl; - return; - } - - if (groups.size() != 1) - { - std::cerr << "WireNotifyPostItem::loadGroup() Wrong number of Items"; - std::cerr << std::endl; - return; - } - RsWireGroup group = groups[0]; - - RsQThreadUtils::postToObject( [group,this]() - { - /* Here it goes any code you want to be executed on the Qt Gui - * thread, for example to update the data model with new information - * after a blocking call to RetroShare API complete */ - - mGroupMeta = group.mMeta; - mLoadingGroup = false; - setGroup(group); - - }, this ); - }); -} - -//void WireNotifyPostItem::updateItem() -//{ -// /* fill in */ - -//#ifdef DEBUG_ITEM -// std::cerr << "WireNotifyPostItem::updateItem()"; -// std::cerr << std::endl; -//#endif - -// int msec_rate = 10000; - -// int downloadCount = 0; -// int downloadStartable = 0; -// int playCount = 0; -// int playStartable = 0; -// bool startable; -// bool loopAgain = false; - -// /* Very slow Tick to check when all files are downloaded */ -// std::list::iterator it; -// for(it = mFileItems.begin(); it != mFileItems.end(); ++it) -// { -// SubFileItem *item = *it; - -// if (item->isDownloadable(startable)) { -// ++downloadCount; -// if (startable) { -// ++downloadStartable; -// } -// } -// if (item->isPlayable(startable)) { -// ++playCount; -// if (startable) { -// ++playStartable; -// } -// } - -// if (!item->done()) -// { -// /* loop again */ -// loopAgain = true; -// } -// } - -// if (downloadCount) { -// ui->downloadButton->show(); - -// if (downloadStartable) { -// ui->downloadButton->setEnabled(true); -// } else { -// ui->downloadButton->setEnabled(false); -// } -// } else { -// ui->downloadButton->hide(); -// } -// if (playCount) { -// /* one file is playable */ -// ui->playButton->show(); - -// if (playStartable == 1) { -// ui->playButton->setEnabled(true); -// } else { -// ui->playButton->setEnabled(false); -// } -// } else { -// ui->playButton->hide(); -// } - -// if (loopAgain) { -// QTimer::singleShot( msec_rate, this, SLOT(updateItem(void))); -// } - -// // HACK TO DISPLAY COMMENT BUTTON FOR NOW. -// //downloadButton->show(); -// //downloadButton->setEnabled(true); -//} - -QString WireNotifyPostItem::groupName() -{ - return QString::fromUtf8(mGroupMeta.mGroupName.c_str()); -} - -void WireNotifyPostItem::doExpand(bool open) -{ - if (mFeedHolder) - { - mFeedHolder->lockLayout(this, true); - } - - if (open) - { - ui->expandFrame->show(); - ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/up-arrow.png"))); - ui->expandButton->setToolTip(tr("Hide")); - -// readToggled(false); - } - else - { - ui->expandFrame->hide(); - ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/down-arrow.png"))); - ui->expandButton->setToolTip(tr("Expand")); - } - - emit sizeChanged(this); - - if (mFeedHolder) - { - mFeedHolder->lockLayout(this, false); - } -} - -void WireNotifyPostItem::fill() -{ - /* fill in */ - -// if (isLoading()) { - // /* Wait for all requests */ - //return; -// } - -#ifdef DEBUG_ITEM - std::cerr << "WireNotifyPostItem::fill()"; - std::cerr << std::endl; -#endif - - std::cout<<"*************************************************filling************************************"<subjectLabel->setText(msgText); - - ui->pulseMessage->setText(QString::fromUtf8(mPulse.mPulseText.c_str())); - ui->datetimelabel->setText(DateTime::formatLongDateTime(mPulse.mRefPublishTs)); - - if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) - { - ui->unsubscribeButton->setEnabled(true); - } - else - { - ui->unsubscribeButton->setEnabled(false); - } - ui->readButton->hide(); - ui->newLabel->hide(); - ui->copyLinkButton->hide(); - - if (IS_MSG_NEW(mPulse.mMeta.mMsgStatus)) { - mCloseOnRead = true; - } - } - else - { - - /* disable buttons: deletion facility not enabled with cache services yet */ - ui->clearButton->setEnabled(false); - ui->unsubscribeButton->setEnabled(false); - ui->clearButton->hide(); - ui->readAndClearButton->hide(); - ui->unsubscribeButton->hide(); - ui->copyLinkButton->show(); - - if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) - { - ui->readButton->setVisible(true); - - setReadStatus(IS_MSG_NEW(mPulse.mMeta.mMsgStatus), IS_MSG_UNREAD(mPulse.mMeta.mMsgStatus) || IS_MSG_NEW(mPulse.mMeta.mMsgStatus)); - } - else - { - ui->readButton->setVisible(false); - ui->newLabel->setVisible(false); - } - - mCloseOnRead = false; - } - - // differences between Feed or Top of Comment. - if (mFeedHolder) - { - if (mIsHome) { - ui->commentButton->show(); - } else if (ui->commentButton->icon().isNull()){ - //Icon is seted if a comment received. - ui->commentButton->hide(); - } - -// THIS CODE IS doesn't compile - disabling until fixed. -#if 0 - if (post.mComments) - { - QString commentText = QString::number(post.mComments); - commentText += " "; - commentText += tr("Comments"); - ui->commentButton->setText(commentText); - } - else - { - ui->commentButton->setText(tr("Comment")); - } -#endif - - } - else - { - ui->commentButton->hide(); - } - - // disable voting buttons - if they have already voted. - /*if (post.mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) - { - voteUpButton->setEnabled(false); - voteDownButton->setEnabled(false); - }*/ - -// { -// QTextDocument doc; -// doc.setHtml( QString::fromUtf8(mPulse.mMsg.c_str()) ); - -// ui->msgFrame->setVisible(doc.toPlainText().length() > 0); -// } - -// if (wasExpanded() || ui->expandFrame->isVisible()) { -// fillExpandFrame(); -// } - -// if ( (mPulse.mAttachmentCount != 0) || (mPulse.mSize != 0) ) { -// ui->filelabel->setVisible(true); -// ui->filelabel->setText(QString("(%1 %2) %3").arg(mPulse.mAttachmentCount).arg( (mPulse.mAttachmentCount > 1)?tr("Files"):tr("File")).arg(misc::friendlyUnit(mPulse.mSize))); -// } else { -// ui->filelabel->setVisible(false); -// } - -// if (mFileItems.empty() == false) { -// std::list::iterator it; -// for(it = mFileItems.begin(); it != mFileItems.end(); ++it) -// { -// delete(*it); -// } -// mFileItems.clear(); -// } - -// std::list::const_iterator it; -// for(it = mPulse.mFiles.begin(); it != mPulse.mFiles.end(); ++it) -// { -// /* add file */ -// std::string path; -// SubFileItem *fi = new SubFileItem(it->mHash, it->mName, path, it->mSize, SFI_STATE_REMOTE | SFI_TYPE_CHANNEL, RsPeerId()); -// mFileItems.push_back(fi); - -// /* check if the file is a media file */ -// if (!misc::isPreviewable(QFileInfo(QString::fromUtf8(it->mName.c_str())).suffix())) -// { -// fi->mediatype(); -// /* check if the file is not a media file and change text */ -// ui->playButton->setText(tr("Open")); -// ui->playButton->setToolTip(tr("Open File")); -// } else { -// ui->playButton->setText(tr("Play")); -// ui->playButton->setToolTip(tr("Play Media")); -// } - -// QLayout *layout = ui->expandFrame->layout(); -// layout->addWidget(fi); -// } - - mInFill = false; -} - -void WireNotifyPostItem::setReadStatus(bool isNew, bool isUnread) -{ - if (isNew) - mPulse.mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_NEW; - else - mPulse.mMeta.mMsgStatus &= ~GXS_SERV::GXS_MSG_STATUS_GUI_NEW; - - if (isUnread) - { - mPulse.mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - whileBlocking(ui->readButton)->setChecked(true); - ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); - } - else - { - mPulse.mMeta.mMsgStatus &= ~GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - whileBlocking(ui->readButton)->setChecked(false); - ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-read.png")); - } - - //ui->newLabel->setVisible(isNew); - - //ui->feedFrame->setProperty("new", isNew); - //ui->feedFrame->style()->unpolish(ui->feedFrame); - //ui->feedFrame->style()->polish( ui->feedFrame); -} - -void WireNotifyPostItem::setGroup(const RsWireGroup &group) -{ - ui->groupName->setText(QString::fromStdString(group.mMeta.mGroupName)); - ui->groupName->setToolTip(QString::fromStdString(group.mMeta.mGroupName) + "@" + QString::fromStdString(group.mMeta.mAuthorId.toStdString())); - - QString title; - - title = tr("Wire Feed") + ": "; - RetroShareLink link = RetroShareLink::createGxsGroupLink(RetroShareLink::TYPE_WIRE, group.mMeta.mGroupId, groupName()); - title += link.toHtml(); - ui->titleLabel->setText(title); - - if (group.mHeadshot.mData ) - { - QPixmap pixmap; - if (GxsIdDetails::loadPixmapFromData( - group.mHeadshot.mData, - group.mHeadshot.mSize, - pixmap,GxsIdDetails::ORIGINAL)) - { - ui->logoLabel->setPixmap(pixmap); - } - } - else - { - // default. - QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png"); - ui->logoLabel->setPixmap(pixmap); - } - -} - -/*********** SPECIFIC FUNCTIONS ***********************/ - -void WireNotifyPostItem::readAndClearItem() -{ -#ifdef DEBUG_ITEM - std::cerr << "WireNotifyPostItem::readAndClearItem()"; - std::cerr << std::endl; -#endif - readToggled(false); - removeItem(); -} - -void WireNotifyPostItem::readToggled(bool /*checked*/) -{ - if (mInFill) { - return; - } - - mCloseOnRead = false; - - RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); - - //rsWire->setMessageReadStatus(msgPair, isUnread()); - - //setReadStatus(false, checked); // Updated by events -} - -void WireNotifyPostItem::on_linkActivated(QString link) -{ - RetroShareLink rsLink(link); - - if (rsLink.valid() ) { - QList rsLinks; - rsLinks.append(rsLink); - RetroShareLink::process(rsLinks); - removeItem(); - return; - } -} +/******************************************************************************* + * gui/feeds/WireNotifyPostItem.cpp * + * * + * Copyright (c) 2012, Robert Fernie * + * * + * 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 "WireNotifyPostItem.h" +#include "ui_WireNotifyPostItem.h" + +#include "FeedHolder.h" +#include "util/qtthreadsutils.h" +#include "gui/RetroShareLink.h" +#include "gui/common/FilesDefs.h" +#include "gui/gxs/GxsIdDetails.h" +#include "util/stringutil.h" +#include "util/DateTime.h" +#include "util/misc.h" + +#include +#include + +WireNotifyPostItem::WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGroupMetaData& group_meta, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate,const std::set& older_versions) : + GxsFeedItem(feedHolder, feedId, group_meta.mGroupId, messageId, isHome, rsWire, autoUpdate), + mGroupMeta(group_meta) +{ + mLoadingGroup = false; + mLoadingMessage = false; + mLoadingComment = false; + + mPulse.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded + mPulse.mMeta.mGroupId = mGroupMeta.mGroupId; + + QVector v; + //bool self = false; + + for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) + v.push_back(*it) ; + + if(older_versions.find(messageId) == older_versions.end()) + v.push_back(messageId); + + setMessageVersions(v) ; + setup(); + + // no call to loadGroup() here because we have it already. +} + +WireNotifyPostItem::WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set &older_versions) : + GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsWire, autoUpdate) // this one should be in GxsFeedItem +{ + mPulse.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded + + QVector v; + //bool self = false; + + for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) + v.push_back(*it) ; + + if(older_versions.find(messageId) == older_versions.end()) + v.push_back(messageId); + + setMessageVersions(v) ; + setup(); + + loadGroup(); +} + +void WireNotifyPostItem::paintEvent(QPaintEvent *e) +{ + /* This method employs a trick to trigger a deferred loading. The post and group is requested only + * when actually displayed on the screen. */ + + if(!mLoaded) + { + mLoaded = true ; + + std::set older_versions; // not so nice. We need to use std::set everywhere + for(auto& m:messageVersions()) + older_versions.insert(m); + + fill(); + requestMessage(); + requestComment(); + } + + GxsFeedItem::paintEvent(e) ; +} + +WireNotifyPostItem::~WireNotifyPostItem() +{ + auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(300); + + while( (mLoadingGroup || mLoadingMessage || mLoadingComment) + && std::chrono::steady_clock::now() < timeout) + { + RsDbg() << __PRETTY_FUNCTION__ << " is Waiting for " + << (mLoadingGroup ? "Group " : "") + << (mLoadingMessage ? "Message " : "") + << (mLoadingComment ? "Comment " : "") + << "loading." << std::endl; + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + + delete ui; +} + +bool WireNotifyPostItem::isUnread() const +{ + return IS_MSG_UNREAD(mPulse.mMeta.mMsgStatus) ; +} + +void WireNotifyPostItem::setup() +{ + /* Invoke the Qt Designer generated object setup routine */ + + ui = new Ui::WireNotifyPostItem; + ui->setupUi(this); + + // Manually set icons to allow to use clever resource sharing that is missing in Qt for Icons loaded from Qt resource file. + // This is particularly important here because a wire may contain many posts, so duplicating the QImages here is deadly for the + // memory. + +// ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/thumb-default-video.png")); + //ui->warn_image_label->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/status_unknown.png")); + ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); +// ui->voteUpButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/vote_up.png")); +// ui->voteDownButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/vote_down.png")); +// ui->downloadButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/download.png")); +// ui->playButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/play.png")); + ui->commentButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/comment.png")); + //ui->editButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/pencil-edit-button.png")); +// ui->copyLinkButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/copy.png")); +// ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/down-arrow.png")); +// ui->readAndClearButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/correct.png")); +// ui->clearButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/exit2.png")); + + setAttribute(Qt::WA_DeleteOnClose, true); + + mInFill = false; + mCloseOnRead = false; + mLoaded = false; + + /* clear ui */ + ui->titleLabel->setText(tr("Loading...")); + ui->titleLabel->setOpenExternalLinks(false); //To get linkActivated working + connect(ui->titleLabel, SIGNAL(linkActivated(QString)), this, SLOT(on_linkActivated(QString))); + ui->datetimelabel->clear(); + ui->filelabel->clear(); +// ui->newCommentLabel->hide(); +// ui->commLabel->hide(); + + /* general ones */ + connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(toggle())); + connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(removeItem())); + + /* specific */ + connect(ui->readAndClearButton, SIGNAL(clicked()), this, SLOT(readAndClearItem())); + connect(ui->unsubscribeButton, SIGNAL(clicked()), this, SLOT(unsubscribeChannel())); + + connect(ui->downloadButton, SIGNAL(clicked()), this, SLOT(download())); + // HACK FOR NOW. + ui->commentButton->hide();// hidden until properly enabled. + connect(ui->commentButton, SIGNAL(clicked()), this, SLOT(loadComments())); + + connect(ui->playButton, SIGNAL(clicked()), this, SLOT(play(void))); + //connect(ui->editButton, SIGNAL(clicked()), this, SLOT(edit(void))); + connect(ui->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyMessageLink())); + + connect(ui->readButton, SIGNAL(toggled(bool)), this, SLOT(readToggled(bool))); + + // hide voting buttons, backend is not implemented yet + ui->voteUpButton->hide(); + ui->voteDownButton->hide(); + //connect(ui-> voteUpButton, SIGNAL(clicked()), this, SLOT(makeUpVote())); + //connect(ui->voteDownButton, SIGNAL(clicked()), this, SLOT(makeDownVote())); + + ui->scoreLabel->hide(); + + // hide unsubscribe button not necessary + ui->unsubscribeButton->hide(); + + ui->downloadButton->hide(); + ui->playButton->hide(); + //ui->warn_image_label->hide(); + //ui->warning_label->hide(); + + ui->titleLabel->setMinimumWidth(100); + ui->subjectLabel->setMinimumWidth(100); + //ui->warning_label->setMinimumWidth(100); + + ui->feedFrame->setProperty("new", false); + ui->feedFrame->style()->unpolish(ui->feedFrame); + ui->feedFrame->style()->polish( ui->feedFrame); + + ui->expandFrame->hide(); +} + +bool WireNotifyPostItem::setPost(const RsWirePulse &pulse, bool doFill) +{ + if (groupId() != pulse.mMeta.mGroupId || messageId() != pulse.mMeta.mMsgId) { + std::cerr << "WireNotifyPostItem::setPost() - Wrong id, cannot set post"; + std::cerr << std::endl; + return false; + } + + mPulse = pulse; + + if (doFill) { + fill(); + std::cout<<"filling needs to be implemented"<getWirePulse(grpId, msgId, pPulse)) + { + RsErr() << "WireNotifyPostItem::loadMessage() ERROR getting pulse" << std::endl; + RsQThreadUtils::postToObject([this]() + { + mLoadingMessage = false; + }, this); + return; + } + + if (pPulse) + { +#ifdef DEBUG_ITEM + std::cerr << (void*)this << ": Obtained post, with msgId = " << pPulse->mMeta.mMsgId << std::endl; +#endif + const RsWirePulse pulse(*pPulse); + + RsQThreadUtils::postToObject([pulse, this]() + { + setPost(pulse); + mLoadingMessage = false; + }, this); + } + else + { + RsQThreadUtils::postToObject([this]() + { + mLoadingMessage = false; + }, this); + } + }); +} + +void WireNotifyPostItem::loadComment() +{ +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyPostItem::loadComment()"; + std::cerr << std::endl; +#endif +// mLoadingComment = true; + +// RsThread::async([this]() +// { +// // 1 - get group data + +// std::set msgIds; + +// for(auto MsgId: messageVersions()) +// msgIds.insert(MsgId); + +// std::vector posts; +// std::vector comments; + +// if(! rsGxsChannels->getChannelComments( groupId(),msgIds,comments)) +// { +// RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; +// return; +// } + +// int comNb = comments.size(); + +// RsQThreadUtils::postToObject( [comNb,this]() +// { +// 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); +// mLoadingComment = false; + +// }, this ); +// }); +} + +void WireNotifyPostItem::loadGroup() +{ +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyGroupItem::loadGroup()"; + std::cerr << std::endl; +#endif + mLoadingGroup = true; + + RsThread::async([this]() + { + // 1 - get group data + +// std::vector groups; +// std::list> groups; + const std::list groupIds = { groupId() }; + std::vector groups; + if(!rsWire->getGroups(groupIds,groups)) // would be better to call channel Summaries for a single group + { + RsErr() << "WireNotifyPostItem::loadGroup() ERROR getting data" << std::endl; + return; + } + + if (groups.size() != 1) + { + std::cerr << "WireNotifyPostItem::loadGroup() Wrong number of Items"; + std::cerr << std::endl; + return; + } + RsWireGroup group = groups[0]; + + RsQThreadUtils::postToObject( [group,this]() + { + /* Here it goes any code you want to be executed on the Qt Gui + * thread, for example to update the data model with new information + * after a blocking call to RetroShare API complete */ + + mGroupMeta = group.mMeta; + mLoadingGroup = false; + setGroup(group); + + }, this ); + }); +} + +//void WireNotifyPostItem::updateItem() +//{ +// /* fill in */ + +//#ifdef DEBUG_ITEM +// std::cerr << "WireNotifyPostItem::updateItem()"; +// std::cerr << std::endl; +//#endif + +// int msec_rate = 10000; + +// int downloadCount = 0; +// int downloadStartable = 0; +// int playCount = 0; +// int playStartable = 0; +// bool startable; +// bool loopAgain = false; + +// /* Very slow Tick to check when all files are downloaded */ +// std::list::iterator it; +// for(it = mFileItems.begin(); it != mFileItems.end(); ++it) +// { +// SubFileItem *item = *it; + +// if (item->isDownloadable(startable)) { +// ++downloadCount; +// if (startable) { +// ++downloadStartable; +// } +// } +// if (item->isPlayable(startable)) { +// ++playCount; +// if (startable) { +// ++playStartable; +// } +// } + +// if (!item->done()) +// { +// /* loop again */ +// loopAgain = true; +// } +// } + +// if (downloadCount) { +// ui->downloadButton->show(); + +// if (downloadStartable) { +// ui->downloadButton->setEnabled(true); +// } else { +// ui->downloadButton->setEnabled(false); +// } +// } else { +// ui->downloadButton->hide(); +// } +// if (playCount) { +// /* one file is playable */ +// ui->playButton->show(); + +// if (playStartable == 1) { +// ui->playButton->setEnabled(true); +// } else { +// ui->playButton->setEnabled(false); +// } +// } else { +// ui->playButton->hide(); +// } + +// if (loopAgain) { +// QTimer::singleShot( msec_rate, this, SLOT(updateItem(void))); +// } + +// // HACK TO DISPLAY COMMENT BUTTON FOR NOW. +// //downloadButton->show(); +// //downloadButton->setEnabled(true); +//} + +QString WireNotifyPostItem::groupName() +{ + return QString::fromUtf8(mGroupMeta.mGroupName.c_str()); +} + +void WireNotifyPostItem::doExpand(bool open) +{ + if (mFeedHolder) + { + mFeedHolder->lockLayout(this, true); + } + + if (open) + { + ui->expandFrame->show(); + ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/up-arrow.png"))); + ui->expandButton->setToolTip(tr("Hide")); + +// readToggled(false); + } + else + { + ui->expandFrame->hide(); + ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/down-arrow.png"))); + ui->expandButton->setToolTip(tr("Expand")); + } + + emit sizeChanged(this); + + if (mFeedHolder) + { + mFeedHolder->lockLayout(this, false); + } +} + +void WireNotifyPostItem::fill() +{ + /* fill in */ + +// if (isLoading()) { + // /* Wait for all requests */ + //return; +// } + +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyPostItem::fill()"; + std::cerr << std::endl; +#endif + + std::cout<<"*************************************************filling************************************"<subjectLabel->setText(msgText); + + ui->pulseMessage->setText(QString::fromUtf8(mPulse.mPulseText.c_str())); + ui->datetimelabel->setText(DateTime::formatLongDateTime(mPulse.mRefPublishTs)); + + if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) + { + ui->unsubscribeButton->setEnabled(true); + } + else + { + ui->unsubscribeButton->setEnabled(false); + } + ui->readButton->hide(); + ui->newLabel->hide(); + ui->copyLinkButton->hide(); + + if (IS_MSG_NEW(mPulse.mMeta.mMsgStatus)) { + mCloseOnRead = true; + } + } + else + { + + /* disable buttons: deletion facility not enabled with cache services yet */ + ui->clearButton->setEnabled(false); + ui->unsubscribeButton->setEnabled(false); + ui->clearButton->hide(); + ui->readAndClearButton->hide(); + ui->unsubscribeButton->hide(); + ui->copyLinkButton->show(); + + if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) + { + ui->readButton->setVisible(true); + + setReadStatus(IS_MSG_NEW(mPulse.mMeta.mMsgStatus), IS_MSG_UNREAD(mPulse.mMeta.mMsgStatus) || IS_MSG_NEW(mPulse.mMeta.mMsgStatus)); + } + else + { + ui->readButton->setVisible(false); + ui->newLabel->setVisible(false); + } + + mCloseOnRead = false; + } + + // differences between Feed or Top of Comment. + if (mFeedHolder) + { + if (mIsHome) { + ui->commentButton->show(); + } else if (ui->commentButton->icon().isNull()){ + //Icon is seted if a comment received. + ui->commentButton->hide(); + } + +// THIS CODE IS doesn't compile - disabling until fixed. +#if 0 + if (post.mComments) + { + QString commentText = QString::number(post.mComments); + commentText += " "; + commentText += tr("Comments"); + ui->commentButton->setText(commentText); + } + else + { + ui->commentButton->setText(tr("Comment")); + } +#endif + + } + else + { + ui->commentButton->hide(); + } + + // disable voting buttons - if they have already voted. + /*if (post.mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) + { + voteUpButton->setEnabled(false); + voteDownButton->setEnabled(false); + }*/ + +// { +// QTextDocument doc; +// doc.setHtml( QString::fromUtf8(mPulse.mMsg.c_str()) ); + +// ui->msgFrame->setVisible(doc.toPlainText().length() > 0); +// } + +// if (wasExpanded() || ui->expandFrame->isVisible()) { +// fillExpandFrame(); +// } + +// if ( (mPulse.mAttachmentCount != 0) || (mPulse.mSize != 0) ) { +// ui->filelabel->setVisible(true); +// ui->filelabel->setText(QString("(%1 %2) %3").arg(mPulse.mAttachmentCount).arg( (mPulse.mAttachmentCount > 1)?tr("Files"):tr("File")).arg(misc::friendlyUnit(mPulse.mSize))); +// } else { +// ui->filelabel->setVisible(false); +// } + +// if (mFileItems.empty() == false) { +// std::list::iterator it; +// for(it = mFileItems.begin(); it != mFileItems.end(); ++it) +// { +// delete(*it); +// } +// mFileItems.clear(); +// } + +// std::list::const_iterator it; +// for(it = mPulse.mFiles.begin(); it != mPulse.mFiles.end(); ++it) +// { +// /* add file */ +// std::string path; +// SubFileItem *fi = new SubFileItem(it->mHash, it->mName, path, it->mSize, SFI_STATE_REMOTE | SFI_TYPE_CHANNEL, RsPeerId()); +// mFileItems.push_back(fi); + +// /* check if the file is a media file */ +// if (!misc::isPreviewable(QFileInfo(QString::fromUtf8(it->mName.c_str())).suffix())) +// { +// fi->mediatype(); +// /* check if the file is not a media file and change text */ +// ui->playButton->setText(tr("Open")); +// ui->playButton->setToolTip(tr("Open File")); +// } else { +// ui->playButton->setText(tr("Play")); +// ui->playButton->setToolTip(tr("Play Media")); +// } + +// QLayout *layout = ui->expandFrame->layout(); +// layout->addWidget(fi); +// } + + mInFill = false; +} + +void WireNotifyPostItem::setReadStatus(bool isNew, bool isUnread) +{ + if (isNew) + mPulse.mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_NEW; + else + mPulse.mMeta.mMsgStatus &= ~GXS_SERV::GXS_MSG_STATUS_GUI_NEW; + + if (isUnread) + { + mPulse.mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; + whileBlocking(ui->readButton)->setChecked(true); + ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); + } + else + { + mPulse.mMeta.mMsgStatus &= ~GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; + whileBlocking(ui->readButton)->setChecked(false); + ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-read.png")); + } + + //ui->newLabel->setVisible(isNew); + + //ui->feedFrame->setProperty("new", isNew); + //ui->feedFrame->style()->unpolish(ui->feedFrame); + //ui->feedFrame->style()->polish( ui->feedFrame); +} + +void WireNotifyPostItem::setGroup(const RsWireGroup &group) +{ + ui->groupName->setText(QString::fromStdString(group.mMeta.mGroupName)); + ui->groupName->setToolTip(QString::fromStdString(group.mMeta.mGroupName) + "@" + QString::fromStdString(group.mMeta.mAuthorId.toStdString())); + ui->groupName->hide(); + + QString title; + + title = tr("Wire Feed") + ": "; + RetroShareLink link = RetroShareLink::createGxsGroupLink(RetroShareLink::TYPE_WIRE, group.mMeta.mGroupId, groupName()); + title += link.toHtml(); + ui->titleLabel->setText(title); + + if (group.mHeadshot.mData ) + { + QPixmap pixmap; + if (GxsIdDetails::loadPixmapFromData( + group.mHeadshot.mData, + group.mHeadshot.mSize, + pixmap,GxsIdDetails::ORIGINAL)) + { + ui->logoLabel->setPixmap(pixmap); + } + } + else + { + // default. + QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png"); + ui->logoLabel->setPixmap(pixmap); + } + +} + +/*********** SPECIFIC FUNCTIONS ***********************/ + +void WireNotifyPostItem::readAndClearItem() +{ +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyPostItem::readAndClearItem()"; + std::cerr << std::endl; +#endif + readToggled(false); + removeItem(); +} + +void WireNotifyPostItem::readToggled(bool /*checked*/) +{ + if (mInFill) { + return; + } + + mCloseOnRead = false; + + RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); + + //rsWire->setMessageReadStatus(msgPair, isUnread()); + + //setReadStatus(false, checked); // Updated by events +} + +void WireNotifyPostItem::on_linkActivated(QString link) +{ + RetroShareLink rsLink(link); + + if (rsLink.valid() ) { + QList rsLinks; + rsLinks.append(rsLink); + RetroShareLink::process(rsLinks); + removeItem(); + return; + } +} diff --git a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.ui b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.ui index 95bf55f45..46d2b5332 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.ui +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.ui @@ -1,492 +1,490 @@ - - - WireNotifyPostItem - - - - 0 - 0 - 822 - 175 - - - - - 1 - - - 1 - - - 1 - - - 1 - - - 6 - - - 1 - - - - - - 0 - 0 - - - - true - - - QFrame::Box - - - QFrame::Sunken - - - - - - - - - - - 70 - 70 - - - - - 70 - 70 - - - - TextLabel - - - - - - - Qt::Vertical - - - - 20 - 20 - - - - - - - - - - - - - - - 12 - 75 - true - true - - - - TextLabel - - - - - - - - 0 - 0 - - - - - 11 - 75 - true - true - - - - Wire Subject - - - false - - - true - - - - - - - - 75 - true - - - - DateTime - - - - - - - New - - - - - - - - - - 11 - - - - TextLabel - - - - - - - - 11 - 75 - false - true - - - - TextLabel - - - true - - - - - - - 8 - - - - - - 24 - 16777215 - - - - Qt::NoFocus - - - Toggle Message Read Status - - - true - - - false - - - false - - - - - - - - 75 - true - - - - 0 - - - - - - - I like this - - - - - - - - - - I dislike this - - - - - - - - - - Qt::NoFocus - - - Download - - - false - - - - - - - Qt::NoFocus - - - Play - - - - - - - Comments - - - - - - - fileLabel - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 0 - 0 - - - - Qt::NoFocus - - - Unsubscribe From Wire - - - Unsubscribe - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - Qt::NoFocus - - - Copy RetroShare Link - - - - - - - - 0 - 0 - - - - Qt::NoFocus - - - Expand - - - - :/icons/png/down-arrow.png:/icons/png/down-arrow.png - - - - - - - - 0 - 0 - - - - Qt::NoFocus - - - Set as read and remove item - - - - :/icons/png/correct.png:/icons/png/correct.png - - - - - - - - 0 - 0 - - - - Qt::NoFocus - - - Remove Item - - - - :/icons/png/exit2.png:/icons/png/exit2.png - - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - QFrame::Box - - - QFrame::Sunken - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - - 0 - 0 - - - - true - - - 6 - - - -1 - - - true - - - Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - - - - - - - Qt::Vertical - - - - 20 - 0 - - - - - - - - - - - - - - + + + WireNotifyPostItem + + + + 0 + 0 + 822 + 175 + + + + + 1 + + + 1 + + + 1 + + + 1 + + + 6 + + + 1 + + + + + + 0 + 0 + + + + true + + + QFrame::Shape::Box + + + QFrame::Shadow::Sunken + + + + + + + + + + + 70 + 70 + + + + + 70 + 70 + + + + TextLabel + + + true + + + + + + + Qt::Orientation::Vertical + + + + 20 + 20 + + + + + + + + + + + + + + + 12 + true + true + + + + TextLabel + + + + + + + + 0 + 0 + + + + + 11 + true + true + + + + Wire Subject + + + false + + + true + + + + + + + + true + + + + DateTime + + + + + + + New + + + + + + + + + + 11 + + + + TextLabel + + + + + + + + 11 + false + true + + + + TextLabel + + + true + + + + + + + 8 + + + + + + 24 + 16777215 + + + + Qt::FocusPolicy::NoFocus + + + Toggle Message Read Status + + + true + + + false + + + false + + + + + + + + true + + + + 0 + + + + + + + I like this + + + + + + + + + + I dislike this + + + + + + + + + + Qt::FocusPolicy::NoFocus + + + Download + + + false + + + + + + + Qt::FocusPolicy::NoFocus + + + Play + + + + + + + Comments + + + + + + + fileLabel + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + + + + 0 + 0 + + + + Qt::FocusPolicy::NoFocus + + + Unsubscribe From Wire + + + Unsubscribe + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Qt::FocusPolicy::NoFocus + + + Copy RetroShare Link + + + + + + + + 0 + 0 + + + + Qt::FocusPolicy::NoFocus + + + Expand + + + + :/icons/png/down-arrow.png:/icons/png/down-arrow.png + + + + + + + + 0 + 0 + + + + Qt::FocusPolicy::NoFocus + + + Set as read and remove item + + + + :/icons/png/correct.png:/icons/png/correct.png + + + + + + + + 0 + 0 + + + + Qt::FocusPolicy::NoFocus + + + Remove Item + + + + :/icons/png/exit2.png:/icons/png/exit2.png + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::Shape::Box + + + QFrame::Shadow::Sunken + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + 0 + 0 + + + + true + + + 6 + + + -1 + + + true + + + Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByKeyboard|Qt::TextInteractionFlag::TextSelectableByMouse + + + + + + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 0 + + + + + + + + + + + + + + From e65ae170f58f8e62de2a2920d92b63a43d4cba77 Mon Sep 17 00:00:00 2001 From: saurabh Date: Wed, 4 Feb 2026 00:15:46 +0530 Subject: [PATCH 10/13] Wire: Add filter menu, event labels, and UI improvements - Add filter menu button with Sort by Ascending toggle and time filters - Show COPY LINK button for own profile (ADMIN) and reposition to header - Add event-based labels: "Now Following", "Wire Updated", "New Wire" - Add pulse type labels: "New Like", "New Republish", "New Reply" --- retroshare-gui/src/gui/NewsFeed.cpp | 6 +-- .../src/gui/TheWire/PulseViewGroup.cpp | 7 ++- .../src/gui/TheWire/PulseViewGroup.ui | 42 +++++++++--------- retroshare-gui/src/gui/TheWire/WireDialog.cpp | 44 ++++++++++++++++++- retroshare-gui/src/gui/TheWire/WireDialog.h | 8 ++++ retroshare-gui/src/gui/TheWire/WireDialog.ui | 14 ++++++ .../src/gui/feeds/WireNotifyGroupItem.cpp | 30 ++++++++----- .../src/gui/feeds/WireNotifyGroupItem.h | 5 ++- .../src/gui/feeds/WireNotifyPostItem.cpp | 28 +++++++++++- 9 files changed, 142 insertions(+), 42 deletions(-) diff --git a/retroshare-gui/src/gui/NewsFeed.cpp b/retroshare-gui/src/gui/NewsFeed.cpp index ebfd0d81e..77b54f453 100644 --- a/retroshare-gui/src/gui/NewsFeed.cpp +++ b/retroshare-gui/src/gui/NewsFeed.cpp @@ -523,10 +523,10 @@ void NewsFeed::handleWireEvent(std::shared_ptr event) switch(pe->mWireEventCode) { case RsWireEventCode::FOLLOW_STATUS_CHANGED: - addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true)); + addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true, RsWireEventCode::FOLLOW_STATUS_CHANGED)); break; case RsWireEventCode::NEW_WIRE: - addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true)); + addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true, RsWireEventCode::NEW_WIRE)); break; case RsWireEventCode::NEW_POST: addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); @@ -541,7 +541,7 @@ void NewsFeed::handleWireEvent(std::shared_ptr event) addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); break; case RsWireEventCode::WIRE_UPDATED: - addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true)); + addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true, RsWireEventCode::WIRE_UPDATED)); break; // case RsWireEventCode::POST_UPDATED: // addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true)); diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp b/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp index f2b8df7db..f962daaeb 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp @@ -120,8 +120,8 @@ void PulseViewGroup::setup() label_extra_likes->setText(BoldString(ToNumberUnits(likes))); // label_extra_following->setText(BoldString(ToNumberUnits(following))); // TODO: enable when mGroupFollowing added - // hide follow. - widget_actions->setVisible(false); + // hide follow button but keep copy link visible. + followButton->setVisible(false); } else { @@ -137,14 +137,17 @@ void PulseViewGroup::setGroupSet() { if (mGroup->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_ADMIN) { editButton->show(); + toolButton_copyProfileLink->show(); } else if (mGroup->mMeta.mSubscribeFlags & GXS_SERV::GROUP_SUBSCRIBE_SUBSCRIBED) { editButton->hide(); + toolButton_copyProfileLink->show(); } else { editButton->hide(); + toolButton_copyProfileLink->show(); } } diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui b/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui index 8e389af5c..caf6533ff 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui @@ -222,6 +222,27 @@ + + + + + 10 + 75 + true + + + + COPY LINK + + + + :/images/link.svg:/images/link.svg + + + Qt::ToolButtonTextBesideIcon + + + @@ -595,27 +616,6 @@ - - - - - 12 - 75 - true - - - - COPY LINK - - - - :/images/link.svg:/images/link.svg - - - Qt::ToolButtonTextBesideIcon - - - diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.cpp b/retroshare-gui/src/gui/TheWire/WireDialog.cpp index a26cf3929..67f698994 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireDialog.cpp @@ -44,6 +44,7 @@ #include #include +#include /**************************************************************** * TheWire Display Widget. @@ -66,7 +67,7 @@ WireDialog::WireDialog(QWidget *parent) : GxsStatisticsProvider(rsWire, settingsGroupName(),parent, true), mGroupSet(GROUP_SET_ALL) , mAddDialog(nullptr), mGroupSelected(nullptr), mWireQueue(nullptr) - , mHistoryIndex(-1), mEventHandlerId(0) + , mHistoryIndex(-1), mEventHandlerId(0), mSortAscending(false) { ui.setupUi(this); @@ -85,6 +86,21 @@ WireDialog::WireDialog(QWidget *parent) ui.toolButton_back->setEnabled(false); ui.toolButton_forward->setEnabled(false); + // Setup filter menu + QMenu *filterMenu = new QMenu(this); + QAction *sortAscAction = filterMenu->addAction(tr("Sort by Ascending")); + sortAscAction->setCheckable(true); + sortAscAction->setChecked(mSortAscending); + connect(sortAscAction, SIGNAL(triggered()), this, SLOT(toggleSortAscending())); + + QMenu *filterTimeMenu = filterMenu->addMenu(tr("Filter by time")); + filterTimeMenu->addAction(tr("All Time"), this, SLOT(setFilterTimeAllTime())); + filterTimeMenu->addAction(tr("Last 24 hours"), this, SLOT(setFilterTimeLast24Hours())); + filterTimeMenu->addAction(tr("Last 7 days"), this, SLOT(setFilterTimeLast7Days())); + filterTimeMenu->addAction(tr("Last 30 days"), this, SLOT(setFilterTimeLast30Days())); + + ui.toolButton_filter->setMenu(filterMenu); + QTimer *timer = new QTimer(this); timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); timer->start(1000); @@ -597,6 +613,32 @@ void WireDialog::selectFilterTime(int index) showSelectedGroups(); } +void WireDialog::toggleSortAscending() +{ + mSortAscending = !mSortAscending; + showSelectedGroups(); +} + +void WireDialog::setFilterTimeAllTime() +{ + ui.comboBox_filterTime->setCurrentIndex(0); +} + +void WireDialog::setFilterTimeLast24Hours() +{ + ui.comboBox_filterTime->setCurrentIndex(1); +} + +void WireDialog::setFilterTimeLast7Days() +{ + ui.comboBox_filterTime->setCurrentIndex(2); +} + +void WireDialog::setFilterTimeLast30Days() +{ + ui.comboBox_filterTime->setCurrentIndex(3); +} + void WireDialog::showSelectedGroups() { ui.comboBox_filterTime->setEnabled(false); diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.h b/retroshare-gui/src/gui/TheWire/WireDialog.h index 598b79ec4..b2e385847 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.h +++ b/retroshare-gui/src/gui/TheWire/WireDialog.h @@ -140,6 +140,13 @@ private slots: void selectGroupSet(int index); void selectFilterTime(int index); + // Filter menu actions + void toggleSortAscending(); + void setFilterTimeAllTime(); + void setFilterTimeLast24Hours(); + void setFilterTimeLast7Days(); + void setFilterTimeLast30Days(); + // history navigation. void back(); void forward(); @@ -186,6 +193,7 @@ private: int32_t mHistoryIndex; std::vector mHistory; + bool mSortAscending; // pending navigation (for when navigate called before groups loaded) RsGxsGroupId mNavigatePendingGroupId; diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.ui b/retroshare-gui/src/gui/TheWire/WireDialog.ui index 6e678774b..8c7426248 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.ui +++ b/retroshare-gui/src/gui/TheWire/WireDialog.ui @@ -303,6 +303,20 @@ + + + + + + + + :/icons/mail/filter24.png:/icons/mail/filter24.png + + + QToolButton::InstantPopup + + + diff --git a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp index 0eeecf46c..44d145066 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp +++ b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp @@ -34,16 +34,18 @@ * #define DEBUG_ITEM 1 ****/ -WireNotifyGroupItem::WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, bool autoUpdate) : - GxsGroupFeedItem(feedHolder, feedId, groupId, isHome, rsWire, autoUpdate) +WireNotifyGroupItem::WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, bool autoUpdate, RsWireEventCode eventCode) : + GxsGroupFeedItem(feedHolder, feedId, groupId, isHome, rsWire, autoUpdate), + mEventCode(eventCode) { setup(); requestGroup(); addEventHandler(); } -WireNotifyGroupItem::WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate) : - GxsGroupFeedItem(feedHolder, feedId, group.mMeta.mGroupId, isHome, rsWire, autoUpdate) +WireNotifyGroupItem::WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate, RsWireEventCode eventCode) : + GxsGroupFeedItem(feedHolder, feedId, group.mMeta.mGroupId, isHome, rsWire, autoUpdate), + mEventCode(eventCode) { setup(); setGroup(group); @@ -204,14 +206,20 @@ void WireNotifyGroupItem::fill() else ui->infoLastPost->setText(DateTime::formatLongDateTime(mGroup.mMeta.mLastPost)); -// if (mIsNew) -// { + // Set title based on event type + switch(mEventCode) + { + case RsWireEventCode::FOLLOW_STATUS_CHANGED: + ui->titleLabel->setText(tr("Now Following")); + break; + case RsWireEventCode::WIRE_UPDATED: + ui->titleLabel->setText(tr("Wire Updated")); + break; + case RsWireEventCode::NEW_WIRE: + default: ui->titleLabel->setText(tr("New Wire")); -// } -// else -// { -// ui->titleLabel->setText(tr("Updated Wire")); -// } + break; + } if (mIsHome) { diff --git a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h index ed99c2618..d8b695d31 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h +++ b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h @@ -36,8 +36,8 @@ class WireNotifyGroupItem : public GxsGroupFeedItem public: /** Default Constructor */ - WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, bool autoUpdate); - WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate); + WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, bool autoUpdate, RsWireEventCode eventCode = RsWireEventCode::NEW_WIRE); + WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate, RsWireEventCode eventCode = RsWireEventCode::NEW_WIRE); ~WireNotifyGroupItem(); bool setGroup(const RsWireGroup &group); @@ -65,6 +65,7 @@ private: private: RsWireGroup mGroup; + RsWireEventCode mEventCode; /** Qt Designer generated object */ Ui::WireNotifyGroupItem *ui; diff --git a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp index 09d8a9727..238173fb9 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp @@ -515,13 +515,25 @@ void WireNotifyPostItem::fill() QString title; QString msgText; + // Determine pulse type for display + QString pulseTypeStr; + if (mPulse.mPulseType & WIRE_PULSE_TYPE_LIKE) { + pulseTypeStr = tr("Like"); + } else if (mPulse.mPulseType & WIRE_PULSE_TYPE_REPUBLISH) { + pulseTypeStr = tr("Republish"); + } else if (mPulse.mPulseType & WIRE_PULSE_TYPE_REPLY) { + pulseTypeStr = tr("Reply"); + } else { + pulseTypeStr = tr("Pulse"); + } + if (!mIsHome) { if (mCloseOnRead && !IS_MSG_NEW(mPulse.mMeta.mMsgStatus)) { removeItem(); } - msgText = tr("Pulse") + ": "; + msgText = pulseTypeStr + ": "; RetroShareLink msgLink = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_WIRE, mPulse.mMeta.mGroupId, mPulse.mMeta.mMsgId, messageName()); msgText += msgLink.toHtml(); ui->subjectLabel->setText(msgText); @@ -698,7 +710,19 @@ void WireNotifyPostItem::setGroup(const RsWireGroup &group) QString title; - title = tr("Wire Feed") + ": "; + // Determine pulse type for title + QString pulseTypeStr; + if (mPulse.mPulseType & WIRE_PULSE_TYPE_LIKE) { + pulseTypeStr = tr("New Like"); + } else if (mPulse.mPulseType & WIRE_PULSE_TYPE_REPUBLISH) { + pulseTypeStr = tr("New Republish"); + } else if (mPulse.mPulseType & WIRE_PULSE_TYPE_REPLY) { + pulseTypeStr = tr("New Reply"); + } else { + pulseTypeStr = tr("Wire Feed"); + } + + title = pulseTypeStr + ": "; RetroShareLink link = RetroShareLink::createGxsGroupLink(RetroShareLink::TYPE_WIRE, group.mMeta.mGroupId, groupName()); title += link.toHtml(); ui->titleLabel->setText(title); From 7acaccb5812153d4ff65bcef747f2bc3bbc9a19c Mon Sep 17 00:00:00 2001 From: saurabh Date: Wed, 4 Feb 2026 15:17:58 +0530 Subject: [PATCH 11/13] Wire: Remove commented hide line for groupSet comboBox --- retroshare-gui/src/gui/TheWire/WireDialog.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.cpp b/retroshare-gui/src/gui/TheWire/WireDialog.cpp index 67f698994..564970664 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireDialog.cpp @@ -79,7 +79,6 @@ WireDialog::WireDialog(QWidget *parent) connect(ui.comboBox_groupSet, SIGNAL(currentIndexChanged(int)), this, SLOT(selectGroupSet(int))); connect(ui.comboBox_filterTime, SIGNAL(currentIndexChanged(int)), this, SLOT(selectFilterTime(int))); - // ui.comboBox_groupSet->hide(); // <--- Re-enabled for testing as requested connect( ui.toolButton_back, SIGNAL(clicked()), this, SLOT(back())); connect( ui.toolButton_forward, SIGNAL(clicked()), this, SLOT(forward())); From 167bcfefa797966c3226bbaf2904887b6905c49c Mon Sep 17 00:00:00 2001 From: saurabh Date: Sun, 8 Feb 2026 23:51:32 +0530 Subject: [PATCH 12/13] Wire: Add account filter menu and update filter UI --- retroshare-gui/src/gui/NewsFeed.cpp | 18 +-- retroshare-gui/src/gui/TheWire/WireDialog.cpp | 129 +++++++++++------- retroshare-gui/src/gui/TheWire/WireDialog.h | 10 +- retroshare-gui/src/gui/TheWire/WireDialog.ui | 71 ++++++---- .../src/gui/feeds/WireNotifyPostItem.cpp | 2 - retroshare-gui/src/gui/feeds/WirePostItem.cpp | 2 - 6 files changed, 139 insertions(+), 93 deletions(-) diff --git a/retroshare-gui/src/gui/NewsFeed.cpp b/retroshare-gui/src/gui/NewsFeed.cpp index 77b54f453..aab329846 100644 --- a/retroshare-gui/src/gui/NewsFeed.cpp +++ b/retroshare-gui/src/gui/NewsFeed.cpp @@ -531,15 +531,15 @@ void NewsFeed::handleWireEvent(std::shared_ptr event) case RsWireEventCode::NEW_POST: addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); break; - case RsWireEventCode::NEW_REPLY: - addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); - break; - case RsWireEventCode::NEW_REPUBLISH: - addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); - break; - case RsWireEventCode::NEW_LIKE: - addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); - break; +// case RsWireEventCode::NEW_REPLY: +// addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); +// break; +// case RsWireEventCode::NEW_REPUBLISH: +// addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); +// break; +// case RsWireEventCode::NEW_LIKE: +// addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); +// break; case RsWireEventCode::WIRE_UPDATED: addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true, RsWireEventCode::WIRE_UPDATED)); break; diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.cpp b/retroshare-gui/src/gui/TheWire/WireDialog.cpp index 564970664..1d83274cb 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireDialog.cpp @@ -39,12 +39,14 @@ #include #include +#include #include #include #include #include #include +#include /**************************************************************** * TheWire Display Widget. @@ -68,6 +70,7 @@ WireDialog::WireDialog(QWidget *parent) : GxsStatisticsProvider(rsWire, settingsGroupName(),parent, true), mGroupSet(GROUP_SET_ALL) , mAddDialog(nullptr), mGroupSelected(nullptr), mWireQueue(nullptr) , mHistoryIndex(-1), mEventHandlerId(0), mSortAscending(false) + , mAccountSortType(0), mHideInactiveAccounts(false) { ui.setupUi(this); @@ -76,7 +79,6 @@ WireDialog::WireDialog(QWidget *parent) connect( ui.toolButton_home, SIGNAL(clicked()), this, SLOT(showHomeFeed())); connect( ui.lineEdit_searchUsers, SIGNAL(textChanged(const QString&)), this, SLOT(filterUsers(const QString&))); - connect(ui.comboBox_groupSet, SIGNAL(currentIndexChanged(int)), this, SLOT(selectGroupSet(int))); connect(ui.comboBox_filterTime, SIGNAL(currentIndexChanged(int)), this, SLOT(selectFilterTime(int))); @@ -92,14 +94,34 @@ WireDialog::WireDialog(QWidget *parent) sortAscAction->setChecked(mSortAscending); connect(sortAscAction, SIGNAL(triggered()), this, SLOT(toggleSortAscending())); - QMenu *filterTimeMenu = filterMenu->addMenu(tr("Filter by time")); - filterTimeMenu->addAction(tr("All Time"), this, SLOT(setFilterTimeAllTime())); - filterTimeMenu->addAction(tr("Last 24 hours"), this, SLOT(setFilterTimeLast24Hours())); - filterTimeMenu->addAction(tr("Last 7 days"), this, SLOT(setFilterTimeLast7Days())); - filterTimeMenu->addAction(tr("Last 30 days"), this, SLOT(setFilterTimeLast30Days())); - ui.toolButton_filter->setMenu(filterMenu); + // Setup account filter menu + QMenu *accountMenu = new QMenu(this); + QActionGroup *sortGroup = new QActionGroup(this); + + QAction *sortByName = accountMenu->addAction(tr("Sort by Name")); + sortByName->setCheckable(true); + sortByName->setChecked(true); + sortByName->setData(0); + sortGroup->addAction(sortByName); + + QAction *sortByActivity = accountMenu->addAction(tr("Sort by Activity")); + sortByActivity->setCheckable(true); + sortByActivity->setData(1); + sortGroup->addAction(sortByActivity); + + accountMenu->addSeparator(); + + QAction *hideInactiveAction = accountMenu->addAction(tr("Hide inactive (>30d)")); + hideInactiveAction->setCheckable(true); + hideInactiveAction->setChecked(false); + + connect(sortGroup, SIGNAL(triggered(QAction*)), this, SLOT(sortAccountsChanged(QAction*))); + connect(hideInactiveAction, SIGNAL(toggled(bool)), this, SLOT(hideInactiveChanged(bool))); + + ui.toolButton_accountFilter->setMenu(accountMenu); + QTimer *timer = new QTimer(this); timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); timer->start(1000); @@ -138,38 +160,21 @@ void WireDialog::handleEvent_main_thread(std::shared_ptr event) // The following switch statements refresh the wire feed whenever there is a new event - std::cout<<"***************the wire event code is ************************* "<mWireEventCode) { case RsWireEventCode::READ_STATUS_CHANGED: updateGroupStatisticsReal(e->mWireGroupId); // update the list immediately - std::cout<<"1"<mWireGroupId); break; @@ -601,6 +606,12 @@ void WireDialog::selectGroupSet(int index) if (mGroupSet < 0) { mGroupSet = GROUP_SET_ALL; } + + // show follow label and account filter only when All is selected + bool showFollow = (mGroupSet == GROUP_SET_ALL); + ui.followLabel->setVisible(showFollow); + ui.toolButton_accountFilter->setVisible(showFollow); + showGroups(); } @@ -618,29 +629,20 @@ void WireDialog::toggleSortAscending() showSelectedGroups(); } -void WireDialog::setFilterTimeAllTime() +void WireDialog::sortAccountsChanged(QAction *action) { - ui.comboBox_filterTime->setCurrentIndex(0); + mAccountSortType = action->data().toInt(); + showGroups(); } -void WireDialog::setFilterTimeLast24Hours() +void WireDialog::hideInactiveChanged(bool checked) { - ui.comboBox_filterTime->setCurrentIndex(1); -} - -void WireDialog::setFilterTimeLast7Days() -{ - ui.comboBox_filterTime->setCurrentIndex(2); -} - -void WireDialog::setFilterTimeLast30Days() -{ - ui.comboBox_filterTime->setCurrentIndex(3); + mHideInactiveAccounts = checked; + showGroups(); } void WireDialog::showSelectedGroups() { - ui.comboBox_filterTime->setEnabled(false); if (mGroupSelected) { // request data. @@ -658,10 +660,14 @@ void WireDialog::showSelectedGroups() void WireDialog::showGroups() { - ui.comboBox_filterTime->setEnabled(false); deleteGroups(); std::list allGroupIds; + std::vector groupsToShow; + + // Collect groups that match the current filter + rstime_t now = time(nullptr); + rstime_t thirtyDaysAgo = now - (30 * 24 * 60 * 60); for (auto &it : mAllGroups) { @@ -682,10 +688,39 @@ void WireDialog::showGroups() } } - if (add) { - addGroup(it.second); - allGroupIds.push_back(it.second.mMeta.mGroupId); + // Filter inactive accounts if checkbox is checked + if (add && mHideInactiveAccounts) { + rstime_t lastPost = it.second.mMeta.mLastPost; + if (lastPost == 0 || lastPost < thirtyDaysAgo) { + add = false; + } } + + if (add) { + groupsToShow.push_back(it.second); + } + } + + // Sort groups based on selection + if (mAccountSortType == 0) { + // Sort by name (alphabetical) + std::sort(groupsToShow.begin(), groupsToShow.end(), + [](const RsWireGroup &a, const RsWireGroup &b) { + return QString::fromStdString(a.mMeta.mGroupName).toLower() < + QString::fromStdString(b.mMeta.mGroupName).toLower(); + }); + } else { + // Sort by activity (most recent first) + std::sort(groupsToShow.begin(), groupsToShow.end(), + [](const RsWireGroup &a, const RsWireGroup &b) { + return a.mMeta.mLastPost > b.mMeta.mLastPost; + }); + } + + // Add sorted groups to UI + for (auto &group : groupsToShow) { + addGroup(group); + allGroupIds.push_back(group.mMeta.mGroupId); } requestGroupsPulses(allGroupIds); @@ -1390,7 +1425,6 @@ void WireDialog::postGroupsPulses(std::list pulses) void WireDialog::getServiceStatistics(GxsServiceStatistic& stats) const { - std::cout<<"inside the getServiceStatics *********"< mHistory; bool mSortAscending; + int mAccountSortType; + bool mHideInactiveAccounts; // pending navigation (for when navigate called before groups loaded) RsGxsGroupId mNavigatePendingGroupId; diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.ui b/retroshare-gui/src/gui/TheWire/WireDialog.ui index 8c7426248..3621c54b5 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.ui +++ b/retroshare-gui/src/gui/TheWire/WireDialog.ui @@ -202,17 +202,38 @@ - - - - 10 - true - - - - Who to Follow - - + + + + + + 10 + true + + + + Who to Follow + + + + + + + + + + + :/icons/png/options.png:/icons/png/options.png + + + QToolButton::InstantPopup + + + true + + + + @@ -303,20 +324,6 @@ - - - - - - - - :/icons/mail/filter24.png:/icons/mail/filter24.png - - - QToolButton::InstantPopup - - - @@ -401,6 +408,20 @@ + + + + + + + + :/icons/mail/filter24.png:/icons/mail/filter24.png + + + QToolButton::InstantPopup + + + diff --git a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp index 238173fb9..786d8ede5 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp @@ -223,7 +223,6 @@ bool WireNotifyPostItem::setPost(const RsWirePulse &pulse, bool doFill) if (doFill) { fill(); - std::cout<<"filling needs to be implemented"< Date: Sat, 21 Feb 2026 14:35:09 +0530 Subject: [PATCH 13/13] Wire: Fix republish/like popup, correct profile counts, show followers, adopt defnax UI cleanup, fix GxsStatisticsProvider migration --- retroshare-gui/src/CMakeLists.txt | 3 - retroshare-gui/src/gui/NewsFeed.cpp | 11 +- retroshare-gui/src/gui/NewsFeed.h | 2 +- retroshare-gui/src/gui/Posted/PostedDialog.h | 2 +- .../src/gui/Posted/PostedUserNotify.cpp | 2 +- .../src/gui/Posted/PostedUserNotify.h | 2 +- .../src/gui/TheWire/PulseAddDialog.cpp | 1 + .../src/gui/TheWire/PulseViewGroup.cpp | 8 +- .../src/gui/TheWire/PulseViewGroup.ui | 34 + retroshare-gui/src/gui/TheWire/WireDialog.cpp | 170 +---- retroshare-gui/src/gui/TheWire/WireDialog.h | 34 +- .../src/gui/common/NotifyWidget.cpp | 65 -- retroshare-gui/src/gui/common/NotifyWidget.h | 83 --- retroshare-gui/src/gui/common/NotifyWidget.ui | 66 -- .../src/gui/feeds/WireNotifyGroupItem.cpp | 13 +- .../src/gui/feeds/WireNotifyGroupItem.h | 1 - .../src/gui/feeds/WireNotifyPostItem.cpp | 376 ++-------- .../src/gui/feeds/WireNotifyPostItem.h | 12 +- .../src/gui/feeds/WireNotifyPostItem.ui | 106 +-- retroshare-gui/src/gui/feeds/WirePostItem.cpp | 693 ------------------ retroshare-gui/src/gui/feeds/WirePostItem.h | 108 --- .../src/gui/gxs/GxsGroupFrameDialog.cpp | 5 +- .../src/gui/gxs/GxsGroupFrameDialog.h | 26 +- .../src/gui/gxs/GxsStatisticsProvider.cpp | 39 - .../src/gui/gxs/GxsStatisticsProvider.h | 53 +- retroshare-gui/src/gui/gxs/GxsUserNotify.h | 1 - .../src/gui/gxschannels/GxsChannelDialog.h | 2 +- .../gui/gxschannels/GxsChannelUserNotify.cpp | 2 +- .../gui/gxschannels/GxsChannelUserNotify.h | 3 +- .../src/gui/gxsforums/GxsForumsDialog.h | 2 +- .../src/gui/settings/rsharesettings.cpp | 4 +- retroshare-gui/src/retroshare-gui.pro | 3 - 32 files changed, 194 insertions(+), 1738 deletions(-) delete mode 100644 retroshare-gui/src/gui/common/NotifyWidget.cpp delete mode 100644 retroshare-gui/src/gui/common/NotifyWidget.h delete mode 100644 retroshare-gui/src/gui/common/NotifyWidget.ui delete mode 100644 retroshare-gui/src/gui/feeds/WirePostItem.cpp delete mode 100644 retroshare-gui/src/gui/feeds/WirePostItem.h diff --git a/retroshare-gui/src/CMakeLists.txt b/retroshare-gui/src/CMakeLists.txt index 6de5ceeba..71dd6770f 100644 --- a/retroshare-gui/src/CMakeLists.txt +++ b/retroshare-gui/src/CMakeLists.txt @@ -176,7 +176,6 @@ list( src/gui/common/FlowLayout.cpp src/gui/common/PictureFlow.cpp src/gui/common/ToasterNotify.cpp - src/gui/common/NotifyWidget.cpp src/gui/style/RSStyle.cpp src/gui/style/StyleDialog.cpp @@ -383,7 +382,6 @@ list( src/gui/common/RsCollectionDialog.ui src/gui/common/HeaderFrame.ui src/gui/common/RSFeedWidget.ui - src/gui/common/NotifyWidget.ui src/gui/style/StyleDialog.ui @@ -643,7 +641,6 @@ list( src/gui/common/FlowLayout.h src/gui/common/PictureFlow.h src/gui/common/ToasterNotify.h - src/gui/common/NotifyWidget.h src/gui/style/RSStyle.h src/gui/style/StyleDialog.h diff --git a/retroshare-gui/src/gui/NewsFeed.cpp b/retroshare-gui/src/gui/NewsFeed.cpp index aab329846..069548356 100644 --- a/retroshare-gui/src/gui/NewsFeed.cpp +++ b/retroshare-gui/src/gui/NewsFeed.cpp @@ -529,17 +529,8 @@ void NewsFeed::handleWireEvent(std::shared_ptr event) addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true, RsWireEventCode::NEW_WIRE)); break; case RsWireEventCode::NEW_POST: - addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); + addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, true)); break; -// case RsWireEventCode::NEW_REPLY: -// addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); -// break; -// case RsWireEventCode::NEW_REPUBLISH: -// addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); -// break; -// case RsWireEventCode::NEW_LIKE: -// addFeedItem( new WireNotifyPostItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, pe->mWireMsgId, false, true)); -// break; case RsWireEventCode::WIRE_UPDATED: addFeedItem( new WireNotifyGroupItem(this, NEWSFEED_WIRELIST, pe->mWireGroupId, false, true, RsWireEventCode::WIRE_UPDATED)); break; diff --git a/retroshare-gui/src/gui/NewsFeed.h b/retroshare-gui/src/gui/NewsFeed.h index b1bc2d967..876eef95a 100644 --- a/retroshare-gui/src/gui/NewsFeed.h +++ b/retroshare-gui/src/gui/NewsFeed.h @@ -49,7 +49,7 @@ const uint32_t NEWSFEED_POSTEDNEWLIST = 0x000b; const uint32_t NEWSFEED_POSTEDMSGLIST = 0x000c; const uint32_t NEWSFEED_CIRCLELIST = 0x000d; const uint32_t NEWSFEED_CHANNELPUBKEYLIST= 0x000e; -const uint32_t NEWSFEED_WIRELIST = 0X000f; +const uint32_t NEWSFEED_WIRELIST = 0x0010; namespace Ui { class NewsFeed; diff --git a/retroshare-gui/src/gui/Posted/PostedDialog.h b/retroshare-gui/src/gui/Posted/PostedDialog.h index 433adbe93..6f348d218 100644 --- a/retroshare-gui/src/gui/Posted/PostedDialog.h +++ b/retroshare-gui/src/gui/Posted/PostedDialog.h @@ -54,7 +54,7 @@ private: /* GxsGroupFrameDialog */ virtual QString text(TextType type) override; virtual QString icon(IconType type) override; - virtual QString settingsGroupName() override{ return "PostedDialog"; } + virtual QString settingsGroupName() { return "PostedDialog"; } virtual GxsGroupDialog *createNewGroupDialog() override; virtual GxsGroupDialog *createGroupDialog(GxsGroupDialog::Mode mode, RsGxsGroupId groupId) override; virtual int shareKeyType() override; diff --git a/retroshare-gui/src/gui/Posted/PostedUserNotify.cpp b/retroshare-gui/src/gui/Posted/PostedUserNotify.cpp index ce6e49835..305bc6fac 100644 --- a/retroshare-gui/src/gui/Posted/PostedUserNotify.cpp +++ b/retroshare-gui/src/gui/Posted/PostedUserNotify.cpp @@ -23,7 +23,7 @@ #include "gui/MainWindow.h" #include "gui/common/FilesDefs.h" -PostedUserNotify::PostedUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsGroupFrameDialog *g, QObject *parent) : +PostedUserNotify::PostedUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsStatisticsProvider *g, QObject *parent) : GxsUserNotify(ifaceImpl, g, parent) { } diff --git a/retroshare-gui/src/gui/Posted/PostedUserNotify.h b/retroshare-gui/src/gui/Posted/PostedUserNotify.h index b7631bc37..26bb08e22 100644 --- a/retroshare-gui/src/gui/Posted/PostedUserNotify.h +++ b/retroshare-gui/src/gui/Posted/PostedUserNotify.h @@ -28,7 +28,7 @@ class PostedUserNotify : public GxsUserNotify Q_OBJECT public: - explicit PostedUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsGroupFrameDialog *g, QObject *parent = 0); + explicit PostedUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsStatisticsProvider *g, QObject *parent = 0); virtual bool hasSetting(QString *name, QString *group) override; diff --git a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp index 77d0217ce..6e681329a 100644 --- a/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseAddDialog.cpp @@ -307,6 +307,7 @@ void PulseAddDialog::setReplyTo(const RsGxsGroupId &grpId, const RsGxsMessageId * Qt::QueuedConnection is important! */ + mGroup = *pGroup; setReplyTo(*pPulse, pPulse, pGroup->mMeta.mGroupName, replyType); }, this ); diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp b/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp index f962daaeb..39739a6d9 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.cpp @@ -112,13 +112,17 @@ void PulseViewGroup::setup() uint32_t replies = mGroup->mRefReplies; uint32_t republishes = mGroup->mRefRepublishes; uint32_t likes = mGroup->mRefLikes; - // uint32_t following = mGroup->mGroupFollowing; // TODO: field not yet in RsWireGroup label_extra_pulses->setText(BoldString(ToNumberUnits(pulses))); label_extra_replies->setText(BoldString(ToNumberUnits(replies))); label_extra_republishes->setText(BoldString(ToNumberUnits(republishes))); label_extra_likes->setText(BoldString(ToNumberUnits(likes))); - // label_extra_following->setText(BoldString(ToNumberUnits(following))); // TODO: enable when mGroupFollowing added + + uint32_t following = mGroup->mGroupFollowing; + label_extra_following->setText(BoldString(ToNumberUnits(following))); + + uint32_t followers = mGroup->mGroupFollowers; + label_extra_followers->setText(BoldString(ToNumberUnits(followers))); // hide follow button but keep copy link visible. followButton->setVisible(false); diff --git a/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui b/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui index caf6533ff..bb4075bd3 100644 --- a/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui +++ b/retroshare-gui/src/gui/TheWire/PulseViewGroup.ui @@ -548,6 +548,40 @@ + + + + + + <html><head/><body><p><span style=" font-weight:600;">0</span></p></body></html> + + + + + + + <html><head/><body><p><span style=" color:#2e3436;">Followers</span></p></body></html> + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 40 + 20 + + + + + + diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.cpp b/retroshare-gui/src/gui/TheWire/WireDialog.cpp index 1d83274cb..10d0c6b4d 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.cpp +++ b/retroshare-gui/src/gui/TheWire/WireDialog.cpp @@ -25,7 +25,6 @@ #include "gui/settings/rsharesettings.h" #include "gui/gxs/GxsIdDetails.h" #include "gui/common/FilesDefs.h" -#include "gui/common/NotifyWidget.h" #include "gui/gxs/GxsStatisticsProvider.h" #include "gui/gxs/GxsGroupShareKey.h" @@ -62,18 +61,20 @@ // #define GROUP_SET_RECOMMENDED (5) -#define WIRE_TOKEN_TYPE_SUBSCRIBE_CHANGE 1 -#define TOKEN_TYPE_GROUP_SUMMARY 1 - /** Constructor */ WireDialog::WireDialog(QWidget *parent) - : GxsStatisticsProvider(rsWire, settingsGroupName(),parent, true), mGroupSet(GROUP_SET_ALL) - , mAddDialog(nullptr), mGroupSelected(nullptr), mWireQueue(nullptr) + : MainPage(parent), mGroupSet(GROUP_SET_ALL) + , mAddDialog(nullptr), mGroupSelected(nullptr) , mHistoryIndex(-1), mEventHandlerId(0), mSortAscending(false) , mAccountSortType(0), mHideInactiveAccounts(false) { ui.setupUi(this); + mInterface = rsWire; + mSettingsName = "WireDialog"; + mDistSyncAllowed = true; + mStateHelper = nullptr; + connect( ui.toolButton_createAccount, SIGNAL(clicked()), this, SLOT(createGroup())); connect( ui.toolButton_createPulse, SIGNAL(clicked()), this, SLOT(createPulse())); connect( ui.toolButton_home, SIGNAL(clicked()), this, SLOT(showHomeFeed())); @@ -126,8 +127,6 @@ WireDialog::WireDialog(QWidget *parent) timer->connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); timer->start(1000); - /* setup TokenQueue */ - mWireQueue = new TokenQueue(rsWire->getTokenService(), this); mCountChildMsgs = false; mShouldUpdateGroupStatistics = false; mDistSyncAllowed = true; @@ -195,7 +194,6 @@ WireDialog::~WireDialog() processSettings(false); clearTwitterView(); - delete(mWireQueue); rsEvents->unregisterEventsHandler(mEventHandlerId); } @@ -435,14 +433,12 @@ void WireDialog::subscribe(RsGxsGroupId &groupId) { uint32_t token; rsWire->subscribeToGroup(token, groupId, true); - mWireQueue->queueRequest(token, TOKENREQ_GROUPINFO, RS_TOKREQ_ANSTYPE_ACK, WIRE_TOKEN_TYPE_SUBSCRIBE_CHANGE); } void WireDialog::unsubscribe(RsGxsGroupId &groupId) { uint32_t token; rsWire->subscribeToGroup(token, groupId, false); - mWireQueue->queueRequest(token, TOKENREQ_GROUPINFO, RS_TOKREQ_ANSTYPE_ACK, WIRE_TOKEN_TYPE_SUBSCRIBE_CHANGE); } void WireDialog::notifyGroupSelection(WireGroupItem *item) @@ -734,25 +730,12 @@ void WireDialog::requestGroupData() std::cerr << "WireDialog::requestGroupData()"; std::cerr << std::endl; - RsTokReqOptions opts; - uint32_t token; - opts.mReqType = GXS_REQUEST_TYPE_GROUP_DATA; - mWireQueue->requestGroupInfo(token, RS_TOKREQ_ANSTYPE_DATA, opts, 0); -} - -bool WireDialog::loadGroupData(const uint32_t &token) -{ - std::cerr << "WireDialog::loadGroupData()"; - std::cerr << std::endl; - std::vector groups; - rsWire->getGroupData(token, groups); + rsWire->getGroups({}, groups); - // save list of groups. updateGroups(groups); showGroups(); - // check for pending navigation if (!mNavigatePendingGroupId.isNull()) { if (!mNavigatePendingMsgId.isNull()) { requestPulseFocus(mNavigatePendingGroupId, mNavigatePendingMsgId); @@ -762,7 +745,6 @@ bool WireDialog::loadGroupData(const uint32_t &token) mNavigatePendingGroupId.clear(); mNavigatePendingMsgId.clear(); } - return true; } rstime_t WireDialog::getFilterTimestamp() @@ -788,60 +770,6 @@ rstime_t WireDialog::getFilterTimestamp() return filterTimestamp; } -void WireDialog::acknowledgeGroup(const uint32_t &token, const uint32_t &userType) -{ - /* reload groups */ - std::cerr << "WireDialog::acknowledgeGroup(usertype: " << userType << ")"; - std::cerr << std::endl; - - RsGxsGroupId grpId; - rsWire->acknowledgeGrp(token, grpId); - - refreshGroups(); -} - - -/**************************** Request / Response Filling of Data ************************/ - -void WireDialog::loadRequest(const TokenQueue *queue, const TokenRequest &req) -{ - std::cerr << "WireDialog::loadRequest()"; - std::cerr << std::endl; - - if (queue == mWireQueue) - { - /* now switch on req */ - switch(req.mType) - { - case TOKENREQ_GROUPINFO: - switch(req.mAnsType) - { - case RS_TOKREQ_ANSTYPE_DATA: - loadGroupData(req.mToken); - break; - case RS_TOKREQ_ANSTYPE_ACK: - acknowledgeGroup(req.mToken, req.mUserType); - break; - default: - std::cerr << "WireDialog::loadRequest() ERROR: GROUP: INVALID ANS TYPE"; - std::cerr << std::endl; - break; - } - break; - default: - std::cerr << "WireDialog::loadRequest() ERROR: INVALID TYPE"; - std::cerr << std::endl; - break; - } - } -} - - -/**************************** Request / Response Filling of Data ************************/ - - - - /****************************************************************************************/ // TWITTER VIEW. @@ -894,55 +822,10 @@ void WireDialog::PVHrepublish(const RsGxsGroupId &groupId, const RsGxsMessageId std::cerr << " MsgId: " << msgId; std::cerr << std::endl; - int idx = ui.groupChooser->currentIndex(); - if (idx < 0 || idx >= (int)mOwnGroups.size()) { - std::cerr << "WireDialog::PVHrepublish() No own group selected"; - std::cerr << std::endl; - QMessageBox::warning(this, tr("RetroShare"), tr("Please select your Wire account first"), QMessageBox::Ok); - return; - } - - RsGxsGroupId replyWith = mOwnGroups[idx].mMeta.mGroupId; - setCursor(Qt::WaitCursor); - - RsThread::async([this, groupId, msgId, replyWith]() + if (setupPulseAddDialog()) { - RsWirePulseSPtr origPulse; - if (!rsWire->getWirePulse(groupId, msgId, origPulse)) - { - std::cerr << "WireDialog::PVHrepublish() failed to fetch original pulse"; - std::cerr << std::endl; - RsQThreadUtils::postToObject([this]() - { - setCursor(Qt::ArrowCursor); - }, this); - return; - } - - RsWirePulseSPtr pPulse(new RsWirePulse()); - pPulse->mSentiment = origPulse->mSentiment; - pPulse->mPulseText = origPulse->mPulseText; - pPulse->mImage1 = origPulse->mImage1; - pPulse->mImage2 = origPulse->mImage2; - pPulse->mImage3 = origPulse->mImage3; - pPulse->mImage4 = origPulse->mImage4; - - RsGxsMessageId targetMsgId = origPulse->mMeta.mOrigMsgId; - if (targetMsgId.isNull()) { - targetMsgId = msgId; - } - - bool success = rsWire->createReplyPulse(groupId, targetMsgId, replyWith, - WIRE_PULSE_TYPE_REPUBLISH, pPulse); - - RsQThreadUtils::postToObject([this, success]() - { - setCursor(Qt::ArrowCursor); - if (!success) { - std::cerr << "WireDialog::PVHrepublish() FAILED" << std::endl; - } - }, this); - }); + mAddDialog->setReplyTo(groupId, msgId, WIRE_PULSE_TYPE_REPUBLISH); + } } void WireDialog::PVHlike(const RsGxsGroupId &groupId, const RsGxsMessageId &msgId) @@ -951,34 +834,10 @@ void WireDialog::PVHlike(const RsGxsGroupId &groupId, const RsGxsMessageId &msgI std::cerr << " MsgId: " << msgId; std::cerr << std::endl; - int idx = ui.groupChooser->currentIndex(); - if (idx < 0 || idx >= (int)mOwnGroups.size()) { - std::cerr << "WireDialog::PVHlike() No own group selected"; - std::cerr << std::endl; - QMessageBox::warning(this, tr("RetroShare"), tr("Please select your Wire account first"), QMessageBox::Ok); - return; - } - - RsGxsGroupId replyWith = mOwnGroups[idx].mMeta.mGroupId; - setCursor(Qt::WaitCursor); - - RsThread::async([this, groupId, msgId, replyWith]() + if (setupPulseAddDialog()) { - RsWirePulseSPtr pPulse(new RsWirePulse()); - pPulse->mSentiment = WIRE_PULSE_SENTIMENT_NO_SENTIMENT; - pPulse->mPulseText = ""; - - bool success = rsWire->createReplyPulse(groupId, msgId, replyWith, - WIRE_PULSE_TYPE_LIKE, pPulse); - - RsQThreadUtils::postToObject([this, success]() - { - setCursor(Qt::ArrowCursor); - if (!success) { - std::cerr << "WireDialog::PVHlike() FAILED" << std::endl; - } - }, this); - }); + mAddDialog->setReplyTo(groupId, msgId, WIRE_PULSE_TYPE_LIKE); + } } void WireDialog::PVHviewGroup(const RsGxsGroupId &groupId) @@ -1022,7 +881,6 @@ void WireDialog::PVHfollow(const RsGxsGroupId &groupId) uint32_t token; rsWire->subscribeToGroup(token, groupId, true); - mWireQueue->queueRequest(token, TOKENREQ_GROUPINFO, RS_TOKREQ_ANSTYPE_ACK, WIRE_TOKEN_TYPE_SUBSCRIBE_CHANGE); } void WireDialog::PVHrate(const RsGxsId &authorId) diff --git a/retroshare-gui/src/gui/TheWire/WireDialog.h b/retroshare-gui/src/gui/TheWire/WireDialog.h index 0557d3002..d3ec5347d 100644 --- a/retroshare-gui/src/gui/TheWire/WireDialog.h +++ b/retroshare-gui/src/gui/TheWire/WireDialog.h @@ -36,7 +36,9 @@ #include "gui/TheWire/PulseReply.h" #include "gui/gxs/GxsStatisticsProvider.h" -#include "util/TokenQueue.h" +class UIStateHelper; +class GxsMessageFrameWidget; +class RsGxsIfaceHelper; #define IMAGE_WIRE ":/icons/wire.png" @@ -68,7 +70,7 @@ public: }; //--------------------------------------------------------- -class WireDialog : public GxsStatisticsProvider, public TokenResponse, public WireGroupHolder, public PulseViewHolder +class WireDialog : public MainPage, public GxsStatisticsProvider, public WireGroupHolder, public PulseViewHolder { Q_OBJECT @@ -118,16 +120,16 @@ public: void showGroupsPulses(const std::list& groupIds); void postGroupsPulses(std::list pulses); - void getServiceStatistics(GxsServiceStatistic& stats) const ; + void getServiceStatistics(GxsServiceStatistic& stats) const override; - virtual bool navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msgId) override; + virtual bool navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msgId); protected: - bool getGroupStatistics(const RsGxsGroupId& groupId,GxsGroupStatistic& stat) override; + bool getGroupStatistics(const RsGxsGroupId& groupId,GxsGroupStatistic& stat); UserNotify *createUserNotify(QObject *parent) override; - virtual void updateGroupStatistics(const RsGxsGroupId &groupId) override; - virtual void updateGroupStatisticsReal(const RsGxsGroupId &groupId) override; + virtual void updateGroupStatistics(const RsGxsGroupId &groupId); + virtual void updateGroupStatisticsReal(const RsGxsGroupId &groupId); private slots: @@ -170,19 +172,13 @@ private: // Loading Data. void requestGroupData(); - bool loadGroupData(const uint32_t &token); - void acknowledgeGroup(const uint32_t &token, const uint32_t &userType); - virtual void loadRequest(const TokenQueue *queue, const TokenRequest &req) override; - - virtual QString settingsGroupName() override{ return "WireDialog"; } - virtual GxsMessageFrameWidget *messageWidget(const RsGxsGroupId &groupId) override; + GxsMessageFrameWidget *messageWidget(const RsGxsGroupId &groupId); int mGroupSet; PulseAddDialog *mAddDialog; WireGroupItem *mGroupSelected; - TokenQueue *mWireQueue; std::map mAllGroups; std::vector mOwnGroups; @@ -197,9 +193,17 @@ private: int mAccountSortType; bool mHideInactiveAccounts; - // pending navigation (for when navigate called before groups loaded) + // Members for GxsStatisticsProvider interface support + QString mSettingsName; + RsGxsIfaceHelper *mInterface; + bool mDistSyncAllowed; + std::map mCachedGroupStats; + bool mShouldUpdateGroupStatistics; + std::set mGroupStatisticsToUpdate; + bool mCountChildMsgs; RsGxsGroupId mNavigatePendingGroupId; RsGxsMessageId mNavigatePendingMsgId; + UIStateHelper *mStateHelper; /* UI - from Designer */ Ui::WireDialog ui; diff --git a/retroshare-gui/src/gui/common/NotifyWidget.cpp b/retroshare-gui/src/gui/common/NotifyWidget.cpp deleted file mode 100644 index 9fe2f4abf..000000000 --- a/retroshare-gui/src/gui/common/NotifyWidget.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include "NotifyWidget.h" -#include "ui_NotifyWidget.h" -#include "RSTreeWidgetItem.h" - -#define ROLE_ID Qt::UserRole -#define ROLE_NAME Qt::UserRole + 1 -#define ROLE_DESCRIPTION Qt::UserRole + 2 -#define ROLE_SUBSCRIBE_FLAGS Qt::UserRole + 3 -#define ROLE_COLOR Qt::UserRole + 4 -#define ROLE_REQUEST_ID Qt::UserRole + 5 -#define ROLE_SORT Qt::UserRole + 6 - -NotifyWidget::NotifyWidget(QWidget *parent) : - QWidget(parent), - ui(new Ui::NotifyWidget) -{ - ui->setupUi(this); -} - -NotifyWidget::~NotifyWidget() -{ - delete ui; -} - -void NotifyWidget::setUnreadCount(QTreeWidgetItem *item, int unreadCount) -{ - if (item == NULL) { - return; - } - - QFont itFont = item->font(GTW_COLUMN_NAME); - - if (unreadCount) { - item->setText(GTW_COLUMN_UNREAD, QString::number(unreadCount)); - itFont.setBold(true); - } else { - item->setText(GTW_COLUMN_UNREAD, ""); - itFont.setBold(false); - } - item->setData(GTW_COLUMN_UNREAD, ROLE_SORT, unreadCount); - - item->setFont(GTW_COLUMN_NAME, itFont); -} - -QTreeWidgetItem *NotifyWidget::getItemFromId(const QString &id) -{ - if (id.isEmpty()) { - return NULL; - } - - /* Search exisiting item */ - QTreeWidgetItemIterator itemIterator(ui->treeWidget); - QTreeWidgetItem *item; - while ((item = *itemIterator) != NULL) { - ++itemIterator; - - if (item->parent() == NULL) { - continue; - } - if (item->data(GTW_COLUMN_DATA, ROLE_ID).toString() == id) { - return item; - } - } - return NULL ; -} diff --git a/retroshare-gui/src/gui/common/NotifyWidget.h b/retroshare-gui/src/gui/common/NotifyWidget.h deleted file mode 100644 index 55c536439..000000000 --- a/retroshare-gui/src/gui/common/NotifyWidget.h +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * gui/common/NotifyWidget.h * - * * - * Copyright (C) 2010, 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 NOTIFYWIDGET_H -#define NOTIFYWIDGET_H - -#include -#include -#include - -#include - -#define GTW_COLUMN_NAME 0 -#define GTW_COLUMN_UNREAD 1 -#define GTW_COLUMN_POSTS 2 -#define GTW_COLUMN_POPULARITY 3 -#define GTW_COLUMN_LAST_POST 4 -#define GTW_COLUMN_SEARCH_SCORE 5 -#define GTW_COLUMN_DESCRIPTION 6 -#define GTW_COLUMN_COUNT 7 -#define GTW_COLUMN_DATA GTW_COLUMN_NAME - -namespace Ui { -class NotifyWidget; -} - -//class GroupItemInfo -//{ -//public: -// GroupItemInfo() -// : popularity(0), publishKey(false), adminKey(false) -// , subscribeFlags(0), max_visible_posts(0) -// {} - -//public: -// QString id; -// QString name; -// QString description; -// int popularity; -// QDateTime lastpost; -// QIcon icon; -// bool publishKey; -// bool adminKey; -// quint32 subscribeFlags; -// quint32 max_visible_posts ; -// std::set context_strings; -//}; - -class NotifyWidget : public QWidget -{ - Q_OBJECT - -public: - NotifyWidget(QWidget *parent = nullptr); - ~NotifyWidget(); - - // Set the unread count of an item - void setUnreadCount(QTreeWidgetItem *item, int unreadCount); - QTreeWidgetItem *getItemFromId(const QString &id); - -private: - Ui::NotifyWidget *ui; - -}; - -#endif // NOTIFYWIDGET_H diff --git a/retroshare-gui/src/gui/common/NotifyWidget.ui b/retroshare-gui/src/gui/common/NotifyWidget.ui deleted file mode 100644 index 6429f4258..000000000 --- a/retroshare-gui/src/gui/common/NotifyWidget.ui +++ /dev/null @@ -1,66 +0,0 @@ - - - NotifyWidget - - - - 0 - 0 - 400 - 300 - - - - Form - - - - - - true - - - - 0 - 0 - - - - - 11 - - - - Qt::CustomContextMenu - - - QAbstractItemView::NoEditTriggers - - - - 19 - 19 - - - - true - - - - 1 - - - - - - - - - RSTreeWidget - QTreeWidget -
    gui/common/RSTreeWidget.h
    -
    -
    - - -
    diff --git a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp index 44d145066..7a0674d09 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp +++ b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp @@ -43,15 +43,6 @@ WireNotifyGroupItem::WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId addEventHandler(); } -WireNotifyGroupItem::WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate, RsWireEventCode eventCode) : - GxsGroupFeedItem(feedHolder, feedId, group.mMeta.mGroupId, isHome, rsWire, autoUpdate), - mEventCode(eventCode) -{ - setup(); - setGroup(group); - addEventHandler(); -} - void WireNotifyGroupItem::addEventHandler() { mEventHandlerId = 0; @@ -68,6 +59,8 @@ void WireNotifyGroupItem::addEventHandler() { case RsWireEventCode::FOLLOW_STATUS_CHANGED: case RsWireEventCode::WIRE_UPDATED: + mGroup = RsWireGroup(); + requestGroup(); break; default: break; @@ -137,6 +130,7 @@ void WireNotifyGroupItem::loadGroup() if(!rsWire->getGroups(groupIds,groups)) { RsErr() << "WireNotifyGroupItem::loadGroup() ERROR getting data" << std::endl; + deferred_update(); return; } @@ -144,6 +138,7 @@ void WireNotifyGroupItem::loadGroup() { std::cerr << "WireNotifyGroupItem::loadGroup() Wrong number of Items"; std::cerr << std::endl; + deferred_update(); return; } RsWireGroup group(groups[0]); diff --git a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h index d8b695d31..7110feb4f 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h +++ b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h @@ -37,7 +37,6 @@ class WireNotifyGroupItem : public GxsGroupFeedItem public: /** Default Constructor */ WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId &groupId, bool isHome, bool autoUpdate, RsWireEventCode eventCode = RsWireEventCode::NEW_WIRE); - WireNotifyGroupItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate, RsWireEventCode eventCode = RsWireEventCode::NEW_WIRE); ~WireNotifyGroupItem(); bool setGroup(const RsWireGroup &group); diff --git a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp index 786d8ede5..824af3131 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp @@ -35,37 +35,14 @@ #include #include -WireNotifyPostItem::WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGroupMetaData& group_meta, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate,const std::set& older_versions) : - GxsFeedItem(feedHolder, feedId, group_meta.mGroupId, messageId, isHome, rsWire, autoUpdate), - mGroupMeta(group_meta) +WireNotifyPostItem::WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool autoUpdate, const std::set &older_versions) : + GxsFeedItem(feedHolder, feedId, groupId, messageId, false, rsWire, autoUpdate) { + mLoadingStatus = LOADING_STATUS_NO_DATA; mLoadingGroup = false; mLoadingMessage = false; mLoadingComment = false; - mPulse.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded - mPulse.mMeta.mGroupId = mGroupMeta.mGroupId; - - QVector v; - //bool self = false; - - for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) - v.push_back(*it) ; - - if(older_versions.find(messageId) == older_versions.end()) - v.push_back(messageId); - - setMessageVersions(v) ; - setup(); - - // no call to loadGroup() here because we have it already. -} - -WireNotifyPostItem::WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set &older_versions) : - GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsWire, autoUpdate) // this one should be in GxsFeedItem -{ - mPulse.mMeta.mMsgId = messageId; // useful for uniqueIdentifer() before the post is loaded - QVector v; //bool self = false; @@ -77,8 +54,6 @@ WireNotifyPostItem::WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, setMessageVersions(v) ; setup(); - - loadGroup(); } void WireNotifyPostItem::paintEvent(QPaintEvent *e) @@ -86,17 +61,27 @@ void WireNotifyPostItem::paintEvent(QPaintEvent *e) /* This method employs a trick to trigger a deferred loading. The post and group is requested only * when actually displayed on the screen. */ - if(!mLoaded) - { - mLoaded = true ; + if(mLoadingStatus != LOADING_STATUS_FILLED && !mGroupMeta.mGroupId.isNull() && !mPulse.mMeta.mMsgId.isNull() ) + mLoadingStatus = LOADING_STATUS_HAS_DATA; - std::set older_versions; // not so nice. We need to use std::set everywhere - for(auto& m:messageVersions()) - older_versions.insert(m); + if(mGroupMeta.mGroupId.isNull() && !mLoadingGroup) + requestGroup(); - fill(); + if(mPulse.mMeta.mMsgId.isNull() && !mLoadingMessage) requestMessage(); - requestComment(); + + switch(mLoadingStatus) + { + case LOADING_STATUS_FILLED: + case LOADING_STATUS_NO_DATA: + default: + break; + + case LOADING_STATUS_HAS_DATA: + fill(); + setGroup(mGroup); + mLoadingStatus = LOADING_STATUS_FILLED; + break; } GxsFeedItem::paintEvent(e) ; @@ -104,7 +89,7 @@ void WireNotifyPostItem::paintEvent(QPaintEvent *e) WireNotifyPostItem::~WireNotifyPostItem() { - auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(300); + auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(GROUP_ITEM_LOADING_TIMEOUT_ms); while( (mLoadingGroup || mLoadingMessage || mLoadingComment) && std::chrono::steady_clock::now() < timeout) @@ -139,11 +124,6 @@ void WireNotifyPostItem::setup() // ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/thumb-default-video.png")); //ui->warn_image_label->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/status_unknown.png")); ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); -// ui->voteUpButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/vote_up.png")); -// ui->voteDownButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/vote_down.png")); -// ui->downloadButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/download.png")); -// ui->playButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/play.png")); - ui->commentButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/comment.png")); //ui->editButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/pencil-edit-button.png")); // ui->copyLinkButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/copy.png")); // ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/down-arrow.png")); @@ -154,14 +134,12 @@ void WireNotifyPostItem::setup() mInFill = false; mCloseOnRead = false; - mLoaded = false; /* clear ui */ ui->titleLabel->setText(tr("Loading...")); ui->titleLabel->setOpenExternalLinks(false); //To get linkActivated working connect(ui->titleLabel, SIGNAL(linkActivated(QString)), this, SLOT(on_linkActivated(QString))); ui->datetimelabel->clear(); - ui->filelabel->clear(); // ui->newCommentLabel->hide(); // ui->commLabel->hide(); @@ -171,32 +149,15 @@ void WireNotifyPostItem::setup() /* specific */ connect(ui->readAndClearButton, SIGNAL(clicked()), this, SLOT(readAndClearItem())); - connect(ui->unsubscribeButton, SIGNAL(clicked()), this, SLOT(unsubscribeChannel())); + connect(ui->unsubscribeButton, SIGNAL(clicked()), this, SLOT(unsubscribe())); - connect(ui->downloadButton, SIGNAL(clicked()), this, SLOT(download())); - // HACK FOR NOW. - ui->commentButton->hide();// hidden until properly enabled. - connect(ui->commentButton, SIGNAL(clicked()), this, SLOT(loadComments())); - - connect(ui->playButton, SIGNAL(clicked()), this, SLOT(play(void))); //connect(ui->editButton, SIGNAL(clicked()), this, SLOT(edit(void))); connect(ui->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyMessageLink())); connect(ui->readButton, SIGNAL(toggled(bool)), this, SLOT(readToggled(bool))); - // hide voting buttons, backend is not implemented yet - ui->voteUpButton->hide(); - ui->voteDownButton->hide(); - //connect(ui-> voteUpButton, SIGNAL(clicked()), this, SLOT(makeUpVote())); - //connect(ui->voteDownButton, SIGNAL(clicked()), this, SLOT(makeDownVote())); - - ui->scoreLabel->hide(); - // hide unsubscribe button not necessary ui->unsubscribeButton->hide(); - - ui->downloadButton->hide(); - ui->playButton->hide(); //ui->warn_image_label->hide(); //ui->warning_label->hide(); @@ -265,10 +226,8 @@ void WireNotifyPostItem::loadMessage() if (!rsWire->getWirePulse(grpId, msgId, pPulse)) { RsErr() << "WireNotifyPostItem::loadMessage() ERROR getting pulse" << std::endl; - RsQThreadUtils::postToObject([this]() - { - mLoadingMessage = false; - }, this); + mLoadingMessage = false; + deferred_update(); return; } @@ -281,15 +240,18 @@ void WireNotifyPostItem::loadMessage() RsQThreadUtils::postToObject([pulse, this]() { - setPost(pulse); + mPulse = pulse; mLoadingMessage = false; + update(); // triggers paintEvent if needed }, this); } else { RsQThreadUtils::postToObject([this]() { + removeItem(); mLoadingMessage = false; + update(); }, this); } }); @@ -297,45 +259,7 @@ void WireNotifyPostItem::loadMessage() void WireNotifyPostItem::loadComment() { -#ifdef DEBUG_ITEM - std::cerr << "WireNotifyPostItem::loadComment()"; - std::cerr << std::endl; -#endif -// mLoadingComment = true; - -// RsThread::async([this]() -// { -// // 1 - get group data - -// std::set msgIds; - -// for(auto MsgId: messageVersions()) -// msgIds.insert(MsgId); - -// std::vector posts; -// std::vector comments; - -// if(! rsGxsChannels->getChannelComments( groupId(),msgIds,comments)) -// { -// RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; -// return; -// } - -// int comNb = comments.size(); - -// RsQThreadUtils::postToObject( [comNb,this]() -// { -// 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); -// mLoadingComment = false; - -// }, this ); -// }); + // TODO: implement Wire comment loading when Wire comments are supported } void WireNotifyPostItem::loadGroup() @@ -357,6 +281,8 @@ void WireNotifyPostItem::loadGroup() if(!rsWire->getGroups(groupIds,groups)) // would be better to call channel Summaries for a single group { RsErr() << "WireNotifyPostItem::loadGroup() ERROR getting data" << std::endl; + mLoadingGroup = false; + deferred_update(); return; } @@ -364,6 +290,8 @@ void WireNotifyPostItem::loadGroup() { std::cerr << "WireNotifyPostItem::loadGroup() Wrong number of Items"; std::cerr << std::endl; + mLoadingGroup = false; + deferred_update(); return; } RsWireGroup group = groups[0]; @@ -374,91 +302,16 @@ void WireNotifyPostItem::loadGroup() * thread, for example to update the data model with new information * after a blocking call to RetroShare API complete */ + mGroup = group; mGroupMeta = group.mMeta; mLoadingGroup = false; - setGroup(group); + + update(); // triggers paintEvent if needed }, this ); }); } -//void WireNotifyPostItem::updateItem() -//{ -// /* fill in */ - -//#ifdef DEBUG_ITEM -// std::cerr << "WireNotifyPostItem::updateItem()"; -// std::cerr << std::endl; -//#endif - -// int msec_rate = 10000; - -// int downloadCount = 0; -// int downloadStartable = 0; -// int playCount = 0; -// int playStartable = 0; -// bool startable; -// bool loopAgain = false; - -// /* Very slow Tick to check when all files are downloaded */ -// std::list::iterator it; -// for(it = mFileItems.begin(); it != mFileItems.end(); ++it) -// { -// SubFileItem *item = *it; - -// if (item->isDownloadable(startable)) { -// ++downloadCount; -// if (startable) { -// ++downloadStartable; -// } -// } -// if (item->isPlayable(startable)) { -// ++playCount; -// if (startable) { -// ++playStartable; -// } -// } - -// if (!item->done()) -// { -// /* loop again */ -// loopAgain = true; -// } -// } - -// if (downloadCount) { -// ui->downloadButton->show(); - -// if (downloadStartable) { -// ui->downloadButton->setEnabled(true); -// } else { -// ui->downloadButton->setEnabled(false); -// } -// } else { -// ui->downloadButton->hide(); -// } -// if (playCount) { -// /* one file is playable */ -// ui->playButton->show(); - -// if (playStartable == 1) { -// ui->playButton->setEnabled(true); -// } else { -// ui->playButton->setEnabled(false); -// } -// } else { -// ui->playButton->hide(); -// } - -// if (loopAgain) { -// QTimer::singleShot( msec_rate, this, SLOT(updateItem(void))); -// } - -// // HACK TO DISPLAY COMMENT BUTTON FOR NOW. -// //downloadButton->show(); -// //downloadButton->setEnabled(true); -//} - QString WireNotifyPostItem::groupName() { return QString::fromUtf8(mGroupMeta.mGroupName.c_str()); @@ -525,150 +378,33 @@ void WireNotifyPostItem::fill() pulseTypeStr = tr("Pulse"); } - if (!mIsHome) + if (mCloseOnRead && !IS_MSG_NEW(mPulse.mMeta.mMsgStatus)) { + removeItem(); + } + + msgText = pulseTypeStr + ": "; + RetroShareLink msgLink = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_WIRE, mPulse.mMeta.mGroupId, mPulse.mMeta.mMsgId, messageName()); + msgText += msgLink.toHtml(); + ui->subjectLabel->setText(msgText); + + ui->pulseMessage->setText(QString::fromUtf8(mPulse.mPulseText.c_str())); + ui->datetimelabel->setText(DateTime::formatLongDateTime(mPulse.mRefPublishTs)); + + if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) { - if (mCloseOnRead && !IS_MSG_NEW(mPulse.mMeta.mMsgStatus)) { - removeItem(); - } - - msgText = pulseTypeStr + ": "; - RetroShareLink msgLink = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_WIRE, mPulse.mMeta.mGroupId, mPulse.mMeta.mMsgId, messageName()); - msgText += msgLink.toHtml(); - ui->subjectLabel->setText(msgText); - - ui->pulseMessage->setText(QString::fromUtf8(mPulse.mPulseText.c_str())); - ui->datetimelabel->setText(DateTime::formatLongDateTime(mPulse.mRefPublishTs)); - - if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) - { - ui->unsubscribeButton->setEnabled(true); - } - else - { - ui->unsubscribeButton->setEnabled(false); - } - ui->readButton->hide(); - ui->newLabel->hide(); - ui->copyLinkButton->hide(); - - if (IS_MSG_NEW(mPulse.mMeta.mMsgStatus)) { - mCloseOnRead = true; - } + ui->unsubscribeButton->setEnabled(true); } else { - - /* disable buttons: deletion facility not enabled with cache services yet */ - ui->clearButton->setEnabled(false); ui->unsubscribeButton->setEnabled(false); - ui->clearButton->hide(); - ui->readAndClearButton->hide(); - ui->unsubscribeButton->hide(); - ui->copyLinkButton->show(); - - if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) - { - ui->readButton->setVisible(true); - - setReadStatus(IS_MSG_NEW(mPulse.mMeta.mMsgStatus), IS_MSG_UNREAD(mPulse.mMeta.mMsgStatus) || IS_MSG_NEW(mPulse.mMeta.mMsgStatus)); - } - else - { - ui->readButton->setVisible(false); - ui->newLabel->setVisible(false); - } - - mCloseOnRead = false; } + ui->readButton->hide(); + ui->newLabel->hide(); + ui->copyLinkButton->hide(); - // differences between Feed or Top of Comment. - if (mFeedHolder) - { - if (mIsHome) { - ui->commentButton->show(); - } else if (ui->commentButton->icon().isNull()){ - //Icon is seted if a comment received. - ui->commentButton->hide(); - } - -// THIS CODE IS doesn't compile - disabling until fixed. -#if 0 - if (post.mComments) - { - QString commentText = QString::number(post.mComments); - commentText += " "; - commentText += tr("Comments"); - ui->commentButton->setText(commentText); - } - else - { - ui->commentButton->setText(tr("Comment")); - } -#endif - + if (IS_MSG_NEW(mPulse.mMeta.mMsgStatus)) { + mCloseOnRead = true; } - else - { - ui->commentButton->hide(); - } - - // disable voting buttons - if they have already voted. - /*if (post.mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) - { - voteUpButton->setEnabled(false); - voteDownButton->setEnabled(false); - }*/ - -// { -// QTextDocument doc; -// doc.setHtml( QString::fromUtf8(mPulse.mMsg.c_str()) ); - -// ui->msgFrame->setVisible(doc.toPlainText().length() > 0); -// } - -// if (wasExpanded() || ui->expandFrame->isVisible()) { -// fillExpandFrame(); -// } - -// if ( (mPulse.mAttachmentCount != 0) || (mPulse.mSize != 0) ) { -// ui->filelabel->setVisible(true); -// ui->filelabel->setText(QString("(%1 %2) %3").arg(mPulse.mAttachmentCount).arg( (mPulse.mAttachmentCount > 1)?tr("Files"):tr("File")).arg(misc::friendlyUnit(mPulse.mSize))); -// } else { -// ui->filelabel->setVisible(false); -// } - -// if (mFileItems.empty() == false) { -// std::list::iterator it; -// for(it = mFileItems.begin(); it != mFileItems.end(); ++it) -// { -// delete(*it); -// } -// mFileItems.clear(); -// } - -// std::list::const_iterator it; -// for(it = mPulse.mFiles.begin(); it != mPulse.mFiles.end(); ++it) -// { -// /* add file */ -// std::string path; -// SubFileItem *fi = new SubFileItem(it->mHash, it->mName, path, it->mSize, SFI_STATE_REMOTE | SFI_TYPE_CHANNEL, RsPeerId()); -// mFileItems.push_back(fi); - -// /* check if the file is a media file */ -// if (!misc::isPreviewable(QFileInfo(QString::fromUtf8(it->mName.c_str())).suffix())) -// { -// fi->mediatype(); -// /* check if the file is not a media file and change text */ -// ui->playButton->setText(tr("Open")); -// ui->playButton->setToolTip(tr("Open File")); -// } else { -// ui->playButton->setText(tr("Play")); -// ui->playButton->setToolTip(tr("Play Media")); -// } - -// QLayout *layout = ui->expandFrame->layout(); -// layout->addWidget(fi); -// } mInFill = false; } diff --git a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.h b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.h index 8633985ae..1dbb4c5ad 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.h +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.h @@ -38,12 +38,7 @@ class WireNotifyPostItem : public GxsFeedItem Q_OBJECT public: - // This one is used in NewFeed for incoming Wire posts. Only the group and msg ids are known at this point. - // It can be used for all apparences of wire posts. But in rder to merge comments from the previous versions of the post, the list of - // previous posts should be supplied. It's optional. If not supplied only the comments of the new version will be displayed. - WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); - WireNotifyPostItem(FeedHolder *parent, uint32_t feedId, const RsGroupMetaData& group_meta, const RsGxsMessageId& messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); - //WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate); + WireNotifyPostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool autoUpdate, const std::set& older_versions = std::set()); virtual ~WireNotifyPostItem(); @@ -52,7 +47,6 @@ public: bool setPost(const RsWirePulse& pulse, bool doFill = true); void setGroup(const RsWireGroup &group); - bool isLoaded() const {return mLoaded;}; bool isUnread() const ; void setReadStatus(bool isNew, bool isUnread); @@ -89,7 +83,8 @@ private: private: bool mInFill; bool mCloseOnRead; - bool mLoaded; + + LoadingStatus mLoadingStatus; bool mLoadingMessage; bool mLoadingGroup; @@ -98,6 +93,7 @@ private: RsGroupMetaData mGroupMeta; RsWirePulse mPulse; + RsWireGroup mGroup; /** Qt Designer generated object */ Ui::WireNotifyPostItem *ui; diff --git a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.ui b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.ui index 46d2b5332..fbbf716cb 100644 --- a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.ui +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.ui @@ -165,28 +165,28 @@
    - - - - - 11 - false - true - - - - TextLabel - - - true - - - 8 + + + + + 11 + false + true + + + + TextLabel + + + true + + + @@ -212,78 +212,6 @@ - - - - - true - - - - 0 - - - - - - - I like this - - - - - - - - - - I dislike this - - - - - - - - - - Qt::FocusPolicy::NoFocus - - - Download - - - false - - - - - - - Qt::FocusPolicy::NoFocus - - - Play - - - - - - - Comments - - - - - - - fileLabel - - - Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter - - - diff --git a/retroshare-gui/src/gui/feeds/WirePostItem.cpp b/retroshare-gui/src/gui/feeds/WirePostItem.cpp deleted file mode 100644 index ece70f37c..000000000 --- a/retroshare-gui/src/gui/feeds/WirePostItem.cpp +++ /dev/null @@ -1,693 +0,0 @@ -/******************************************************************************* - * gui/feeds/WirePostItem.cpp * - * * - * Copyright (c) 2012, Robert Fernie * - * * - * 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 "WirePostItem.h" -#include "ui_WirePostItem.h" - -#include "FeedHolder.h" -#include "util/qtthreadsutils.h" -#include "gui/RetroShareLink.h" -#include "gui/common/FilesDefs.h" -#include "gui/gxs/GxsIdDetails.h" -#include "util/stringutil.h" -#include "util/DateTime.h" -#include "util/misc.h" - -#include -#include - -/**** - * #define DEBUG_ITEM 1 - ****/ - -WirePostItem::WirePostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set &older_versions) : - GxsFeedItem(feedHolder, feedId, groupId, messageId, isHome, rsWire, autoUpdate) // this one should be in GxsFeedItem -{ - QVector v; - //bool self = false; - - for(std::set::const_iterator it(older_versions.begin());it!=older_versions.end();++it) - v.push_back(*it) ; - - if(older_versions.find(messageId) == older_versions.end()) - v.push_back(messageId); - - mLoadingStatus = LOADING_STATUS_NO_DATA; - mLoadingMessage = false; - mLoadingGroup = false; - mLoadingComment = false; - - setMessageVersions(v) ; - setup(); -} - -void WirePostItem::paintEvent(QPaintEvent *e) -{ - /* This method employs a trick to trigger a deferred loading. The post and group is requested only - * when actually displayed on the screen. */ - - if(mLoadingStatus != LOADING_STATUS_FILLED && !mGroupMeta.mGroupId.isNull() && !mPulse.mMeta.mMsgId.isNull() ) - mLoadingStatus = LOADING_STATUS_HAS_DATA; - - if(mGroupMeta.mGroupId.isNull() && !mLoadingGroup) - requestGroup(); - - if(mPulse.mMeta.mMsgId.isNull() && !mLoadingMessage) - requestMessage(); - - switch(mLoadingStatus) - { - case LOADING_STATUS_FILLED: - case LOADING_STATUS_NO_DATA: - default: - break; - - case LOADING_STATUS_HAS_DATA: - fill(); - mLoadingStatus = LOADING_STATUS_FILLED; - break; - } - - GxsFeedItem::paintEvent(e) ; -} - -WirePostItem::~WirePostItem() -{ - auto timeout = std::chrono::steady_clock::now() + std::chrono::milliseconds(GROUP_ITEM_LOADING_TIMEOUT_ms); - - while( (mLoadingGroup || mLoadingMessage) - && std::chrono::steady_clock::now() < timeout) - { - RsDbg() << __PRETTY_FUNCTION__ << " is Waiting for " - << (mLoadingGroup ? "Group " : "") - << (mLoadingMessage ? "Message " : "") - << "loading." << std::endl; - std::this_thread::sleep_for(std::chrono::milliseconds(100)); - } - - delete ui; -} - -bool WirePostItem::isUnread() const -{ - return IS_MSG_UNREAD(mPulse.mMeta.mMsgStatus) ; -} - -void WirePostItem::setup() -{ - /* Invoke the Qt Designer generated object setup routine */ - - ui = new Ui::WirePostItem; - ui->setupUi(this); - - // Manually set icons to allow to use clever resource sharing that is missing in Qt for Icons loaded from Qt resource file. - // This is particularly important here because a wire may contain many posts, so duplicating the QImages here is deadly for the - // memory. - -// ui->logoLabel->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/thumb-default-video.png")); - //ui->warn_image_label->setPixmap(FilesDefs::getPixmapFromQtResourcePath(":/images/status_unknown.png")); - ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); -// ui->voteUpButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/vote_up.png")); -// ui->voteDownButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/vote_down.png")); -// ui->downloadButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/download.png")); -// ui->playButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/play.png")); - ui->commentButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/comment.png")); - //ui->editButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/pencil-edit-button.png")); -// ui->copyLinkButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/copy.png")); -// ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/down-arrow.png")); -// ui->readAndClearButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/correct.png")); -// ui->clearButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/icons/png/exit2.png")); - - setAttribute(Qt::WA_DeleteOnClose, true); - - mCloseOnRead = false; - - /* clear ui */ - ui->titleLabel->setText(tr("Loading...")); - ui->titleLabel->setOpenExternalLinks(false); //To get linkActivated working - connect(ui->titleLabel, SIGNAL(linkActivated(QString)), this, SLOT(on_linkActivated(QString))); - ui->datetimelabel->clear(); - ui->filelabel->clear(); -// ui->newCommentLabel->hide(); -// ui->commLabel->hide(); - - /* general ones */ - connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(toggle())); - connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(removeItem())); - - /* specific */ - connect(ui->readAndClearButton, SIGNAL(clicked()), this, SLOT(readAndClearItem())); - connect(ui->unsubscribeButton, SIGNAL(clicked()), this, SLOT(unsubscribeChannel())); - - connect(ui->downloadButton, SIGNAL(clicked()), this, SLOT(download())); - // HACK FOR NOW. - ui->commentButton->hide();// hidden until properly enabled. - connect(ui->commentButton, SIGNAL(clicked()), this, SLOT(loadComments())); - - connect(ui->playButton, SIGNAL(clicked()), this, SLOT(play(void))); - //connect(ui->editButton, SIGNAL(clicked()), this, SLOT(edit(void))); - connect(ui->copyLinkButton, SIGNAL(clicked()), this, SLOT(copyMessageLink())); - - connect(ui->readButton, SIGNAL(toggled(bool)), this, SLOT(readToggled(bool))); - - // hide voting buttons, backend is not implemented yet - ui->voteUpButton->hide(); - ui->voteDownButton->hide(); - - ui->scoreLabel->hide(); - - // hide unsubscribe button not necessary - ui->unsubscribeButton->hide(); - - ui->downloadButton->hide(); - ui->playButton->hide(); - //ui->warn_image_label->hide(); - //ui->warning_label->hide(); - - ui->titleLabel->setMinimumWidth(100); - ui->subjectLabel->setMinimumWidth(100); - //ui->warning_label->setMinimumWidth(100); - ui->titleLabel->setEnabled(false); - - ui->feedFrame->setProperty("new", false); - ui->feedFrame->style()->unpolish(ui->feedFrame); - ui->feedFrame->style()->polish( ui->feedFrame); - - ui->expandFrame->hide(); -} - -QString WirePostItem::groupName() -{ - return QString::fromUtf8(mGroupMeta.mGroupName.c_str()); -} - -void WirePostItem::loadGroup() -{ -#ifdef DEBUG_ITEM - std::cerr << "WireNotifyGroupItem::loadGroup()"; - std::cerr << std::endl; -#endif - - mLoadingGroup = true; - - RsThread::async([this]() - { - // 1 - get group data - - std::vector groups; - const std::list groupIds = { groupId() }; - - if(!rsWire->getGroups(groupIds,groups)) // would be better to call channel Summaries for a single group - { - RsErr() << "WirePostItem::loadGroup() ERROR getting data" << std::endl; - mLoadingGroup = false; - return; - } - - if (groups.size() != 1) - { - std::cerr << "WirePostItem::loadGroup() Wrong number of Items"; - std::cerr << std::endl; - mLoadingGroup = false; - return; - } - - RsWireGroup group(groups[0]); - - RsQThreadUtils::postToObject( [group,this]() - { - /* Here it goes any code you want to be executed on the Qt Gui - * thread, for example to update the data model with new information - * after a blocking call to RetroShare API complete */ - - mGroupMeta = group.mMeta; - mLoadingGroup = false; - - update(); // this triggers a paintEvent if needed. - - }, this ); - }); -} - -void WirePostItem::loadMessage() -{ -#ifdef DEBUG_ITEM - std::cerr << "WirePostItem::loadMessage()"; - std::cerr << std::endl; -#endif - mLoadingMessage = true; - - RsThread::async([this]() - { - // 1 - get group data - - std::list groupIds; - std::list pulses; -// std::vector comments; -// std::vector votes; - //groupIds.push_back(groupId()); - - if(! rsWire->getPulsesForGroups(groupIds, pulses)) - { - RsErr() << "WirePostItem::loadMessage() ERROR getting data" << std::endl; - mLoadingMessage = false; - return; - } - - if (pulses.size() == 1) - { -#ifdef DEBUG_ITEM - std::cerr << (void*)this << ": Obtained post, with msgId = " << pulses[0].mMeta.mMsgId << std::endl; -#endif - const RsWirePulse& pulse(*pulses.front()); - - RsQThreadUtils::postToObject( [pulse,this]() - { - mPulse = pulse; - mLoadingMessage = false; - update(); // this triggers a paintEvent if needed. - }, this ); - } - -// else if(comments.size() == 1) -// { -// const RsGxsComment& cmt = comments[0]; -//#ifdef DEBUG_ITEM -// std::cerr << (void*)this << ": Obtained comment, setting messageId to threadID = " << cmt.mMeta.mThreadId << std::endl; -//#endif - -// RsQThreadUtils::postToObject( [cmt,this]() -// { -// 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(); - -// mLoadingMessage = false; -// }, this ); - -// } -// else -// { -//#ifdef DEBUG_ITEM -// std::cerr << "WirePostItem::loadMessage() Wrong number of Items. Remove It."; -// std::cerr << std::endl; -//#endif - -// RsQThreadUtils::postToObject( [this]() -// { -// removeItem(); -// mLoadingMessage = false; -// }, this ); -// } - }); -} - -void WirePostItem::loadComment() -{ -#ifdef DEBUG_ITEM - std::cerr << "WirePostItem::loadComment()"; - std::cerr << std::endl; -#endif -// mLoadingComment = true; - -// RsThread::async([this]() -// { -// // 1 - get group data - -// std::set msgIds; - -// for(auto MsgId: messageVersions()) -// msgIds.insert(MsgId); - -// std::vector posts; -// std::vector comments; - -// if(! rsGxsChannels->getChannelComments( groupId(),msgIds,comments)) -// { -// RsErr() << "GxsGxsChannelGroupItem::loadGroup() ERROR getting data" << std::endl; -// return; -// } - -// int comNb = comments.size(); - -// RsQThreadUtils::postToObject( [comNb,this]() -// { -// 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); -// mLoadingComment = false; - -// }, this ); -// }); -} - - -void WirePostItem::fill() -{ -#ifdef DEBUG_ITEM - std::cerr << "WirePostItem::fill()"; - std::cerr << std::endl; -#endif - - QString title; - QString msgText; - - ui->groupName->setText(QString::fromStdString(mGroup.mMeta.mGroupName)); - ui->groupName->setToolTip(QString::fromStdString(mGroup.mMeta.mGroupName) + "@" + QString::fromStdString(mGroup.mMeta.mAuthorId.toStdString())); - - if (mGroup.mHeadshot.mData ) - { - QPixmap pixmap; - if (GxsIdDetails::loadPixmapFromData( - mGroup.mHeadshot.mData, - mGroup.mHeadshot.mSize, - pixmap,GxsIdDetails::ORIGINAL)) - { - ui->logoLabel->setPixmap(pixmap); - } - } - else{ - // default. - QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png"); - ui->logoLabel->setPixmap(pixmap); - } - - if (!mIsHome) - { - if (mCloseOnRead && !IS_MSG_NEW(mPulse.mMeta.mMsgStatus)) { - removeItem(); - } - - title = tr("Wire Feed") + ": "; - RetroShareLink link = RetroShareLink::createGxsGroupLink(RetroShareLink::TYPE_WIRE, mGroup.mMeta.mGroupId, groupName()); - title += link.toHtml(); - ui->titleLabel->setText(title); - - msgText = tr("Pulse") + ": "; - RetroShareLink msgLink = RetroShareLink::createGxsMessageLink(RetroShareLink::TYPE_WIRE, mPulse.mMeta.mGroupId, mPulse.mMeta.mMsgId, messageName()); - msgText += msgLink.toHtml(); - ui->subjectLabel->setText(msgText); - - ui->pulseMessage->setText(QString::fromUtf8(mPulse.mPulseText.c_str())); - ui->datetimelabel->setText(DateTime::formatLongDateTime(mPulse.mRefPublishTs)); - - if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) - { - ui->unsubscribeButton->setEnabled(true); - } - else - { - ui->unsubscribeButton->setEnabled(false); - } - ui->readButton->hide(); - ui->newLabel->hide(); - ui->copyLinkButton->hide(); - - if (IS_MSG_NEW(mPulse.mMeta.mMsgStatus)) { - mCloseOnRead = true; - } - } - else - { - - /* disable buttons: deletion facility not enabled with cache services yet */ - ui->clearButton->setEnabled(false); - ui->unsubscribeButton->setEnabled(false); - ui->clearButton->hide(); - ui->readAndClearButton->hide(); - ui->unsubscribeButton->hide(); - ui->copyLinkButton->show(); - - if (IS_GROUP_SUBSCRIBED(mGroupMeta.mSubscribeFlags) || IS_GROUP_ADMIN(mGroupMeta.mSubscribeFlags)) - { - ui->readButton->setVisible(true); - - setReadStatus(IS_MSG_NEW(mPulse.mMeta.mMsgStatus), IS_MSG_UNREAD(mPulse.mMeta.mMsgStatus) || IS_MSG_NEW(mPulse.mMeta.mMsgStatus)); - } - else - { - ui->readButton->setVisible(false); - ui->newLabel->setVisible(false); - } - - mCloseOnRead = false; - } - - // differences between Feed or Top of Comment. - if (mFeedHolder) - { - if (mIsHome) { - ui->commentButton->show(); - } else if (ui->commentButton->icon().isNull()){ - //Icon is seted if a comment received. - ui->commentButton->hide(); - } - -// THIS CODE IS doesn't compile - disabling until fixed. -#if 0 - if (post.mComments) - { - QString commentText = QString::number(post.mComments); - commentText += " "; - commentText += tr("Comments"); - ui->commentButton->setText(commentText); - } - else - { - ui->commentButton->setText(tr("Comment")); - } -#endif - - } - else - { - ui->commentButton->hide(); - } - - // disable voting buttons - if they have already voted. - /*if (post.mMeta.mMsgStatus & GXS_SERV::GXS_MSG_STATUS_VOTE_MASK) - { - voteUpButton->setEnabled(false); - voteDownButton->setEnabled(false); - }*/ - -// { -// QTextDocument doc; -// doc.setHtml( QString::fromUtf8(mPulse.mMsg.c_str()) ); - -// ui->msgFrame->setVisible(doc.toPlainText().length() > 0); -// } - -// if (wasExpanded() || ui->expandFrame->isVisible()) { -// fillExpandFrame(); -// } - -// if ( (mPulse.mAttachmentCount != 0) || (mPulse.mSize != 0) ) { -// ui->filelabel->setVisible(true); -// ui->filelabel->setText(QString("(%1 %2) %3").arg(mPulse.mAttachmentCount).arg( (mPulse.mAttachmentCount > 1)?tr("Files"):tr("File")).arg(misc::friendlyUnit(mPulse.mSize))); -// } else { -// ui->filelabel->setVisible(false); -// } - -// if (mFileItems.empty() == false) { -// std::list::iterator it; -// for(it = mFileItems.begin(); it != mFileItems.end(); ++it) -// { -// delete(*it); -// } -// mFileItems.clear(); -// } - -// std::list::const_iterator it; -// for(it = mPulse.mFiles.begin(); it != mPulse.mFiles.end(); ++it) -// { -// /* add file */ -// std::string path; -// SubFileItem *fi = new SubFileItem(it->mHash, it->mName, path, it->mSize, SFI_STATE_REMOTE | SFI_TYPE_CHANNEL, RsPeerId()); -// mFileItems.push_back(fi); - -// /* check if the file is a media file */ -// if (!misc::isPreviewable(QFileInfo(QString::fromUtf8(it->mName.c_str())).suffix())) -// { -// fi->mediatype(); -// /* check if the file is not a media file and change text */ -// ui->playButton->setText(tr("Open")); -// ui->playButton->setToolTip(tr("Open File")); -// } else { -// ui->playButton->setText(tr("Play")); -// ui->playButton->setToolTip(tr("Play Media")); -// } - -// QLayout *layout = ui->expandFrame->layout(); -// layout->addWidget(fi); -// } - -} - -QString WirePostItem::messageName() -{ - return QString::fromUtf8(mPulse.mMeta.mMsgName.c_str()); -} - - -void WirePostItem::doExpand(bool open) -{ - if (mFeedHolder) - { - mFeedHolder->lockLayout(this, true); - } - - if (open) - { - ui->expandFrame->show(); - ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/up-arrow.png"))); - ui->expandButton->setToolTip(tr("Hide")); - -// readToggled(false); - } - else - { - ui->expandFrame->hide(); - ui->expandButton->setIcon(FilesDefs::getIconFromQtResourcePath(QString(":/icons/png/down-arrow.png"))); - ui->expandButton->setToolTip(tr("Expand")); - } - - emit sizeChanged(this); - - if (mFeedHolder) - { - mFeedHolder->lockLayout(this, false); - } -} - - -void WirePostItem::setReadStatus(bool isNew, bool isUnread) -{ - if (isNew) - mPulse.mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_NEW; - else - mPulse.mMeta.mMsgStatus &= ~GXS_SERV::GXS_MSG_STATUS_GUI_NEW; - - if (isUnread) - { - mPulse.mMeta.mMsgStatus |= GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - whileBlocking(ui->readButton)->setChecked(true); - ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-unread.png")); - } - else - { - mPulse.mMeta.mMsgStatus &= ~GXS_SERV::GXS_MSG_STATUS_GUI_UNREAD; - whileBlocking(ui->readButton)->setChecked(false); - ui->readButton->setIcon(FilesDefs::getIconFromQtResourcePath(":/images/message-state-read.png")); - } - - //ui->newLabel->setVisible(isNew); - - //ui->feedFrame->setProperty("new", isNew); - //ui->feedFrame->style()->unpolish(ui->feedFrame); - //ui->feedFrame->style()->polish( ui->feedFrame); -} - -/*void WirePostItem::setGroup(const RsWireGroup &group) -{ - ui->groupName->setText(QString::fromStdString(group.mMeta.mGroupName)); - ui->groupName->setToolTip(QString::fromStdString(group.mMeta.mGroupName) + "@" + QString::fromStdString(group.mMeta.mAuthorId.toStdString())); - - QString title; - - title = tr("Wire Feed") + ": "; - RetroShareLink link = RetroShareLink::createGxsGroupLink(RetroShareLink::TYPE_WIRE, group.mMeta.mGroupId, groupName()); - title += link.toHtml(); - ui->titleLabel->setText(title); - - if (group.mHeadshot.mData ) - { - QPixmap pixmap; - if (GxsIdDetails::loadPixmapFromData( - group.mHeadshot.mData, - group.mHeadshot.mSize, - pixmap,GxsIdDetails::ORIGINAL)) - { - ui->logoLabel->setPixmap(pixmap); - } - } - else - { - // default. - QPixmap pixmap = FilesDefs::getPixmapFromQtResourcePath(":/icons/wire.png"); - ui->logoLabel->setPixmap(pixmap); - } - -}*/ - -void WirePostItem::expandFill(bool first) -{ - GxsFeedItem::expandFill(first); - - if (first) { -// fillExpandFrame(); - } -} - -/*********** SPECIFIC FUNCTIONS ***********************/ - -void WirePostItem::readAndClearItem() -{ -#ifdef DEBUG_ITEM - std::cerr << "WirePostItem::readAndClearItem()"; - std::cerr << std::endl; -#endif - readToggled(false); - removeItem(); -} - -void WirePostItem::readToggled(bool /*checked*/) -{ - mCloseOnRead = false; - - RsGxsGrpMsgIdPair msgPair = std::make_pair(groupId(), messageId()); - - //rsWire->setMessageReadStatus(msgPair, isUnread()); - - //setReadStatus(false, checked); // Updated by events -} - -void WirePostItem::on_linkActivated(QString link) -{ - RetroShareLink rsLink(link); - - if (rsLink.valid() ) { - QList rsLinks; - rsLinks.append(rsLink); - RetroShareLink::process(rsLinks); - removeItem(); - return; - } -} diff --git a/retroshare-gui/src/gui/feeds/WirePostItem.h b/retroshare-gui/src/gui/feeds/WirePostItem.h deleted file mode 100644 index f0c295935..000000000 --- a/retroshare-gui/src/gui/feeds/WirePostItem.h +++ /dev/null @@ -1,108 +0,0 @@ -/******************************************************************************* - * gui/feeds/WirePostItem.h * - * * - * Copyright (c) 2012, Robert Fernie * - * * - * 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 WirePostItem_H -#define WirePostItem_H - -#include -#include - -#include -#include "gui/gxs/GxsFeedItem.h" -#include "gui/gxs/GxsGroupFeedItem.h" - -namespace Ui { -class WirePostItem; -} - -class FeedHolder; -class SubFileItem; - -class WirePostItem : public GxsFeedItem -{ - Q_OBJECT - -public: - // This one is used in NewFeed for incoming Wire posts. Only the group and msg ids are known at this point. - // It can be used for all apparences of wire posts. But in rder to merge comments from the previous versions of the post, the list of - // previous posts should be supplied. It's optional. If not supplied only the comments of the new version will be displayed. - WirePostItem(FeedHolder *feedHolder, uint32_t feedId, const RsGxsGroupId& groupId, const RsGxsMessageId &messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); - -#ifdef UNUSED - WirePostItem(FeedHolder *parent, uint32_t feedId, const RsGroupMetaData& group_meta, const RsGxsMessageId& messageId, bool isHome, bool autoUpdate, const std::set& older_versions = std::set()); - //WirePostItem(FeedHolder *feedHolder, uint32_t feedId, const RsWireGroup &group, bool isHome, bool autoUpdate); -#endif - - virtual ~WirePostItem(); - - uint64_t uniqueIdentifier() const override { return hash_64bits("WirePostItem " + messageId().toStdString()); } - - bool isUnread() const ; - void setReadStatus(bool isNew, bool isUnread); - -protected: - - /* FeedItem */ - virtual void doExpand(bool open); - virtual void expandFill(bool first); - - virtual void paintEvent(QPaintEvent *) override; - - /* GxsGroupFeedItem */ - virtual QString groupName(); - virtual void loadGroup() override; - virtual RetroShareLink::enumType getLinkType() { return RetroShareLink::TYPE_WIRE; } - - /* GxsFeedItem */ -// virtual QString messageName(); - virtual void loadMessage(); - virtual void loadComment(); - virtual QString messageName() override; - -private slots: - /* default stuff */ - //void toggle() override; - void readAndClearItem(); - void readToggled(bool checked); - - void on_linkActivated(QString link); -private: - void setup(); - void fill(); - -private: - bool mCloseOnRead; - - LoadingStatus mLoadingStatus; - - bool mLoadingMessage; - bool mLoadingGroup; - bool mLoadingComment; - - RsGroupMetaData mGroupMeta; - RsWirePulse mPulse; - RsWireGroup mGroup; - - /** Qt Designer generated object */ - Ui::WirePostItem *ui; -}; - -Q_DECLARE_METATYPE(RsWirePulse) - -#endif // WirePostItem_H diff --git a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp index dea307387..ef2089b4c 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp @@ -33,6 +33,7 @@ #include "gui/common/RSTreeWidget.h" #include "gui/common/UIStateHelper.h" #include "gui/common/UserNotify.h" +#include "gui/RsGUIEventManager.h" #include "util/qtthreadsutils.h" #include "retroshare/rsgxsifacetypes.h" #include "GxsCommentDialog.h" @@ -71,7 +72,7 @@ static const uint32_t DELAY_BETWEEN_GROUP_STATISTICS_UPDATE = 120; // do not upd /** Constructor */ GxsGroupFrameDialog::GxsGroupFrameDialog(RsGxsIfaceHelper *ifaceImpl,const QString& settings_name, QWidget *parent,bool allow_dist_sync) -: GxsStatisticsProvider(ifaceImpl,settings_name,parent) +: MainPage(parent), mSettingsName(settings_name) { /* Invoke the Qt Designer generated object setup routine */ ui = new Ui::GxsGroupFrameDialog(); @@ -172,7 +173,7 @@ void GxsGroupFrameDialog::initUi() processSettings(true); if (groupFrameSettingsType() != GroupFrameSettings::Nothing) { - //connect(NotifyQt::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); + connect(RsGUIEventManager::getInstance(), SIGNAL(settingsChanged()), this, SLOT(settingsChanged())); settingsChanged(); } diff --git a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.h b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.h index 055be83da..c2d75a23c 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.h +++ b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.h @@ -45,7 +45,7 @@ class UIStateHelper; struct RsGxsCommentService; class GxsCommentDialog; -class GxsGroupFrameDialog : public GxsStatisticsProvider +class GxsGroupFrameDialog : public MainPage, public GxsStatisticsProvider { Q_OBJECT @@ -75,13 +75,13 @@ public: GxsGroupFrameDialog(RsGxsIfaceHelper *ifaceImpl, const QString& settings_name,QWidget *parent = 0,bool allow_dist_sync=false); virtual ~GxsGroupFrameDialog(); - virtual bool navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msgId) override; + virtual bool navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msgId); virtual QString getHelpString() const =0; virtual void getGroupList(std::map &groups) ; - void getServiceStatistics(GxsServiceStatistic& stats) const ; + void getServiceStatistics(GxsServiceStatistic& stats) const override; static uint32_t checkDelay(uint32_t time_in_secs); @@ -182,7 +182,7 @@ private: // subscribe/unsubscribe ack. - virtual GxsMessageFrameWidget *messageWidget(const RsGxsGroupId &groupId) override; + virtual GxsMessageFrameWidget *messageWidget(const RsGxsGroupId &groupId); GxsMessageFrameWidget *createMessageWidget(const RsGxsGroupId &groupId); GxsCommentDialog *commentWidget(const RsGxsMessageId &msgId); @@ -191,8 +191,22 @@ protected: void updateSearchResults(const TurtleRequestId &sid); void updateSearchResults(); // update all searches - virtual void updateGroupStatistics(const RsGxsGroupId &groupId) override; - virtual void updateGroupStatisticsReal(const RsGxsGroupId &groupId) override; + virtual void updateGroupStatistics(const RsGxsGroupId &groupId); + virtual void updateGroupStatisticsReal(const RsGxsGroupId &groupId); + + // This needs to be overloaded by subclasses, possibly calling the blocking API, since it is used asynchronously. + virtual bool getGroupStatistics(const RsGxsGroupId& groupId, GxsGroupStatistic& stat) = 0; + + QString mSettingsName; + RsGxsIfaceHelper *mInterface; + bool mDistSyncAllowed; + std::map mCachedGroupStats; + bool mShouldUpdateGroupStatistics; + std::set mGroupStatisticsToUpdate; + bool mCountChildMsgs; + RsGxsGroupId mNavigatePendingGroupId; + RsGxsMessageId mNavigatePendingMsgId; + UIStateHelper *mStateHelper; private: GxsMessageFrameWidget *currentWidget() const; diff --git a/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.cpp b/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.cpp index 54766a251..47a77e983 100644 --- a/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.cpp +++ b/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.cpp @@ -18,43 +18,4 @@ * * *******************************************************************************/ -#include -#include -#include - #include "GxsStatisticsProvider.h" - -#include "gui/common/UserNotify.h" -#include "util/qtthreadsutils.h" -#include "retroshare/rsgxsifacetypes.h" - -#define TOKEN_TYPE_GROUP_SUMMARY 1 -//#define TOKEN_TYPE_SUBSCRIBE_CHANGE 2 -//#define TOKEN_TYPE_CURRENTGROUP 3 -#define TOKEN_TYPE_STATISTICS 4 - -#define MAX_COMMENT_TITLE 32 - -static const uint32_t DELAY_BETWEEN_GROUP_STATISTICS_UPDATE = 120; // do not update group statistics more often than once every 2 mins - -/* - * Transformation Notes: - * there are still a couple of things that the new groups differ from Old version. - * these will need to be addressed in the future. - * -> Child TS (for sorting) is not handled by GXS, this will probably have to be done in the GUI. - * -> Need to handle IDs properly. - * -> Much more to do. - */ - -/** Constructor */ -GxsStatisticsProvider::GxsStatisticsProvider(RsGxsIfaceHelper *ifaceImpl,const QString& settings_name, QWidget *parent,bool allow_dist_sync) -: MainPage(parent),mSettingsName(settings_name) -{ - mDistSyncAllowed = allow_dist_sync; - mInterface = ifaceImpl; - mShouldUpdateGroupStatistics = false; -} - -GxsStatisticsProvider::~GxsStatisticsProvider() -{ -} diff --git a/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.h b/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.h index ade29b1e8..3309e795b 100644 --- a/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.h +++ b/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.h @@ -21,58 +21,15 @@ #ifndef GXSSTATISTICSPROVIDER_H #define GXSSTATISTICSPROVIDER_H -#include +#include "retroshare/rsgxsifacetypes.h" -#include "gui/gxs/RsGxsUpdateBroadcastPage.h" -#include "gui/RetroShareLink.h" -#include "gui/settings/rsharesettings.h" -#include "util/RsUserdata.h" +// Interface for GxsUserNotify to query service statistics. -#include - -#include "GxsIdTreeWidgetItem.h" -#include "GxsGroupDialog.h" - -class GroupTreeWidget; -class GroupItemInfo; -class GxsMessageFrameWidget; -class UIStateHelper; -struct RsGxsCommentService; -class GxsCommentDialog; - -class GxsStatisticsProvider : public MainPage +class GxsStatisticsProvider { - Q_OBJECT - public: - GxsStatisticsProvider(RsGxsIfaceHelper *ifaceImpl, const QString& settings_name,QWidget *parent = 0,bool allow_dist_sync=false); - virtual ~GxsStatisticsProvider(); - + virtual ~GxsStatisticsProvider() = default; virtual void getServiceStatistics(GxsServiceStatistic& stats) const = 0; - virtual bool navigate(const RsGxsGroupId &groupId, const RsGxsMessageId& msgId) = 0; - -protected: - virtual void updateGroupStatistics(const RsGxsGroupId &groupId) = 0; - virtual void updateGroupStatisticsReal(const RsGxsGroupId &groupId) = 0; - - // This needs to be overloaded by subsclasses, possibly calling the blocking API, since it is used asynchroneously. - virtual bool getGroupStatistics(const RsGxsGroupId& groupId,GxsGroupStatistic& stat) = 0; - - virtual GxsMessageFrameWidget *messageWidget(const RsGxsGroupId &groupId) = 0; - - QString mSettingsName; - RsGxsIfaceHelper *mInterface; - bool mDistSyncAllowed; - std::map mCachedGroupStats; - bool mShouldUpdateGroupStatistics; - std::set mGroupStatisticsToUpdate; - bool mCountChildMsgs; // Count unread child messages? - - RsGxsGroupId mNavigatePendingGroupId; - RsGxsMessageId mNavigatePendingMsgId; - UIStateHelper *mStateHelper; - -private: - virtual QString settingsGroupName() = 0; }; + #endif // GXSSTATISTICSPROVIDER_H diff --git a/retroshare-gui/src/gui/gxs/GxsUserNotify.h b/retroshare-gui/src/gui/gxs/GxsUserNotify.h index a42ec69c4..27f5099e2 100644 --- a/retroshare-gui/src/gui/gxs/GxsUserNotify.h +++ b/retroshare-gui/src/gui/gxs/GxsUserNotify.h @@ -24,7 +24,6 @@ #include #include "gui/common/UserNotify.h" #include "gui/gxs/GxsStatisticsProvider.h" -#include "gui/gxs/GxsGroupFrameDialog.h" class RsGxsIfaceHelper; class RsGxsUpdateBroadcastBase; diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.h b/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.h index 7dab607be..0e8f9e6b5 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.h +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.h @@ -71,7 +71,7 @@ private: /* GxsGroupFrameDialog */ virtual QString text(TextType type) override; virtual QString icon(IconType type) override; - virtual QString settingsGroupName() override { return "ChannelDialog"; } + virtual QString settingsGroupName() { return "ChannelDialog"; } virtual GxsGroupDialog *createNewGroupDialog() override; virtual GxsGroupDialog *createGroupDialog(GxsGroupDialog::Mode mode, RsGxsGroupId groupId) override; virtual int shareKeyType() override; diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelUserNotify.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelUserNotify.cpp index ce88231fc..46c5afaab 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelUserNotify.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelUserNotify.cpp @@ -23,7 +23,7 @@ #include "gui/MainWindow.h" #include "gui/common/FilesDefs.h" -GxsChannelUserNotify::GxsChannelUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsGroupFrameDialog *g, QObject *parent) : +GxsChannelUserNotify::GxsChannelUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsStatisticsProvider *g, QObject *parent) : GxsUserNotify(ifaceImpl, g, parent) { } diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelUserNotify.h b/retroshare-gui/src/gui/gxschannels/GxsChannelUserNotify.h index 2604f5d34..94a787e91 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelUserNotify.h +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelUserNotify.h @@ -22,14 +22,13 @@ #define GXSCHANNELUSERNOTIFY_H #include "gui/gxs/GxsUserNotify.h" -#include "gui/gxs/GxsGroupFrameDialog.h" class GxsChannelUserNotify : public GxsUserNotify { Q_OBJECT public: - explicit GxsChannelUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsGroupFrameDialog *g, QObject *parent = 0); + explicit GxsChannelUserNotify(RsGxsIfaceHelper *ifaceImpl, const GxsStatisticsProvider *g, QObject *parent = 0); virtual bool hasSetting(QString *name, QString *group) override; diff --git a/retroshare-gui/src/gui/gxsforums/GxsForumsDialog.h b/retroshare-gui/src/gui/gxsforums/GxsForumsDialog.h index 75d10a1e1..24bb5e057 100644 --- a/retroshare-gui/src/gui/gxsforums/GxsForumsDialog.h +++ b/retroshare-gui/src/gui/gxsforums/GxsForumsDialog.h @@ -53,7 +53,7 @@ private: /* GxsGroupFrameDialog */ QString text(TextType type)override ; QString icon(IconType type)override ; - QString settingsGroupName() override { return "ForumsDialog"; } + QString settingsGroupName() { return "ForumsDialog"; } GxsGroupDialog *createNewGroupDialog() override; GxsGroupDialog *createGroupDialog(GxsGroupDialog::Mode mode, RsGxsGroupId groupId) override; diff --git a/retroshare-gui/src/gui/settings/rsharesettings.cpp b/retroshare-gui/src/gui/settings/rsharesettings.cpp index bb69af532..2c1f28598 100644 --- a/retroshare-gui/src/gui/settings/rsharesettings.cpp +++ b/retroshare-gui/src/gui/settings/rsharesettings.cpp @@ -1119,8 +1119,8 @@ static QString groupFrameSettingsTypeToString(GroupFrameSettings::Type type) case GroupFrameSettings::Posted: return "Posted"; #ifdef RS_USE_WIRE - case GroupFrameSettings::Wire: - return "Wire" ; + case GroupFrameSettings::Wire: + return "Wire"; #endif } diff --git a/retroshare-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index 4f2da7bff..b33ada159 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -623,7 +623,6 @@ HEADERS += rshare.h \ gui/NetworkDialog/pgpid_item_model.h \ gui/NetworkDialog/pgpid_item_proxy.h \ gui/common/RsCollection.h \ - gui/common/NotifyWidget.h \ util/retroshareWin32.h FORMS += gui/StartDialog.ui \ @@ -717,7 +716,6 @@ FORMS += gui/StartDialog.ui \ gui/common/RsCollectionDialog.ui \ gui/common/HeaderFrame.ui \ gui/common/RSFeedWidget.ui \ - gui/common/NotifyWidget.ui \ gui/style/StyleDialog.ui \ gui/statistics/BandwidthGraphWindow.ui \ gui/statistics/BandwidthStatsWidget.ui \ @@ -895,7 +893,6 @@ SOURCES += main.cpp \ gui/common/FlowLayout.cpp \ gui/common/PictureFlow.cpp \ gui/common/ToasterNotify.cpp \ - gui/common/NotifyWidget.cpp \ gui/style/RSStyle.cpp \ gui/style/StyleDialog.cpp \ gui/settings/RSPermissionMatrixWidget.cpp \