From 212197f9808a700a2d083687c10ec372b7ce7d9d Mon Sep 17 00:00:00 2001 From: defnax Date: Wed, 12 Mar 2025 20:35:16 +0100 Subject: [PATCH] rework on notify for wire posts --- retroshare-gui/src/CMakeLists.txt | 17 +- retroshare-gui/src/gui/MainWindow.cpp | 7 + retroshare-gui/src/gui/MainWindow.h | 7 +- retroshare-gui/src/gui/NewsFeed.cpp | 47 +- 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 | 38 + .../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 ++ .../src/gui/feeds/WireNotifyGroupItem.cpp | 238 ++++++ .../src/gui/feeds/WireNotifyGroupItem.h | 71 ++ .../src/gui/feeds/WireNotifyGroupItem.ui | 399 +++++++++ .../src/gui/feeds/WireNotifyPostItem.cpp | 758 ++++++++++++++++++ .../src/gui/feeds/WireNotifyPostItem.h | 106 +++ .../src/gui/feeds/WireNotifyPostItem.ui | 492 ++++++++++++ .../src/gui/gxs/GxsGroupFrameDialog.cpp | 81 +- .../src/gui/gxs/GxsGroupFrameDialog.h | 35 +- .../src/gui/gxs/GxsGroupFrameDialog.ui | 3 +- retroshare-gui/src/gui/gxs/GxsIdDetails.cpp | 7 +- .../src/gui/gxs/GxsStatisticsProvider.cpp | 62 ++ .../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 | 15 + retroshare-gui/src/gui/settings/NotifyPage.ui | 23 +- .../src/gui/settings/rsharesettings.cpp | 10 + .../src/gui/settings/rsharesettings.h | 2 +- retroshare-gui/src/retroshare-gui.pro | 42 +- 42 files changed, 3276 insertions(+), 134 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/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 b936552ed..0297e1899 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 b1e4b1e69..9bf98cfe3 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -1073,6 +1073,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; } @@ -1157,6 +1162,8 @@ void SetForegroundWindowInternal(HWND hWnd) return _instance->postedDialog; case Home: return _instance->homePage; + case Wire: + return _instance->wireDialog; } return NULL; diff --git a/retroshare-gui/src/gui/MainWindow.h b/retroshare-gui/src/gui/MainWindow.h index a7f3013f1..04c7c7e73 100644 --- a/retroshare-gui/src/gui/MainWindow.h +++ b/retroshare-gui/src/gui/MainWindow.h @@ -67,6 +67,7 @@ class BandwidthGraph; class MainPage; class NewsFeed; class UserNotify; +class WireDialog; #ifdef MESSENGER_WINDOW class MessengerWindow; @@ -103,7 +104,8 @@ public: Posted = 11, /** Posted links */ People = 12, /** People page. */ Options = 13, /** People page. */ - Home = 14 /** Home page. */ + Home = 14, /** Home page. */ + Wire = 15 /** Wire page. */ }; @@ -163,7 +165,8 @@ public: GxsChannelDialog *gxschannelDialog ; GxsForumsDialog *gxsforumDialog ; PostedDialog *postedDialog; - + WireDialog *wireDialog; + // ForumsDialog *forumsDialog; // ChannelFeed *channelFeed; Idle *idle; diff --git a/retroshare-gui/src/gui/NewsFeed.cpp b/retroshare-gui/src/gui/NewsFeed.cpp index dc0834e71..b9eff0c08 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" @@ -48,6 +49,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" @@ -81,7 +84,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 */ @@ -127,6 +131,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)); @@ -214,6 +221,10 @@ void NewsFeed::handleEvent_main_thread(std::shared_ptr event) if(event->mType == RsEventType::MAIL_STATUS && (flags & RS_FEED_TYPE_MSG)) handleMailEvent(event); + + if(event->mType == RsEventType::WIRE && (flags & RS_FEED_TYPE_WIRE)) + handleWireEvent(event); + } void NewsFeed::handleMailEvent(std::shared_ptr event) @@ -510,6 +521,40 @@ void NewsFeed::handleSecurityEvent(std::shared_ptr event) NotifyQt::getInstance()->addToaster(RS_POPUP_CONNECT_ATTEMPT, e.mPgpId.toStdString().c_str(), det.location, e.mSslId.toStdString().c_str()); } +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_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_LIKE: + 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::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(uint /*notifyFlags*/) { #ifdef TO_REMOVE diff --git a/retroshare-gui/src/gui/NewsFeed.h b/retroshare-gui/src/gui/NewsFeed.h index 2b246fb4c..59d8b7706 100644 --- a/retroshare-gui/src/gui/NewsFeed.h +++ b/retroshare-gui/src/gui/NewsFeed.h @@ -48,6 +48,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; @@ -106,6 +107,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 0001cd9bc..e1674a0c8 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" @@ -76,7 +77,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" @@ -94,6 +96,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" @@ -291,6 +297,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); @@ -470,7 +489,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; @@ -795,6 +814,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; @@ -888,7 +918,9 @@ QString RetroShareLink::title() const return QString("Forum id: %1").arg(hash()); case TYPE_CHANNEL: return QString("Channel id: %1").arg(hash()); - case TYPE_SEARCH: + case TYPE_WIRE: + return QString("Wire id: %1").arg(hash()); + case TYPE_SEARCH: return QString("Search files"); case TYPE_MESSAGE: @@ -1075,6 +1107,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) @@ -1309,6 +1352,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: @@ -1357,6 +1401,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; @@ -1383,9 +1433,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 @@ -1477,6 +1527,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 @@ -1855,6 +1933,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()) { @@ -2038,3 +2126,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 61c794b11..93b4dd00e 100644 --- a/retroshare-gui/src/gui/RetroShareLink.h +++ b/retroshare-gui/src/gui/RetroShareLink.h @@ -74,7 +74,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..d3f62da7b 100644 --- a/retroshare-gui/src/gui/TheWire/PulseReply.cpp +++ b/retroshare-gui/src/gui/TheWire/PulseReply.cpp @@ -150,6 +150,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/PulseViewItem.cpp b/retroshare-gui/src/gui/TheWire/PulseViewItem.cpp index 5a309f94b..d33c342fc 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/WireNotifyGroupItem.cpp b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp new file mode 100644 index 000000000..0bc40a517 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.cpp @@ -0,0 +1,238 @@ +/******************************************************************************* + * 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/RetroShareLink.h" +#include "gui/gxs/GxsIdDetails.h" +#include "gui/common/FilesDefs.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(); +} + +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); +} + +WireNotifyGroupItem::~WireNotifyGroupItem() +{ + 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->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_FORUMS + 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->nameLabel->setText(groupName()); + + 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")); + } + + if(mGroup.mMeta.mLastPost==0) + ui->infoLastPost->setText(tr("Never")); + else + ui->infoLastPost->setText(DateTime::formatLongDateTime(mGroup.mMeta.mLastPost)); + + //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 (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(); +} diff --git a/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h new file mode 100644 index 000000000..7a401552a --- /dev/null +++ b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.h @@ -0,0 +1,71 @@ +/******************************************************************************* + * 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/gxs/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_UNKNOWN; } + +private slots: + void toggle() override; + void subscribeWire(); + +private: + void fill(); + void setup(); + +private: + RsWireGroup mGroup; + + /** Qt Designer generated object */ + Ui::WireNotifyGroupItem *ui; +}; + +#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..b85573091 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/WireNotifyGroupItem.ui @@ -0,0 +1,399 @@ + + + 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 + true + true + + + + Wire + + + + + + + + 11 + true + true + + + + name + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + true + + + + Last activity + + + + + + + + true + true + + + + TextLabel + + + + + + + + + + + + 0 + 0 + + + + Qt::NoFocus + + + Subscribe to Posted + + + 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..3c2decc1b --- /dev/null +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.cpp @@ -0,0 +1,758 @@ +/******************************************************************************* + * 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 "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 +#include + +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(); +} + +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() +{ + 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->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(); +} + +void WireNotifyPostItem::expandFill(bool first) +{ + GxsFeedItem::expandFill(first); + + if (first) { +// fillExpandFrame(); + } +} + +QString WireNotifyPostItem::messageName() +{ + return QString::fromUtf8(mPulse.mMeta.mMsgName.c_str()); +} + +void WireNotifyPostItem::loadMessage() +{ +#ifdef DEBUG_ITEM + std::cerr << "WireNotifyPostItem::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() << "WireNotifyPostItem::loadGroup() ERROR getting data" << std::endl; + return; + } + + if (pulses.size() == 1) + { +#ifdef DEBUG_ITEM + std::cerr << (void*)this << ": Obtained post, with msgId = " << posts[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 ); + }); +} + +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"<::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************************************"<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); + + 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 + { + /* subject */ + ui->titleLabel->setText(QString::fromUtf8(mPulse.mMeta.mMsgName.c_str())); + + /* 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(); +// } + ui->pulseMessage->setText(QString::fromUtf8(mPulse.mPulseText.c_str())); + ui->datetimelabel->setText(DateTime::formatLongDateTime(mPulse.mRefPublishTs)); + +// 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::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) ; +} + +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())); + + 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 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); +} + +/*********** 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 +} diff --git a/retroshare-gui/src/gui/feeds/WireNotifyPostItem.h b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.h new file mode 100644 index 000000000..12e7a3733 --- /dev/null +++ b/retroshare-gui/src/gui/feeds/WireNotifyPostItem.h @@ -0,0 +1,106 @@ +/******************************************************************************* + * 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/gxs/GxsFeedItem.h" +#include "gui/gxs/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); + + ~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 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); + +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..14239d22a --- /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 + + + + + + + + 11 + 75 + false + true + + + + TextLabel + + + true + + + + + + + + 75 + true + + + + DateTime + + + + + + + New + + + + + + + + + + 11 + + + + TextLabel + + + + + + + 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/gxs/GxsGroupFrameDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp index 069c51b79..4d8f6cca7 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp @@ -71,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(); @@ -466,9 +466,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...")) ; @@ -1151,45 +1149,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()) @@ -1274,3 +1233,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/GxsIdDetails.cpp b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp index b1961a6e6..d854b1f76 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp @@ -95,7 +95,12 @@ void ReputationItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem const QRect r = option.rect; // get pixmap - unsigned int icon_index = qvariant_cast(index.data(Qt::DecorationRole)); + auto v = index.data(Qt::DecorationRole); + + if(!v.canConvert(QVariant::Int)) + return; + + unsigned int icon_index = qvariant_cast(v); if(icon_index > mMaxLevelToDisplay) return ; diff --git a/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.cpp b/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.cpp new file mode 100644 index 000000000..6e71720ca --- /dev/null +++ b/retroshare-gui/src/gui/gxs/GxsStatisticsProvider.cpp @@ -0,0 +1,62 @@ +/******************************************************************************* + * 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/notifyqt.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 ff3771075..2290a3555 100644 --- a/retroshare-gui/src/gui/icons.qrc +++ b/retroshare-gui/src/gui/icons.qrc @@ -345,7 +345,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 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 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 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 newsFlags |= RS_FEED_TYPE_POSTED; + +#ifdef RS_USE_WIRE + if (ui.notify_Wire->isChecked()) + newsFlags |= RS_FEED_TYPE_WIRE; +#endif + #if 0 if (ui.notify_Blogs->isChecked()) newsFlags |= RS_FEED_TYPE_BLOG; @@ -311,6 +321,11 @@ void NotifyPage::load() whileBlocking(ui.notify_Channels)->setChecked(newsflags & RS_FEED_TYPE_CHANNEL); whileBlocking(ui.notify_Forums)->setChecked(newsflags & RS_FEED_TYPE_FORUM); whileBlocking(ui.notify_Posted)->setChecked(newsflags & RS_FEED_TYPE_POSTED); + +#ifdef RS_USE_WIRE + whileBlocking(ui.notify_Wire)->setChecked(newsflags & RS_FEED_TYPE_WIRE); +#endif + #if 0 whileBlocking(ui.notify_Blogs)->setChecked(newsflags & RS_FEED_TYPE_BLOG); #endif 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 e811acd4a..c508a8c51 100644 --- a/retroshare-gui/src/gui/settings/rsharesettings.cpp +++ b/retroshare-gui/src/gui/settings/rsharesettings.cpp @@ -139,6 +139,10 @@ void RshareSettings::initSettings() uint defNotify = (RS_POPUP_CONNECT | RS_POPUP_MSG); uint defNewsFeed = (RS_FEED_TYPE_MSG | RS_FEED_TYPE_FILES | RS_FEED_TYPE_SECURITY | RS_FEED_TYPE_SECURITY_IP | RS_FEED_TYPE_CIRCLE | RS_FEED_TYPE_CHANNEL |RS_FEED_TYPE_FORUM | RS_FEED_TYPE_POSTED); +#ifdef RS_USE_WIRE + defNewsFeed = (defNewsFeed | RS_FEED_TYPE_WIRE); +#endif + setDefault(SETTING_NEWSFEED_FLAGS, defNewsFeed); setDefault(SETTING_CHAT_FLAGS, defChat); setDefault(SETTING_NOTIFY_FLAGS, defNotify); @@ -1109,6 +1113,12 @@ 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 362e52606..b791b11b4 100644 --- a/retroshare-gui/src/gui/settings/rsharesettings.h +++ b/retroshare-gui/src/gui/settings/rsharesettings.h @@ -43,7 +43,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-gui/src/retroshare-gui.pro b/retroshare-gui/src/retroshare-gui.pro index d73117b84..515dddd52 100644 --- a/retroshare-gui/src/retroshare-gui.pro +++ b/retroshare-gui/src/retroshare-gui.pro @@ -116,7 +116,7 @@ CONFIG += gxscircles ## To enable unfinished services #CONFIG += wikipoos -#CONFIG += gxsthewire +CONFIG += gxsthewire #CONFIG += gxsphotoshare DEFINES += RS_RELEASE_VERSION @@ -614,7 +614,8 @@ HEADERS += rshare.h \ gui/NetworkDialog/pgpid_item_model.h \ gui/NetworkDialog/pgpid_item_proxy.h \ gui/common/RsCollection.h \ - util/retroshareWin32.h + util/retroshareWin32.h \ + gui/common/NotifyWidget.h # gui/ForumsDialog.h \ # gui/forums/ForumDetails.h \ # gui/forums/EditForumDetails.h \ @@ -736,8 +737,8 @@ FORMS += gui/StartDialog.ui \ gui/statistics/BwCtrlWindow.ui \ gui/statistics/RttStatistics.ui \ gui/GetStartedDialog.ui \ - util/RichTextEdit.ui - + util/RichTextEdit.ui \ + gui/common/NotifyWidget.ui # gui/ForumsDialog.ui \ # gui/forums/CreateForum.ui \ @@ -982,12 +983,13 @@ SOURCES += main.cpp \ gui/statistics/BwCtrlWindow.cpp \ gui/statistics/RttStatistics.cpp \ gui/statistics/BWGraph.cpp \ - util/RsSyntaxHighlighter.cpp \ - util/imageutil.cpp \ - gui/NetworkDialog/pgpid_item_model.cpp \ - gui/NetworkDialog/pgpid_item_proxy.cpp \ - gui/common/RsCollection.cpp \ - util/retroshareWin32.cpp + util/RsSyntaxHighlighter.cpp \ + util/imageutil.cpp \ + gui/NetworkDialog/pgpid_item_model.cpp \ + gui/NetworkDialog/pgpid_item_proxy.cpp \ + gui/common/RsCollection.cpp \ + util/retroshareWin32.cpp \ + gui/common/NotifyWidget.cpp # gui/ForumsDialog.cpp \ # gui/forums/ForumDetails.cpp \ # gui/forums/EditForumDetails.cpp \ @@ -1225,7 +1227,10 @@ gxsthewire { gui/TheWire/PulseReply.h \ gui/TheWire/PulseReplySeperator.h \ gui/TheWire/PulseMessage.h \ - gui/TheWire/CustomFrame.h \ + gui/TheWire/CustomFrame.h \ + gui/feeds/WireNotifyGroupItem.h \ + gui/TheWire/WireUserNotify.h \ + gui/feeds/WireNotifyPostItem.h \ FORMS += gui/TheWire/WireDialog.ui \ gui/TheWire/WireGroupItem.ui \ @@ -1236,7 +1241,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 \ @@ -1248,7 +1255,10 @@ gxsthewire { gui/TheWire/PulseReply.cpp \ gui/TheWire/PulseReplySeperator.cpp \ gui/TheWire/PulseMessage.cpp \ - gui/TheWire/CustomFrame.cpp \ + gui/TheWire/CustomFrame.cpp \ + gui/feeds/WireNotifyGroupItem.cpp \ + gui/TheWire/WireUserNotify.cpp \ + gui/feeds/WireNotifyPostItem.cpp \ RESOURCES += gui/TheWire/TheWire_images.qrc } @@ -1442,7 +1452,8 @@ gxsgui { gui/gxs/GxsFeedWidget.h \ util/TokenQueue.h \ util/RsGxsUpdateBroadcast.h \ - + gui/gxs/GxsStatisticsProvider.h \ + # gui/gxs/GxsMsgDialog.h \ FORMS += gui/gxs/GxsGroupDialog.ui \ @@ -1475,7 +1486,8 @@ gxsgui { gui/gxs/GxsFeedWidget.cpp \ util/TokenQueue.cpp \ util/RsGxsUpdateBroadcast.cpp \ - + gui/gxs/GxsStatisticsProvider.cpp \ + # gui/gxs/GxsMsgDialog.cpp \