mirror of
https://github.com/RetroShare/RetroShare.git
synced 2026-09-12 19:50:17 +05:00
Merge 408aa22843 into 21c981a430
This commit is contained in:
commit
fd435e5f63
@ -62,6 +62,7 @@ option( RS_GXSCHANNELS "Enable GXS channels in GUI" ON )
|
||||
option( RS_GXSFORUMS "Enable GXS forums in GUI" ON )
|
||||
option( RS_GXSPOSTED "Enable GXS posted in GUI" ON )
|
||||
option( RS_GXSCIRCLES "Enable GXS circles in GUI" ON )
|
||||
option( RS_GXSPEOPLE "Enable GXS people page in GUI" OFF )
|
||||
option( RS_GUI_CMARK "Enable CommonMark support in GUI" OFF )
|
||||
set(RS_GXSIDENTITIES ON CACHE BOOL "Enable GXS identities in GUI" FORCE)
|
||||
set(RS_IDLE ON CACHE BOOL "Enable Idle support" FORCE)
|
||||
@ -664,6 +665,10 @@ if(RS_GXSCIRCLES)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE RS_USE_CIRCLES )
|
||||
endif(RS_GXSCIRCLES)
|
||||
|
||||
if(RS_GXSPEOPLE)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE RS_USE_NEW_PEOPLE )
|
||||
endif(RS_GXSPEOPLE)
|
||||
|
||||
# NOTE: the GUI does NOT use botan, json-c, z or bz2 directly (it uses rapidjson
|
||||
# for JSON). They are transitive dependencies of librnp (PGP), pulled in here only
|
||||
# because the statically-linked librnp does not propagate them. Ideally librnp
|
||||
|
||||
@ -1078,30 +1078,44 @@ if(RS_GXSCIRCLES)
|
||||
APPEND RS_IMPLEMENTATION_HEADERS
|
||||
src/gui/Circles/CirclesDialog.h
|
||||
src/gui/Circles/CreateCircleDialog.h
|
||||
src/gui/People/PeopleDialog.h
|
||||
src/gui/People/CircleWidget.h
|
||||
src/gui/People/IdentityWidget.h
|
||||
)
|
||||
|
||||
list(
|
||||
APPEND RS_GUI_FORMS
|
||||
src/gui/Circles/CirclesDialog.ui
|
||||
src/gui/Circles/CreateCircleDialog.ui
|
||||
src/gui/People/PeopleDialog.ui
|
||||
src/gui/People/CircleWidget.ui
|
||||
src/gui/People/IdentityWidget.ui
|
||||
)
|
||||
|
||||
list(
|
||||
APPEND RS_GUI_SOURCES
|
||||
src/gui/Circles/CirclesDialog.cpp
|
||||
src/gui/Circles/CreateCircleDialog.cpp
|
||||
src/gui/People/PeopleDialog.cpp
|
||||
src/gui/People/CircleWidget.cpp
|
||||
src/gui/People/IdentityWidget.cpp
|
||||
)
|
||||
endif(RS_GXSCIRCLES)
|
||||
|
||||
if(RS_GXSPEOPLE)
|
||||
list(
|
||||
APPEND RS_IMPLEMENTATION_HEADERS
|
||||
src/gui/People/CircleWidget.h
|
||||
src/gui/People/IdentityWidget.h
|
||||
src/gui/People/PeopleDialog.h
|
||||
)
|
||||
|
||||
list(
|
||||
APPEND RS_GUI_FORMS
|
||||
src/gui/People/CircleWidget.ui
|
||||
src/gui/People/IdentityWidget.ui
|
||||
src/gui/People/PeopleDialog.ui
|
||||
)
|
||||
|
||||
list(
|
||||
APPEND RS_GUI_SOURCES
|
||||
src/gui/People/CircleWidget.cpp
|
||||
src/gui/People/IdentityWidget.cpp
|
||||
src/gui/People/PeopleDialog.cpp
|
||||
)
|
||||
endif(RS_GXSPEOPLE)
|
||||
|
||||
if(RS_GXSGUI)
|
||||
list(
|
||||
APPEND RS_IMPLEMENTATION_HEADERS
|
||||
|
||||
@ -300,9 +300,7 @@ RsIdentityListModel::EntryIndex RsIdentityListModel::EntryIndex::parent() const
|
||||
break;
|
||||
case ENTRY_TYPE_TOP_LEVEL:
|
||||
std::cerr << "ERROR: calling parent() on entryindex with no parent!" << std::endl;
|
||||
|
||||
default:
|
||||
//Can be when request root index.
|
||||
i.type = ENTRY_TYPE_TOP_LEVEL;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
385
retroshare-gui/src/gui/Identity/UsageStatistics.cpp
Normal file
385
retroshare-gui/src/gui/Identity/UsageStatistics.cpp
Normal file
@ -0,0 +1,385 @@
|
||||
/*******************************************************************************
|
||||
* retroshare-gui/src/gui/Identity/UsageStatistics.cpp *
|
||||
* *
|
||||
* Copyright (C) 2026 by Retroshare Team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* 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 <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <memory>
|
||||
|
||||
#include "UsageStatistics.h"
|
||||
#include "ui_UsageStatistics.h"
|
||||
|
||||
#include "gui/RetroShareLink.h"
|
||||
#include "gui/gxs/GxsIdDetails.h"
|
||||
#include "util/DateTime.h"
|
||||
#include "util/rstime.h"
|
||||
|
||||
#include "retroshare/rsgxsflags.h"
|
||||
#include "retroshare/rschats.h"
|
||||
#include "retroshare/rspeers.h"
|
||||
#include "retroshare/rsservicecontrol.h"
|
||||
#include "retroshare/rsgxschannels.h"
|
||||
#include "retroshare/rsgxsforums.h"
|
||||
#include "retroshare/rsposted.h"
|
||||
#ifdef RS_USE_WIRE
|
||||
#include "retroshare/rswire.h"
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
/******
|
||||
* #define ID_DEBUG 1
|
||||
*****/
|
||||
|
||||
/** Constructor */
|
||||
UsageStatistics::UsageStatistics(QWidget *parent)
|
||||
: QWidget(parent), ui(new Ui::UsageStatistics)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
}
|
||||
|
||||
/** Destructor */
|
||||
UsageStatistics::~UsageStatistics()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
static QString getHumanReadableDuration(uint32_t seconds)
|
||||
{
|
||||
if(seconds < 60)
|
||||
return QString(QObject::tr("%1 seconds ago")).arg(seconds) ;
|
||||
else if(seconds < 120)
|
||||
return QString(QObject::tr("%1 minute ago")).arg(seconds/60) ;
|
||||
else if(seconds < 3600)
|
||||
return QString(QObject::tr("%1 minutes ago")).arg(seconds/60) ;
|
||||
else if(seconds < 7200)
|
||||
return QString(QObject::tr("%1 hour ago")).arg(seconds/3600) ;
|
||||
else if(seconds < 24*3600)
|
||||
return QString(QObject::tr("%1 hours ago")).arg(seconds/3600) ;
|
||||
else if(seconds < 2*24*3600)
|
||||
return QString(QObject::tr("%1 day ago")).arg(seconds/86400) ;
|
||||
else
|
||||
return QString(QObject::tr("%1 days ago")).arg(seconds/86400) ;
|
||||
}
|
||||
|
||||
QString UsageStatistics::createUsageString(const RsIdentityUsage& u) const
|
||||
{
|
||||
QString service_name;
|
||||
RetroShareLink::enumType service_type = RetroShareLink::TYPE_UNKNOWN;
|
||||
|
||||
switch(u.mServiceId)
|
||||
{
|
||||
case RsServiceType::CHANNELS: service_name = tr("Channels") ;service_type = RetroShareLink::TYPE_CHANNEL ; break ;
|
||||
case RsServiceType::FORUMS: service_name = tr("Forums") ; service_type = RetroShareLink::TYPE_FORUM ; break ;
|
||||
case RsServiceType::POSTED: service_name = tr("Boards") ; service_type = RetroShareLink::TYPE_POSTED ; break ;
|
||||
case RsServiceType::CHAT: service_name = tr("Chat") ; service_type = RetroShareLink::TYPE_CHAT_ROOM ; break ;
|
||||
|
||||
case RsServiceType::GXS_TRANS: return tr("GxsMail author ");
|
||||
|
||||
case RsServiceType::GXSCIRCLE: service_name = tr("GxsCircles"); service_type = RetroShareLink::TYPE_CIRCLES; break ;
|
||||
#ifdef RS_USE_WIRE
|
||||
case RsServiceType::WIRE: service_name = tr("Wire"); service_type = RetroShareLink::TYPE_WIRE; break ;
|
||||
#endif
|
||||
default:
|
||||
service_name = tr("Unknown (service=")+QString::number((int)u.mServiceId,16)+")"; service_type = RetroShareLink::TYPE_UNKNOWN ;
|
||||
}
|
||||
|
||||
switch(u.mUsageCode)
|
||||
{
|
||||
case RsIdentityUsage::UNKNOWN_USAGE:
|
||||
return tr("[Unknown]") ;
|
||||
case RsIdentityUsage::GROUP_ADMIN_SIGNATURE_CREATION: // These 2 are normally not normal GXS identities, but nothing prevents it to happen either.
|
||||
return tr("Admin signature in service %1").arg(service_name);
|
||||
case RsIdentityUsage::GROUP_ADMIN_SIGNATURE_VALIDATION:
|
||||
return tr("Admin signature verification in service %1").arg(service_name);
|
||||
case RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_CREATION: // not typically used, since most services do not require group author signatures
|
||||
return tr("Creation of author signature in service %1").arg(service_name);
|
||||
case RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_CREATION: // most common use case. Messages are signed by authors in e.g. forums.
|
||||
{
|
||||
QString label = getGroupName(service_type, u.mGrpId);
|
||||
RetroShareLink l = RetroShareLink::createGxsGroupLink(service_type, u.mGrpId, label);
|
||||
|
||||
return tr("Message signature creation in group %1 of service %2").arg(l.toHtml(), service_name);
|
||||
}
|
||||
case RsIdentityUsage::GROUP_AUTHOR_KEEP_ALIVE: // Identities are stamped regularly by crawlign the set of messages for all groups. That helps keepign the useful identities in hand.
|
||||
case RsIdentityUsage::GROUP_AUTHOR_SIGNATURE_VALIDATION:
|
||||
{
|
||||
// label is either the Name or the ID string (from helper)
|
||||
QString label = getGroupName(service_type, u.mGrpId);
|
||||
RetroShareLink l = RetroShareLink::createGxsGroupLink(service_type, u.mGrpId, label);
|
||||
|
||||
return tr("Group author for group %1 in service %2").arg(l.toHtml(), service_name);
|
||||
}
|
||||
case RsIdentityUsage::MESSAGE_AUTHOR_SIGNATURE_VALIDATION:
|
||||
case RsIdentityUsage::MESSAGE_AUTHOR_KEEP_ALIVE: // Identities are stamped regularly by crawling the set of messages for all groups. That helps keepign the useful identities in hand.
|
||||
{
|
||||
RetroShareLink l;
|
||||
QString title;
|
||||
bool titleFound = false;
|
||||
|
||||
// Create a set containing only the ID we are looking for
|
||||
std::set<RsGxsMessageId> msgIds;
|
||||
msgIds.insert(u.mMsgId);
|
||||
|
||||
if (service_type == RetroShareLink::TYPE_CHANNEL && rsGxsChannels) {
|
||||
std::vector<RsGxsChannelPost> posts;
|
||||
std::vector<RsGxsComment> cmts; // Local variable to avoid rvalue error
|
||||
std::vector<RsGxsVote> vots; // Local variable to avoid rvalue error
|
||||
|
||||
if (rsGxsChannels->getChannelContent(u.mGrpId, msgIds, posts, cmts, vots)) {
|
||||
if (!posts.empty()) {
|
||||
title = QString::fromUtf8(posts[0].mMeta.mMsgName.c_str());
|
||||
titleFound = !title.isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (service_type == RetroShareLink::TYPE_FORUM && rsGxsForums) {
|
||||
std::vector<RsGxsForumMsg> msgs;
|
||||
// getForumContent only needs 3 arguments, so no extra vectors needed
|
||||
if (rsGxsForums->getForumContent(u.mGrpId, msgIds, msgs)) {
|
||||
if (!msgs.empty()) {
|
||||
title = QString::fromUtf8(msgs[0].mMeta.mMsgName.c_str());
|
||||
titleFound = !title.isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (service_type == RetroShareLink::TYPE_POSTED && rsPosted) {
|
||||
std::vector<RsPostedPost> posts;
|
||||
std::vector<RsGxsComment> cmts;
|
||||
std::vector<RsGxsVote> vots;
|
||||
|
||||
if (rsPosted->getBoardContent(u.mGrpId, msgIds, posts, cmts, vots)) {
|
||||
if (!posts.empty()) {
|
||||
title = QString::fromUtf8(posts[0].mMeta.mMsgName.c_str());
|
||||
titleFound = !title.isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the label
|
||||
QString label;
|
||||
if (titleFound) {
|
||||
label = title;
|
||||
} else {
|
||||
// Use raw Group ID string if it's a group validation case or total failure
|
||||
label = QString::fromStdString(u.mGrpId.toStdString());
|
||||
}
|
||||
|
||||
|
||||
// Generate the link
|
||||
if ((service_type == RetroShareLink::TYPE_CHANNEL || service_type == RetroShareLink::TYPE_POSTED) && !u.mThreadId.isNull()) {
|
||||
l = RetroShareLink::createGxsMessageLink(service_type, u.mGrpId, u.mThreadId, label);
|
||||
}
|
||||
else {
|
||||
l = RetroShareLink::createGxsMessageLink(service_type, u.mGrpId, u.mMsgId, label);
|
||||
}
|
||||
|
||||
// Determine the suffix based on the service type
|
||||
QString suffix;
|
||||
if (service_type == RetroShareLink::TYPE_CHANNEL || service_type == RetroShareLink::TYPE_POSTED) {
|
||||
suffix = tr("Vote/comment");
|
||||
} else {
|
||||
suffix = tr("Message");
|
||||
}
|
||||
|
||||
return tr("%2 in %3 service %1").arg(l.toHtml(), suffix, service_name);
|
||||
}
|
||||
case RsIdentityUsage::CHAT_LOBBY_MSG_VALIDATION: // Chat lobby msgs are signed, so each time one comes, or a chat lobby event comes, a signature verificaiton happens.
|
||||
{
|
||||
ChatId id = ChatId(ChatLobbyId(u.mAdditionalId));
|
||||
ChatLobbyInfo linfo ;
|
||||
rsChats->getChatLobbyInfo(ChatLobbyId(u.mAdditionalId),linfo);
|
||||
RetroShareLink l = RetroShareLink::createChatRoom(id, QString::fromUtf8(linfo.lobby_name.c_str()));
|
||||
return tr("Message in chat room %1").arg(l.toHtml()) ;
|
||||
}
|
||||
case RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CHECK: // Global router message validation
|
||||
{
|
||||
return tr("Distant message signature validation.");
|
||||
}
|
||||
case RsIdentityUsage::GLOBAL_ROUTER_SIGNATURE_CREATION: // Global router message signature
|
||||
{
|
||||
return tr("Distant message signature creation.");
|
||||
}
|
||||
case RsIdentityUsage::GXS_TUNNEL_DH_SIGNATURE_CHECK: //
|
||||
{
|
||||
return tr("Signature validation in distant tunnel system.");
|
||||
}
|
||||
case RsIdentityUsage::GXS_TUNNEL_DH_SIGNATURE_CREATION: //
|
||||
{
|
||||
return tr("Signature in distant tunnel system.");
|
||||
}
|
||||
case RsIdentityUsage::IDENTITY_NEW_FROM_GXS_SYNC: // Group update on that identity data. Can be avatar, name, etc.
|
||||
{
|
||||
return tr("Received from GXS sync.");
|
||||
}
|
||||
case RsIdentityUsage::IDENTITY_NEW_FROM_DISCOVERY: // Own friend sended his own ids
|
||||
{
|
||||
return tr("Friend node identity received through discovery.");
|
||||
}
|
||||
case RsIdentityUsage::IDENTITY_GENERIC_SIGNATURE_CHECK: // Any signature verified for that identity
|
||||
{
|
||||
return tr("Generic signature validation.");
|
||||
}
|
||||
case RsIdentityUsage::IDENTITY_GENERIC_SIGNATURE_CREATION: // Any signature made by that identity
|
||||
{
|
||||
return tr("Generic signature creation (e.g. chat room message, global router,...).");
|
||||
}
|
||||
case RsIdentityUsage::IDENTITY_GENERIC_ENCRYPTION: return tr("Generic encryption.");
|
||||
case RsIdentityUsage::IDENTITY_GENERIC_DECRYPTION: return tr("Generic decryption.");
|
||||
case RsIdentityUsage::CIRCLE_MEMBERSHIP_CHECK:
|
||||
{
|
||||
RetroShareLink l;
|
||||
RsGxsCircleDetails det;
|
||||
|
||||
// Try to fetch circle details to get the name
|
||||
if (rsGxsCircles->getCircleDetails(RsGxsCircleId(u.mGrpId), det)) {
|
||||
|
||||
// Prepare the label:
|
||||
QString label;
|
||||
if (!det.mCircleName.empty()) {
|
||||
label = QString::fromUtf8(det.mCircleName.c_str()) ;
|
||||
} else {
|
||||
label = QString::fromStdString(u.mGrpId.toStdString());
|
||||
}
|
||||
|
||||
// Create the RetroShareLink for the circle
|
||||
l = RetroShareLink::createCircle(RsGxsCircleId(u.mGrpId), label);
|
||||
|
||||
// Return the formatted string with the clickable link
|
||||
if (!det.mCircleName.empty()) {
|
||||
return tr("Membership verification in circle %1.").arg(l.toHtml());
|
||||
} else {
|
||||
return tr("Membership verification in circle (ID=%1).").arg(l.toHtml());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#warning TODO! csoler 2017-01-03: Add the different strings and translations here.
|
||||
default:
|
||||
return QString("Undone yet");
|
||||
}
|
||||
return QString("Unknown");
|
||||
}
|
||||
|
||||
void UsageStatistics::setUsageData(RsGxsIdGroup data)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
RsIdentityDetails det;
|
||||
rsIdentity->getIdDetails(RsGxsId(data.mMeta.mGroupId), det);
|
||||
|
||||
QString usage_txt;
|
||||
std::map<rstime_t, RsIdentityUsage> rmap;
|
||||
for(auto it(det.mUseCases.begin()); it != det.mUseCases.end(); ++it)
|
||||
rmap.insert(std::make_pair(it->second, it->first));
|
||||
|
||||
for(auto it(rmap.begin()); it != rmap.end(); ++it)
|
||||
usage_txt += QString("<b>") + getHumanReadableDuration(now - data.mLastUsageTS) + "</b> \t: " + createUsageString(it->second) + "<br/>";
|
||||
|
||||
if(usage_txt.isEmpty()) // .isNull() can sometimes be tricky, .isEmpty() is safer here
|
||||
usage_txt = tr("<b>[No record in current session]</b>");
|
||||
|
||||
ui->usageStatistics_TB->setText(usage_txt);
|
||||
}
|
||||
|
||||
QString UsageStatistics::getGroupName(uint32_t service_type, const RsGxsGroupId& groupId) const
|
||||
{
|
||||
std::list<RsGxsGroupId> groupIds;
|
||||
groupIds.push_back(groupId);
|
||||
|
||||
if (service_type == RetroShareLink::TYPE_CHANNEL && rsGxsChannels) {
|
||||
std::vector<RsGxsChannelGroup> groups;
|
||||
if (rsGxsChannels->getChannelsInfo(groupIds, groups) && !groups.empty()) {
|
||||
QString name = QString::fromUtf8(groups[0].mMeta.mGroupName.c_str());
|
||||
if (!name.isEmpty()) return name;
|
||||
}
|
||||
}
|
||||
else if (service_type == RetroShareLink::TYPE_FORUM && rsGxsForums) {
|
||||
std::vector<RsGxsForumGroup> groups;
|
||||
if (rsGxsForums->getForumsInfo(groupIds, groups) && !groups.empty()) {
|
||||
QString name = QString::fromUtf8(groups[0].mMeta.mGroupName.c_str());
|
||||
if (!name.isEmpty()) return name;
|
||||
}
|
||||
}
|
||||
else if (service_type == RetroShareLink::TYPE_POSTED && rsPosted) {
|
||||
std::vector<RsPostedGroup> groups;
|
||||
if (rsPosted->getBoardsInfo(groupIds, groups) && !groups.empty()) {
|
||||
QString name = QString::fromUtf8(groups[0].mMeta.mGroupName.c_str());
|
||||
if (!name.isEmpty()) return name;
|
||||
}
|
||||
}
|
||||
else if (service_type == RetroShareLink::TYPE_CIRCLES && rsGxsCircles) {
|
||||
RsGxsCircleDetails det;
|
||||
if (rsGxsCircles->getCircleDetails(RsGxsCircleId(groupId), det)) {
|
||||
QString name = QString::fromUtf8(det.mCircleName.c_str());
|
||||
if (!name.isEmpty()) return name;
|
||||
}
|
||||
}
|
||||
#ifdef RS_USE_WIRE
|
||||
else if (service_type == RetroShareLink::TYPE_WIRE && rsWire) {
|
||||
RsWireGroupSPtr group; // Shared pointer for the result
|
||||
if (rsWire->getWireGroup(groupId, group) && group) {
|
||||
QString name = QString::fromUtf8(group->mMeta.mGroupName.c_str());
|
||||
if (!name.isEmpty()) return name;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Returns the raw ID string as the label
|
||||
return QString::fromStdString(groupId.toStdString());
|
||||
}
|
||||
|
||||
QString UsageStatistics::getMessageTitle(uint32_t service_type, const RsGxsGroupId& groupId, const RsGxsMessageId& msgId) const
|
||||
{
|
||||
std::set<RsGxsMessageId> msgIds;
|
||||
msgIds.insert(msgId);
|
||||
|
||||
if (service_type == RetroShareLink::TYPE_CHANNEL && rsGxsChannels) {
|
||||
std::vector<RsGxsChannelPost> posts;
|
||||
std::vector<RsGxsComment> cmts;
|
||||
std::vector<RsGxsVote> vots;
|
||||
if (rsGxsChannels->getChannelContent(groupId, msgIds, posts, cmts, vots) && !posts.empty()) {
|
||||
return QString::fromUtf8(posts[0].mMeta.mMsgName.c_str());
|
||||
}
|
||||
}
|
||||
else if (service_type == RetroShareLink::TYPE_FORUM && rsGxsForums) {
|
||||
std::vector<RsGxsForumMsg> msgs;
|
||||
if (rsGxsForums->getForumContent(groupId, msgIds, msgs) && !msgs.empty()) {
|
||||
return QString::fromUtf8(msgs[0].mMeta.mMsgName.c_str());
|
||||
}
|
||||
}
|
||||
else if (service_type == RetroShareLink::TYPE_POSTED && rsPosted) {
|
||||
std::vector<RsPostedPost> posts;
|
||||
std::vector<RsGxsComment> cmts;
|
||||
std::vector<RsGxsVote> vots;
|
||||
if (rsPosted->getBoardContent(groupId, msgIds, posts, cmts, vots) && !posts.empty()) {
|
||||
return QString::fromUtf8(posts[0].mMeta.mMsgName.c_str());
|
||||
}
|
||||
}
|
||||
else if (service_type == RetroShareLink::TYPE_CIRCLES && rsGxsCircles) {
|
||||
RsGxsCircleDetails det;
|
||||
if (rsGxsCircles->getCircleDetails(RsGxsCircleId(groupId), det)) {
|
||||
return QString::fromUtf8(det.mCircleName.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return QString(); // Return empty if not found
|
||||
}
|
||||
58
retroshare-gui/src/gui/Identity/UsageStatistics.h
Normal file
58
retroshare-gui/src/gui/Identity/UsageStatistics.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*******************************************************************************
|
||||
* retroshare-gui/src/gui/Identity/UsageStatistics.h *
|
||||
* *
|
||||
* Copyright (C) 2026 by Retroshare Team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* 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 <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef USAGESTATISTICS_H
|
||||
#define USAGESTATISTICS_H
|
||||
|
||||
#include "gui/gxs/RsGxsUpdateBroadcastPage.h"
|
||||
|
||||
#include "retroshare/rsidentity.h"
|
||||
|
||||
namespace Ui {
|
||||
class UsageStatistics;
|
||||
}
|
||||
|
||||
|
||||
class UsageStatistics : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
UsageStatistics(QWidget *parent = 0);
|
||||
~UsageStatistics();
|
||||
|
||||
void setUsageData(RsGxsIdGroup data);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
private slots:
|
||||
|
||||
|
||||
private:
|
||||
QString createUsageString(const RsIdentityUsage& u) const;
|
||||
QString getGroupName(uint32_t service_type, const RsGxsGroupId& groupId) const;
|
||||
QString getMessageTitle(uint32_t service_type, const RsGxsGroupId& groupId, const RsGxsMessageId& msgId) const;
|
||||
|
||||
/* UI - Designer */
|
||||
Ui::UsageStatistics *ui;
|
||||
};
|
||||
|
||||
#endif
|
||||
52
retroshare-gui/src/gui/Identity/UsageStatistics.ui
Normal file
52
retroshare-gui/src/gui/Identity/UsageStatistics.ui
Normal file
@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UsageStatistics</class>
|
||||
<widget class="QWidget" name="UsageStatistics">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="usageStatisticsGBox">
|
||||
<property name="title">
|
||||
<string>Usage statistics</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="usageStatisticsGBoxHLayout">
|
||||
<item>
|
||||
<widget class="RSTextBrowser" name="usageStatistics_TB"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RSTextBrowser</class>
|
||||
<extends>QTextBrowser</extends>
|
||||
<header>gui/common/RSTextBrowser.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -80,7 +80,7 @@
|
||||
#include "gui/GetStartedDialog.h"
|
||||
#endif
|
||||
|
||||
#ifdef RS_USE_CIRCLES
|
||||
#ifdef RS_USE_NEW_PEOPLE
|
||||
#include "gui/People/PeopleDialog.h"
|
||||
#endif
|
||||
#include "idle/idle.h"
|
||||
@ -456,10 +456,10 @@ void MainWindow::initStackedPage()
|
||||
addPage(gxsforumDialog = new GxsForumsDialog(ui->stackPages), grp, ¬ify);
|
||||
addPage(postedDialog = new PostedDialog(ui->stackPages), grp, ¬ify);
|
||||
|
||||
#ifdef RS_USE_NEW_PEOPLE_DIALOG
|
||||
#ifdef RS_USE_NEW_PEOPLE
|
||||
PeopleDialog *peopleDialog = NULL;
|
||||
addPage(peopleDialog = new PeopleDialog(ui->stackPages), grp, ¬ify);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef RS_USE_WIKI
|
||||
wikiDialog = NULL;
|
||||
addPage(wikiDialog = new WikiDialog(ui->stackPages), grp, ¬ify);
|
||||
|
||||
@ -52,6 +52,12 @@ CircleWidget::CircleWidget(QString name/*=QString()*/
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
void CircleWidget::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
emit clicked();
|
||||
FlowLayoutItem::mousePressEvent(event);
|
||||
}
|
||||
|
||||
CircleWidget::~CircleWidget()
|
||||
{
|
||||
delete _scene;
|
||||
|
||||
@ -59,10 +59,14 @@ public:
|
||||
signals:
|
||||
void askForGXSIdentityWidget(RsGxsId gxs_id);
|
||||
void askForPGPIdentityWidget(RsPgpId pgp_id);
|
||||
void clicked(); // emitted when circle is clicked (for selection state machine)
|
||||
|
||||
private slots:
|
||||
void updateIdImage();
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
void updateScene();
|
||||
|
||||
|
||||
@ -209,8 +209,8 @@ void IdentityWidget::setIsSelected(bool value)
|
||||
void IdentityWidget::setIsCurrent(bool value)
|
||||
{
|
||||
m_isCurrent=value;
|
||||
ui->labelKeyId->setVisible(value);
|
||||
ui->labelGXSId->setVisible(value && (_haveGXSId && _havePGPDetail));
|
||||
ui->labelKeyId->setVisible(false); // disabled by default
|
||||
ui->labelGXSId->setVisible(false); // disable by default
|
||||
ui->labelPositive->setVisible(value);
|
||||
ui->labelNegative->setVisible(value);
|
||||
ui->label_PosIcon_2->setVisible(value);
|
||||
@ -223,3 +223,22 @@ void IdentityWidget::pbAdd_clicked()
|
||||
emit addButtonClicked();
|
||||
}
|
||||
|
||||
uint32_t IdentityWidget::getReputation() const
|
||||
{
|
||||
RsReputationInfo info;
|
||||
// Use the logic to fetch reputation
|
||||
if (rsReputations->getReputationInfo(RsGxsId(_group_info.mMeta.mGroupId), _group_info.mPgpId, info)) {
|
||||
return info.mFriendsPositiveVotes;
|
||||
}
|
||||
return 0; // Default if no info found
|
||||
}
|
||||
|
||||
void IdentityWidget::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::RightButton) {
|
||||
emit addButtonClicked();
|
||||
} else {
|
||||
emit clicked();
|
||||
}
|
||||
FlowLayoutItem::mousePressEvent(event);
|
||||
}
|
||||
|
||||
@ -63,9 +63,15 @@ public:
|
||||
const QString nickname() const { return _nickname; }
|
||||
const QString gxsId() const { return _gxsId; }
|
||||
const QImage avatar() const { return _avatar; }
|
||||
|
||||
uint32_t getReputation() const;
|
||||
|
||||
signals:
|
||||
void addButtonClicked();
|
||||
void clicked();
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
private slots:
|
||||
void pbAdd_clicked();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -26,6 +26,7 @@
|
||||
|
||||
#include "gui/People/CircleWidget.h"
|
||||
#include "gui/People/IdentityWidget.h"
|
||||
#include "gui/Identity/UsageStatistics.h"
|
||||
#include "gui/gxs/RsGxsUpdateBroadcastPage.h"
|
||||
#include "util/TokenQueue.h"
|
||||
|
||||
@ -59,7 +60,7 @@ class PeopleDialog : public MainPage, public Ui::PeopleDialog, public TokenRespo
|
||||
void insertCircles(uint32_t token) ;
|
||||
|
||||
protected:
|
||||
// Derives from RsGxsUpdateBroadcastPage
|
||||
// Derives from MainPage
|
||||
virtual void updateDisplay(bool complete);
|
||||
//End RsGxsUpdateBroadcastPage
|
||||
|
||||
@ -88,16 +89,51 @@ private slots:
|
||||
void personDetails();
|
||||
void sendInvite();
|
||||
void addtoContacts();
|
||||
|
||||
void filterChanged(const QString &text);
|
||||
void sortByName();
|
||||
void sortByPopularity();
|
||||
void clearAllSelections();
|
||||
void onIdentitySelected();
|
||||
void onCircleSelected(); // circle widget clicked → circle-selected state
|
||||
void onCircleTreeItemClicked(QTreeWidgetItem *item, int column);
|
||||
void onCircleTreeContextMenuRequested(const QPoint &pos);
|
||||
void onBackClicked(); // back button → return to no-selection state
|
||||
void clearPerson();
|
||||
void toggleStackedPage();
|
||||
void toggledetailsStackedPage();
|
||||
void onDetailsPageChanged(int index);
|
||||
void modifyReputation();
|
||||
void requestJoinLeaveCircle(); // join/leave button in circle details page
|
||||
|
||||
private:
|
||||
void reloadAll();
|
||||
void populatePictureFlowExt();
|
||||
void populatePictureFlowInt();
|
||||
void applySortAndFilter(bool);
|
||||
void loadIdentityLabels(const RsGxsIdGroup& data);
|
||||
void populateCirclesTree(const std::list<RsGroupMetaData>& circles);
|
||||
void setVoteControlsVisible(bool visible);
|
||||
|
||||
// Selection state machine
|
||||
enum class SelectionMode { None, Identity, Circle };
|
||||
void showNoneSelected();
|
||||
void showIdentitySelected(const RsGxsId& id);
|
||||
void showCircleSelected(const RsGxsGroupId& circleId);
|
||||
void loadCircleLabels(const CircleWidget* cw);
|
||||
void loadCircleLabels(const RsGxsGroupId& circleId);
|
||||
|
||||
TokenQueue *mIdentityQueue;
|
||||
TokenQueue *mCirclesQueue;
|
||||
//RsGxsUpdateBroadcastBase *mCirclesBroadcastBase ;
|
||||
RsGxsId mCurrentSelectedId; // Store the ID of the person currently clicked
|
||||
QWidget *UsagePage;
|
||||
|
||||
// Selection state
|
||||
SelectionMode _selectionMode = SelectionMode::None;
|
||||
RsGxsId _selectedGxsId;
|
||||
RsGxsGroupId _selectedCircleId;
|
||||
bool _inSelectionUpdate = false;
|
||||
std::set<RsGxsGroupId> _requestedCircles;
|
||||
|
||||
FlowLayout *_flowLayoutExt;
|
||||
std::map<RsGxsId,IdentityWidget *> _gxs_identity_widgets ;
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>727</width>
|
||||
<height>524</height>
|
||||
<width>988</width>
|
||||
<height>529</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -51,6 +51,45 @@
|
||||
<string>People</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="LineEditClear" name="filterLineEdit">
|
||||
<property name="placeholderText">
|
||||
<string>Search...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="filterButton">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/mail/filter24.png</normaloff>:/icons/mail/filter24.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="switchButton">
|
||||
<property name="toolTip">
|
||||
<string>View circles</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/png/circles.png</normaloff>:/icons/png/circles.png</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitterExternal">
|
||||
<property name="orientation">
|
||||
@ -60,7 +99,7 @@
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>250</height>
|
||||
<height>80</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
@ -71,39 +110,613 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>701</width>
|
||||
<height>248</height>
|
||||
<width>962</width>
|
||||
<height>78</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout"/>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QFrame" name="widgetExternal">
|
||||
<layout class="QGridLayout" name="layoutExternal">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_External">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Drag your circles or people to each other.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="PictureFlow" name="pictureFlowWidgetExternal" native="true">
|
||||
<property name="widgetResizable" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QStackedWidget" name="widgetExternal">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="widgetExternalPage">
|
||||
<layout class="QGridLayout" name="layoutExternal">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_External">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Drag your circles or people to each other.</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="PictureFlow" name="pictureFlowWidgetExternal" native="true">
|
||||
<property name="widgetResizable" stdset="0">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="widgetPeoplePage">
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0" rowspan="2">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="avatarLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string extracomment="Click here to change your avatar">Your Avatar</string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QPushButton" name="editButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit Identity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="inviteButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Send Invite</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QPushButton" name="joinLeaveCircleButton">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-family:'ui-monospace','SFMono-Regular','Menlo','Monaco','Consolas','Liberation Mono','Courier New','monospace'; font-size:12px; color:#101010; background-color:rgba(198,236,203,0.376471);">Request to join</span></p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Request</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="avatarOpinionHLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_PosIcon">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>34</width>
|
||||
<height>34</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../icons.qrc">:/icons/png/thumbs-up.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_positive">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Positive votes</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_Opinion">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_NegIcon">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>34</width>
|
||||
<height>34</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../icons.qrc">:/icons/png/thumbs-down.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_negative">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>16</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Negative votes</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="avatarVSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>118</width>
|
||||
<height>17</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="statsButton">
|
||||
<property name="text">
|
||||
<string>View Stats</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="ElidedLabel" name="headerTextLabel_Person">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>22</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>People</string>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="backButton">
|
||||
<property name="text">
|
||||
<string>Back</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/png/arrow-left.png</normaloff>:/icons/png/arrow-left.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QStackedWidget" name="detailsStackedWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>299</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="detailsPage">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="neighborNodesOpinion_LB">
|
||||
<property name="text">
|
||||
<string>Votes:</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="neighborNodesOpinion_TF">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Average opinion of neighbor nodes about this identity. Negative is bad,</p><p>positive is good. Zero is neutral.</p></body></html></string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_KeyId">
|
||||
<property name="text">
|
||||
<string>Identity ID :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="lineEdit_LastUsed">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_GpgId">
|
||||
<property name="text">
|
||||
<string>Owner node ID :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_LastUsed">
|
||||
<property name="text">
|
||||
<string>Last used:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="lineEdit_KeyId">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4" rowspan="9">
|
||||
<widget class="QTreeWidget" name="circlesTreeWidget">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Circle Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Members</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_Type">
|
||||
<property name="text">
|
||||
<string>Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2" colspan="2">
|
||||
<widget class="QCheckBox" name="autoBanIdentities_CB">
|
||||
<property name="toolTip">
|
||||
<string>Auto-Ban all identities signed by the same node</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Auto-Ban profile</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="lineEdit_Type">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_YourOpinion">
|
||||
<property name="text">
|
||||
<string>Your opinion:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="RSComboBox" name="ownOpinion_CB">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p><span style=" font-family:'Sans'; font-size:9pt;">Your own opinion about an identity rules the visibility of that identity for yourself and your friend nodes. Your own opinion is shared among friends and used to compute a reputation score: If your opinion about an identity is neutral, the reputation score is the difference between friend's positive and negative opinions. If not, your own opinion gives the score.</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">The overall score is used in chat lobbies, forums and channels to decide on the actions to take for each specific identity. When the overall score is lower than -1, the identity is banned, which prevents all messages and forums/channels authored by this identity to be forwarded, both ways. Some forums also have special anti-spam flags that require a non negative reputation level, making them more sensitive to bad opinions. Banned identities gradually lose their activity and eventually disappear (after 5 days).</span></p><p><span style=" font-family:'Sans'; font-size:9pt;">You can change the thresholds and the time of inactivity to delete identities in preferences -&gt; people. </span></p></body></html></string>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Negative</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/png/thumbs-down.png</normaloff>:/icons/png/thumbs-down.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Neutral</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/png/thumbs-neutral.png</normaloff>:/icons/png/thumbs-neutral.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Positive</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../icons.qrc">
|
||||
<normaloff>:/icons/png/thumbs-up.png</normaloff>:/icons/png/thumbs-up.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="lineEdit_GpgId">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_PublishTS">
|
||||
<property name="text">
|
||||
<string>Created on :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="3">
|
||||
<widget class="QLineEdit" name="overallOpinion_TF">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Overall reputation score, accounting for yours and your friends'.</p><p>Negative is bad, positive is good. Zero is neutral. If the score is too low,</p><p>the identity is flagged as bad, and will be filtered out in forums, chat lobbies,</p><p>channels, etc.</p></body></html></string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="lineEdit_GpgName">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_GpgName">
|
||||
<property name="text">
|
||||
<string>Owner node name :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0" colspan="4">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="3">
|
||||
<widget class="QLineEdit" name="lineEdit_PublishTS">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="circleDetailsPage">
|
||||
<layout class="QGridLayout" name="circleDetailsLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_CircleName">
|
||||
<property name="text">
|
||||
<string>Circle Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="circleNameEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_CircleId">
|
||||
<property name="text">
|
||||
<string>Circle ID:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="circleIdEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_CircleType">
|
||||
<property name="text">
|
||||
<string>Type:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="circleTypeEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_CircleMembers">
|
||||
<property name="text">
|
||||
<string>Members:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="circleMemberCountEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<spacer name="circleDetailsSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
@ -129,7 +742,7 @@
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>250</height>
|
||||
<height>80</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
@ -140,8 +753,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>701</width>
|
||||
<height>248</height>
|
||||
<width>962</width>
|
||||
<height>164</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout"/>
|
||||
@ -183,6 +796,11 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LineEditClear</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header>gui/common/LineEditClear.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PictureFlow</class>
|
||||
<extends>QWidget</extends>
|
||||
@ -195,9 +813,20 @@
|
||||
<header location="global">gui/common/FlowLayout.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ElidedLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>gui/common/ElidedLabel.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RSComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>gui/common/RSComboBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../images.qrc"/>
|
||||
<include location="../icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@ -596,8 +596,10 @@ QSize FlowLayout::minimumSize() const
|
||||
{
|
||||
QSize size;
|
||||
QLayoutItem *item;
|
||||
foreach (item, m_itemList)
|
||||
foreach (item, m_itemList) {
|
||||
if (item->widget() && !item->widget()->isVisible()) continue;
|
||||
size = size.expandedTo(item->minimumSize());
|
||||
}
|
||||
|
||||
QMargins margins = contentsMargins();
|
||||
size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
|
||||
@ -681,6 +683,8 @@ int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
|
||||
for (int curs=0; curs<count; ++curs) {
|
||||
QLayoutItem *item=m_itemList.value(curs);
|
||||
QWidget *wid = item->widget();
|
||||
// Skip hidden widgets so they don't leave empty gaps in the flow
|
||||
if (!wid || !wid->isVisible()) continue;
|
||||
int spaceX = horizontalSpacing();
|
||||
if (spaceX == -1)
|
||||
spaceX = wid->style()->layoutSpacing(
|
||||
|
||||
@ -111,6 +111,7 @@ CONFIG += gxschannels
|
||||
CONFIG += posted
|
||||
CONFIG += gxsgui
|
||||
CONFIG += gxscircles
|
||||
CONFIG += gxspeople
|
||||
|
||||
# Other Disabled Bits.
|
||||
#CONFIG += framecatcher
|
||||
@ -1277,22 +1278,24 @@ identities {
|
||||
gui/Identity/IdentityListModel.h \
|
||||
gui/Identity/IdEditDialog.h \
|
||||
gui/Identity/IdDetailsDialog.h \
|
||||
gui/Identity/UsageStatistics.h \
|
||||
|
||||
FORMS += gui/Identity/IdDialog.ui \
|
||||
gui/Identity/IdEditDialog.ui \
|
||||
gui/Identity/IdDetailsDialog.ui \
|
||||
gui/Identity/UsageStatistics.ui \
|
||||
|
||||
SOURCES += \
|
||||
gui/Identity/IdDialog.cpp \
|
||||
gui/Identity/IdentityListModel.cpp \
|
||||
gui/Identity/IdEditDialog.cpp \
|
||||
gui/Identity/IdDetailsDialog.cpp \
|
||||
gui/Identity/UsageStatistics.cpp \
|
||||
|
||||
}
|
||||
|
||||
gxscircles {
|
||||
DEFINES += RS_USE_CIRCLES
|
||||
# DEFINES += RS_USE_NEW_PEOPLE_DIALOG
|
||||
|
||||
HEADERS += \
|
||||
gui/Circles/CirclesDialog.h \
|
||||
@ -1304,27 +1307,24 @@ gxscircles {
|
||||
SOURCES += \
|
||||
gui/Circles/CirclesDialog.cpp \
|
||||
gui/Circles/CreateCircleDialog.cpp \
|
||||
}
|
||||
|
||||
gxspeople {
|
||||
# Enable the new PeopleDialog by adding CONFIG += rs_new_people_dialog
|
||||
# on the qmake command line or at the top of this .pro file.
|
||||
DEFINES += RS_USE_NEW_PEOPLE
|
||||
|
||||
HEADERS += gui/People/PeopleDialog.h
|
||||
HEADERS += gui/People/CircleWidget.h
|
||||
HEADERS += gui/People/IdentityWidget.h
|
||||
|
||||
FORMS += gui/People/PeopleDialog.ui
|
||||
FORMS += gui/People/PeopleDialog.ui
|
||||
FORMS += gui/People/CircleWidget.ui
|
||||
FORMS += gui/People/IdentityWidget.ui
|
||||
|
||||
SOURCES += gui/People/PeopleDialog.cpp
|
||||
SOURCES += gui/People/PeopleDialog.cpp
|
||||
SOURCES += gui/People/CircleWidget.cpp
|
||||
SOURCES += gui/People/IdentityWidget.cpp
|
||||
|
||||
#HEADERS += gui/People/IdentityItem.h
|
||||
#HEADERS += gui/People/CircleItem.h
|
||||
#HEADERS += gui/People/GroupListView.h
|
||||
#SOURCES += gui/People/GroupListView.cpp
|
||||
#SOURCES += gui/People/IdentityItem.cpp
|
||||
#SOURCES += gui/People/CircleItem.cpp
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user