Merge pull request #3117 from dbear496/fix-mod-select-circle

fix moderator list dropdown when editing post in circle-restricted forum
This commit is contained in:
csoler 2026-02-02 21:47:33 +01:00 committed by GitHub
commit 16a4063a5c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 93 additions and 47 deletions

View File

@ -51,8 +51,10 @@
//#define IDCHOOSER_DEBUG
/** Constructor */
GxsIdChooser::GxsIdChooser(QWidget *parent)
: RSComboBox(parent), mFlags(IDCHOOSER_ANON_DEFAULT)
GxsIdChooser::GxsIdChooser(QWidget *parent) :
RSComboBox(parent),
mFlags(IDCHOOSER_ANON_DEFAULT),
noIdConstraint(true)
{
// mBase = new RsGxsUpdateBroadcastBase(rsIdentity, this);
// connect(mBase, SIGNAL(fillDisplay(bool)), this, SLOT(fillDisplay(bool)));
@ -121,20 +123,54 @@ void GxsIdChooser::showEvent(QShowEvent *event)
QComboBox::showEvent(event);
}
void GxsIdChooser::setIdConstraintSet(const std::set<RsGxsId>& s)
void GxsIdChooser::setIdConstraintSet(const std::set<RsGxsId>& s)
{
mConstraintIdsSet = s ;
updateDisplay(true);
update(); // Qt flush
noIdConstraint = s.empty();
mConstraintIdsSet = s;
updateDisplay(true);
update(); // Qt flush
}
void
GxsIdChooser::intersectIdConstraintSet(const std::set<RsGxsId>& s) {
if(noIdConstraint) {
mConstraintIdsSet = s;
noIdConstraint = false;
}
else for(std::set<RsGxsId>::const_iterator i = mConstraintIdsSet.begin();
i != mConstraintIdsSet.end();
) {
if(s.find(*i) == s.end())
i = mConstraintIdsSet.erase(i);
else
i++;
}
updateDisplay(true);
update(); // Qt flush
}
void
GxsIdChooser::unionIdConstraintSet(const std::set<RsGxsId>& s) {
if(noIdConstraint) {
return;
}
else for(const RsGxsId& id : s) {
mConstraintIdsSet.insert(id);
}
updateDisplay(true);
update(); // Qt flush
}
void GxsIdChooser::loadIds(uint32_t chooserFlags, const RsGxsId &defId)
{
mFlags = chooserFlags;
mDefaultId = defId;
clear();
mFirstLoad = true;
updateDisplay(true);
update(); // Qt flush
}
@ -182,7 +218,7 @@ static void loadPrivateIdsCallback(GxsIdDetailsType type, const RsIdentityDetail
case GXS_ID_DETAILS_TYPE_DONE:
GxsIdDetails::getIcons(details, icons, GxsIdDetails::ICON_TYPE_AVATAR);
break;
case GXS_ID_DETAILS_TYPE_BANNED:
icons.push_back(FilesDefs::getIconFromQtResourcePath(BANNED_ICON)) ;
break;
@ -193,16 +229,25 @@ static void loadPrivateIdsCallback(GxsIdDetailsType type, const RsIdentityDetail
chooser->setItemIcon(index, icons.empty() ? QIcon() : icons[0]);
//std::cerr << "ID=" << details.mId << ", chooser->flags()=" << chooser->flags() << ", flags=" << details.mFlags ;
if((chooser->flags() & IDCHOOSER_NON_ANONYMOUS) && !(details.mFlags & RS_IDENTITY_FLAGS_PGP_LINKED))
{
//std::cerr << " - disabling ID - entry = " << index << std::endl;
chooser->setEntryEnabled(index,false) ;
}
if(!chooser->isInConstraintSet(details.mId))
if(!chooser->isInConstraintSet(details.mId)) {
chooser->setEntryEnabled(index,false) ;
#ifdef IDCHOOSER_DEBUG
std::cerr << "GxsIdChooser: ID not in constraint set: " << details.mId << std::endl;
#endif
}
else {
#ifdef IDCHOOSER_DEBUG
std::cerr << "GxsIdChooser: ID in constraint set: " << details.mId << std::endl;
#endif
}
chooser->model()->sort(0);
// now restore the current item. Problem is, we cannot use the ID position because it may have changed.
@ -233,12 +278,12 @@ static void loadPrivateIdsCallback(GxsIdDetailsType type, const RsIdentityDetail
chooser->blockSignals(false) ;
}
bool GxsIdChooser::isInConstraintSet(const RsGxsId& id) const
bool GxsIdChooser::isInConstraintSet(const RsGxsId& id) const
{
if(mConstraintIdsSet.empty()) // special case: empty set means no constraint
return true ;
return mConstraintIdsSet.find(id) != mConstraintIdsSet.end() ;
if(noIdConstraint)
return true ;
return mConstraintIdsSet.find(id) != mConstraintIdsSet.end() ;
}
void GxsIdChooser::setEntryEnabled(int indx,bool /*enabled*/)
{
@ -310,8 +355,8 @@ void GxsIdChooser::loadPrivateIds()
addItem(FilesDefs::getIconFromQtResourcePath(":/icons/png/add-identity.png"), str, id);
setItemData(count() - 1, QString("%1_%2").arg(TYPE_CREATE_ID).arg(str), ROLE_SORT);
setItemData(count() - 1, TYPE_CREATE_ID, ROLE_TYPE);
}
setDefaultItem();
emit idsLoaded();

View File

@ -58,10 +58,12 @@ public:
ChosenId_Ret getChosenId(RsGxsId &gxsId);
void setEntryEnabled(int index, bool enabled);
void setIdConstraintSet(const std::set<RsGxsId>& s) ;
void setIdConstraintSet(const std::set<RsGxsId>& s); // empty = all allowed
void intersectIdConstraintSet(const std::set<RsGxsId>& s);
void unionIdConstraintSet(const std::set<RsGxsId>& s);
bool isInConstraintSet(const RsGxsId& id) const ;
uint32_t countEnabledEntries() const ;
signals:
// emitted after first load of own ids
@ -84,9 +86,10 @@ private:
uint32_t mFlags;
RsGxsId mDefaultId;
bool mFirstLoad;
uint32_t mAllowedCount ;
uint32_t mAllowedCount ;
std::set<RsGxsId> mConstraintIdsSet ; // leave empty if all allowed
std::set<RsGxsId> mConstraintIdsSet ;
bool noIdConstraint;
// RsGxsUpdateBroadcastBase *mBase;
RsEventsHandlerId_t mEventHandlerId;

View File

@ -180,7 +180,7 @@ void CreateGxsForumMsg::newMsg()
// NOTE: mPosterId may not be our own; then GxsIdChooser will not include it.
idChooserFlags |= IDCHOOSER_NO_CREATE;
ui->idChooser->setIdConstraintSet(id_set);
ui->idChooser->intersectIdConstraintSet(id_set);
}
ui->idChooser->loadIds(idChooserFlags, mPosterId);
@ -585,6 +585,21 @@ void CreateGxsForumMsg::loadCircleInfo(const RsGxsGroupId& circle_id)
RsThread::async( [circle_id,this]()
{
// get set of eligible ids
RsGxsCircleDetails circleDetails;
rsGxsCircles->getCircleDetails(RsGxsCircleId(circle_id), circleDetails);
std::set<RsGxsId> ids;
uint32_t mask =
GXS_EXTERNAL_CIRCLE_FLAGS_IN_ADMIN_LIST |
GXS_EXTERNAL_CIRCLE_FLAGS_SUBSCRIBED;
for(auto it = circleDetails.mSubscriptionFlags.begin();
it != circleDetails.mSubscriptionFlags.end(); it++
) {
if((it->second & mask) == mask) {
ids.insert(it->first);
}
}
std::vector<RsGxsCircleGroup> circle_grp_v ;
rsGxsCircles->getCirclesInfo(std::list<RsGxsGroupId>{ circle_id }, circle_grp_v);
@ -602,17 +617,12 @@ void CreateGxsForumMsg::loadCircleInfo(const RsGxsGroupId& circle_id)
RsGxsCircleGroup cg = circle_grp_v.front();
RsQThreadUtils::postToObject( [cg,this]()
RsQThreadUtils::postToObject( [cg,ids,this]()
{
mForumCircleData = cg;
mForumCircleLoaded = true;
//std::cerr << "Loaded content of circle " << cg.mMeta.mGroupId << std::endl;
//for(std::set<RsGxsId>::const_iterator it(cg.mInvitedMembers.begin());it!=cg.mInvitedMembers.end();++it)
// std::cerr << " added constraint to circle element " << *it << std::endl;
ui->idChooser->setIdConstraintSet(cg.mInvitedMembers) ;
ui->idChooser->intersectIdConstraintSet(ids);
ui->idChooser->setFlags(IDCHOOSER_NO_CREATE | ui->idChooser->flags()) ; // since there's a circle involved, no ID creation can be needed
RsGxsId tmpid ;

View File

@ -730,12 +730,12 @@ void GxsForumThreadWidget::threadListCustomPopupMenu(QPoint /*point*/)
else
{
// Go through the list of own ids and see if one of them is a moderator
// TODO: offer to select which moderator ID to use if multiple IDs fit the conditions of the forum
std::list<RsGxsId> own_ids ;
rsIdentity->getOwnIds(own_ids) ;
for(auto it(own_ids.begin());it!=own_ids.end();++it)
// TODO: also make sure the ID is in the circle
if(mForumGroup.canEditPosts(*it))
{
contextMnu.addAction(editAct);
@ -1746,19 +1746,7 @@ void GxsForumThreadWidget::editForumMessageData(const RsGxsForumMsg& msg)
return;
}
// Go through the list of own ids and see if one of them is a moderator
// TODO: offer to select which moderator ID to use if multiple IDs fit the conditions of the forum
RsGxsId moderator_id ;
std::list<RsGxsId> own_ids ;
rsIdentity->getOwnIds(own_ids) ;
std::set<RsGxsId> modIds;
for(auto it(own_ids.begin());it!=own_ids.end();++it)
if(mForumGroup.mAdminList.ids.find(*it) != mForumGroup.mAdminList.ids.end())
modIds.insert(*it);
CreateGxsForumMsg *cfm = new CreateGxsForumMsg(groupId(), msg.mMeta.mParentId, msg.mMeta.mMsgId, msg.mMeta.mAuthorId, modIds);
CreateGxsForumMsg *cfm = new CreateGxsForumMsg(groupId(), msg.mMeta.mParentId, msg.mMeta.mMsgId, msg.mMeta.mAuthorId, mForumGroup.mAdminList.ids);
cfm->insertPastedText(QString::fromUtf8(msg.mMsg.c_str())) ;
cfm->show();