diff options
24 files changed, 2556 insertions, 1327 deletions
| diff --git a/indra/llcommon/roles_constants.h b/indra/llcommon/roles_constants.h index effd15ea72..ee3e8b6b74 100755 --- a/indra/llcommon/roles_constants.h +++ b/indra/llcommon/roles_constants.h @@ -53,7 +53,7 @@ enum LLRoleChangeType  // KNOWN HOLES: use these for any single bit powers you need  // bit 0x1 << 46 -// bit 0x1 << 49 and above +// bit 0x1 << 50 and above  // These powers were removed to make group roles simpler  // bit 0x1 << 41 (GP_ACCOUNTING_VIEW) @@ -63,88 +63,90 @@ const U64 GP_NO_POWERS = 0x0;  const U64 GP_ALL_POWERS = 0xFFFFFFFFFFFFFFFFLL;  // Membership -const U64 GP_MEMBER_INVITE		= 0x1 << 1;		// Invite member -const U64 GP_MEMBER_EJECT			= 0x1 << 2;		// Eject member from group -const U64 GP_MEMBER_OPTIONS		= 0x1 << 3;		// Toggle "Open enrollment" and change "Signup Fee" -const U64 GP_MEMBER_VISIBLE_IN_DIR = 0x1LL << 47; +const U64 GP_MEMBER_INVITE				= 0x1LL << 1;	// Invite member +const U64 GP_MEMBER_EJECT				= 0x1LL << 2;	// Eject member from group +const U64 GP_MEMBER_OPTIONS				= 0x1LL << 3;	// Toggle "Open enrollment" and change "Signup Fee" +const U64 GP_MEMBER_VISIBLE_IN_DIR		= 0x1LL << 47;  // Roles -const U64 GP_ROLE_CREATE			= 0x1 << 4;		// Create new roles -const U64 GP_ROLE_DELETE			= 0x1 << 5;		// Delete roles -const U64 GP_ROLE_PROPERTIES		= 0x1 << 6;		// Change Role Names, Titles, and Descriptions (Of roles the user is in, only, or any role in group?) -const U64 GP_ROLE_ASSIGN_MEMBER_LIMITED = 0x1 << 7; // Assign Member to a Role that the assigner is in -const U64 GP_ROLE_ASSIGN_MEMBER	= 0x1 << 8;		// Assign Member to Role -const U64 GP_ROLE_REMOVE_MEMBER	= 0x1 << 9;		// Remove Member from Role -const U64 GP_ROLE_CHANGE_ACTIONS	= 0x1 << 10;	// Change actions a role can perform +const U64 GP_ROLE_CREATE				= 0x1LL << 4;	// Create new roles +const U64 GP_ROLE_DELETE				= 0x1LL << 5;	// Delete roles +const U64 GP_ROLE_PROPERTIES			= 0x1LL << 6;	// Change Role Names, Titles, and Descriptions (Of roles the user is in, only, or any role in group?) +const U64 GP_ROLE_ASSIGN_MEMBER_LIMITED	= 0x1LL << 7;	// Assign Member to a Role that the assigner is in +const U64 GP_ROLE_ASSIGN_MEMBER			= 0x1LL << 8;	// Assign Member to Role +const U64 GP_ROLE_REMOVE_MEMBER			= 0x1LL << 9;	// Remove Member from Role +const U64 GP_ROLE_CHANGE_ACTIONS		= 0x1LL << 10;	// Change actions a role can perform  // Group Identity -const U64 GP_GROUP_CHANGE_IDENTITY = 0x1 << 11;	// Charter, insignia, 'Show In Group List', 'Publish on the web', 'Mature', all 'Show Member In Group Profile' checkboxes +const U64 GP_GROUP_CHANGE_IDENTITY		= 0x1LL << 11;	// Charter, insignia, 'Show In Group List', 'Publish on the web', 'Mature', all 'Show Member In Group Profile' checkboxes  // Parcel Management -const U64 GP_LAND_DEED			= 0x1 << 12;	// Deed Land and Buy Land for Group -const U64 GP_LAND_RELEASE			= 0x1 << 13;	// Release Land (to Gov. Linden) -const U64 GP_LAND_SET_SALE_INFO	= 0x1 << 14;	// Set for sale info (Toggle "For Sale", Set Price, Set Target, Toggle "Sell objects with the land") -const U64 GP_LAND_DIVIDE_JOIN		= 0x1 << 15;	// Divide and Join Parcels +const U64 GP_LAND_DEED					= 0x1LL << 12;	// Deed Land and Buy Land for Group +const U64 GP_LAND_RELEASE				= 0x1LL << 13;	// Release Land (to Gov. Linden) +const U64 GP_LAND_SET_SALE_INFO			= 0x1LL << 14;	// Set for sale info (Toggle "For Sale", Set Price, Set Target, Toggle "Sell objects with the land") +const U64 GP_LAND_DIVIDE_JOIN			= 0x1LL << 15;	// Divide and Join Parcels  // Parcel Identity -const U64 GP_LAND_FIND_PLACES		= 0x1 << 17;	// Toggle "Show in Find Places" and Set Category. -const U64 GP_LAND_CHANGE_IDENTITY = 0x1 << 18;	// Change Parcel Identity: Parcel Name, Parcel Description, Snapshot, 'Publish on the web', and 'Mature' checkbox -const U64 GP_LAND_SET_LANDING_POINT = 0x1 << 19;	// Set Landing Point +const U64 GP_LAND_FIND_PLACES			= 0x1LL << 17;	// Toggle "Show in Find Places" and Set Category. +const U64 GP_LAND_CHANGE_IDENTITY		= 0x1LL << 18;	// Change Parcel Identity: Parcel Name, Parcel Description, Snapshot, 'Publish on the web', and 'Mature' checkbox +const U64 GP_LAND_SET_LANDING_POINT		= 0x1LL << 19;	// Set Landing Point  // Parcel Settings -const U64 GP_LAND_CHANGE_MEDIA	= 0x1 << 20;	// Change Media Settings -const U64 GP_LAND_EDIT			= 0x1 << 21;	// Toggle Edit Land -const U64 GP_LAND_OPTIONS			= 0x1 << 22;	// Toggle Set Home Point, Fly, Outside Scripts, Create/Edit Objects, Landmark, and Damage checkboxes +const U64 GP_LAND_CHANGE_MEDIA			= 0x1LL << 20;	// Change Media Settings +const U64 GP_LAND_EDIT					= 0x1LL << 21;	// Toggle Edit Land +const U64 GP_LAND_OPTIONS				= 0x1LL << 22;	// Toggle Set Home Point, Fly, Outside Scripts, Create/Edit Objects, Landmark, and Damage checkboxes  // Parcel Powers -const U64 GP_LAND_ALLOW_EDIT_LAND = 0x1 << 23;	// Bypass Edit Land Restriction -const U64 GP_LAND_ALLOW_FLY		= 0x1 << 24;	// Bypass Fly Restriction -const U64 GP_LAND_ALLOW_CREATE	= 0x1 << 25;	// Bypass Create/Edit Objects Restriction -const U64 GP_LAND_ALLOW_LANDMARK	= 0x1 << 26;	// Bypass Landmark Restriction -const U64 GP_LAND_ALLOW_SET_HOME	= 0x1 << 28;	// Bypass Set Home Point Restriction -const U64 GP_LAND_ALLOW_HOLD_EVENT	= 0x1LL << 41;	// Allowed to hold events on group-owned land - +const U64 GP_LAND_ALLOW_EDIT_LAND		= 0x1LL << 23;	// Bypass Edit Land Restriction +const U64 GP_LAND_ALLOW_FLY				= 0x1LL << 24;	// Bypass Fly Restriction +const U64 GP_LAND_ALLOW_CREATE			= 0x1LL << 25;	// Bypass Create/Edit Objects Restriction +const U64 GP_LAND_ALLOW_LANDMARK		= 0x1LL << 26;	// Bypass Landmark Restriction +const U64 GP_LAND_ALLOW_SET_HOME		= 0x1LL << 28;	// Bypass Set Home Point Restriction +const U64 GP_LAND_ALLOW_HOLD_EVENT		= 0x1LL << 41;	// Allowed to hold events on group-owned land  // Parcel Access -const U64 GP_LAND_MANAGE_ALLOWED	= 0x1 << 29;	// Manage Allowed List -const U64 GP_LAND_MANAGE_BANNED	= 0x1 << 30;	// Manage Banned List -const U64 GP_LAND_MANAGE_PASSES	= 0x1LL << 31;	// Change Sell Pass Settings -const U64 GP_LAND_ADMIN			= 0x1LL << 32;	// Eject and Freeze Users on the land +const U64 GP_LAND_MANAGE_ALLOWED		= 0x1LL << 29;	// Manage Allowed List +const U64 GP_LAND_MANAGE_BANNED			= 0x1LL << 30;	// Manage Banned List +const U64 GP_LAND_MANAGE_PASSES			= 0x1LL << 31;	// Change Sell Pass Settings +const U64 GP_LAND_ADMIN					= 0x1LL << 32;	// Eject and Freeze Users on the land  // Parcel Content -const U64 GP_LAND_RETURN_GROUP_SET	= 0x1LL << 33;	// Return objects on parcel that are set to group -const U64 GP_LAND_RETURN_NON_GROUP	= 0x1LL << 34;	// Return objects on parcel that are not set to group -const U64 GP_LAND_RETURN_GROUP_OWNED= 0x1LL << 48;	// Return objects on parcel that are owned by the group +const U64 GP_LAND_RETURN_GROUP_SET		= 0x1LL << 33;	// Return objects on parcel that are set to group +const U64 GP_LAND_RETURN_NON_GROUP		= 0x1LL << 34;	// Return objects on parcel that are not set to group +const U64 GP_LAND_RETURN_GROUP_OWNED	= 0x1LL << 48;	// Return objects on parcel that are owned by the group  // Select a power-bit based on an object's relationship to a parcel.  const U64 GP_LAND_RETURN		= GP_LAND_RETURN_GROUP_OWNED   								| GP_LAND_RETURN_GROUP_SET	  								| GP_LAND_RETURN_NON_GROUP; -const U64 GP_LAND_GARDENING		= 0x1LL << 35;	// Parcel Gardening - plant and move linden trees +const U64 GP_LAND_GARDENING				= 0x1LL << 35;	// Parcel Gardening - plant and move linden trees  // Object Management -const U64 GP_OBJECT_DEED			= 0x1LL << 36;	// Deed Object -const U64 GP_OBJECT_MANIPULATE		= 0x1LL << 38;	// Manipulate Group Owned Objects (Move, Copy, Mod) -const U64 GP_OBJECT_SET_SALE		= 0x1LL << 39;	// Set Group Owned Object for Sale +const U64 GP_OBJECT_DEED				= 0x1LL << 36;	// Deed Object +const U64 GP_OBJECT_MANIPULATE			= 0x1LL << 38;	// Manipulate Group Owned Objects (Move, Copy, Mod) +const U64 GP_OBJECT_SET_SALE			= 0x1LL << 39;	// Set Group Owned Object for Sale  // Accounting -const U64 GP_ACCOUNTING_ACCOUNTABLE = 0x1LL << 40;	// Pay Group Liabilities and Receive Group Dividends +const U64 GP_ACCOUNTING_ACCOUNTABLE		= 0x1LL << 40;	// Pay Group Liabilities and Receive Group Dividends  // Notices -const U64 GP_NOTICES_SEND			= 0x1LL << 42;	// Send Notices -const U64 GP_NOTICES_RECEIVE		= 0x1LL << 43;	// Receive Notices and View Notice History +const U64 GP_NOTICES_SEND				= 0x1LL << 42;	// Send Notices +const U64 GP_NOTICES_RECEIVE			= 0x1LL << 43;	// Receive Notices and View Notice History  // Proposals  // TODO: _DEPRECATED suffix as part of vote removal - DEV-24856: -const U64 GP_PROPOSAL_START		= 0x1LL << 44;	// Start Proposal +const U64 GP_PROPOSAL_START				= 0x1LL << 44;	// Start Proposal  // TODO: _DEPRECATED suffix as part of vote removal - DEV-24856: -const U64 GP_PROPOSAL_VOTE		= 0x1LL << 45;	// Vote on Proposal +const U64 GP_PROPOSAL_VOTE				= 0x1LL << 45;	// Vote on Proposal  // Group chat moderation related -const U64 GP_SESSION_JOIN = 0x1LL << 16; //can join session -const U64 GP_SESSION_VOICE = 0x1LL << 27; //can hear/talk -const U64 GP_SESSION_MODERATOR = 0x1LL << 37; //can mute people's session +const U64 GP_SESSION_JOIN				= 0x1LL << 16;	//can join session +const U64 GP_SESSION_VOICE				= 0x1LL << 27;	//can hear/talk +const U64 GP_SESSION_MODERATOR			= 0x1LL << 37;	//can mute people's session + +// Group Banning +const U64 GP_GROUP_BAN_ACCESS			= 0x1LL << 49;	// Allows access to ban / un-ban agents from a group.  const U64 GP_DEFAULT_MEMBER = GP_ACCOUNTING_ACCOUNTABLE  								| GP_LAND_ALLOW_SET_HOME diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h index efcbe76795..b505ef0b4b 100755 --- a/indra/llcommon/stdenums.h +++ b/indra/llcommon/stdenums.h @@ -127,6 +127,7 @@ enum LLGroupChange  	GC_ROLE_DATA,  	GC_ROLE_MEMBER_DATA,  	GC_TITLES, +	GC_BANLIST,  	GC_ALL  }; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3a09bc530c..4efd2317eb 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -230,6 +230,7 @@ set(viewer_SOURCE_FILES      llfloatergesture.cpp      llfloatergodtools.cpp      llfloatergotoline.cpp +    llfloatergroupbulkban.cpp      llfloatergroupinvite.cpp      llfloatergroups.cpp      llfloaterhandler.cpp @@ -399,6 +400,8 @@ set(viewer_SOURCE_FILES      llpanelface.cpp      llpanelgenerictip.cpp      llpanelgroup.cpp +    llpanelgroupbulk.cpp +    llpanelgroupbulkban.cpp      llpanelgroupgeneral.cpp      llpanelgroupinvite.cpp      llpanelgrouplandmoney.cpp @@ -814,6 +817,7 @@ set(viewer_HEADER_FILES      llfloatergesture.h      llfloatergodtools.h      llfloatergotoline.h +    llfloatergroupbulkban.h      llfloatergroupinvite.h      llfloatergroups.h      llfloaterhandler.h @@ -976,6 +980,9 @@ set(viewer_HEADER_FILES      llpanelface.h      llpanelgenerictip.h      llpanelgroup.h +    llpanelgroupbulk.h +    llpanelgroupbulkimpl.h +    llpanelgroupbulkban.h      llpanelgroupgeneral.h      llpanelgroupinvite.h      llpanelgrouplandmoney.h diff --git a/indra/newview/llfloatergroupbulkban.cpp b/indra/newview/llfloatergroupbulkban.cpp new file mode 100644 index 0000000000..54a2283b13 --- /dev/null +++ b/indra/newview/llfloatergroupbulkban.cpp @@ -0,0 +1,134 @@ +/**  +* @file llfloatergroupbulkban.cpp +* @brief Floater to ban Residents from a group. +*  +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library 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 +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatergroupbulkban.h" +#include "llpanelgroupbulkban.h" +#include "lltrans.h" +#include "lldraghandle.h" + + +class LLFloaterGroupBulkBan::impl +{ +public: +	impl(const LLUUID& group_id) : mGroupID(group_id), mBulkBanPanelp(NULL) {} +	~impl() {} + +	static void closeFloater(void* data); + +public: +	LLUUID mGroupID; +	LLPanelGroupBulkBan* mBulkBanPanelp; + +	static std::map<LLUUID, LLFloaterGroupBulkBan*> sInstances; +}; + +// +// Globals +// +std::map<LLUUID, LLFloaterGroupBulkBan*> LLFloaterGroupBulkBan::impl::sInstances; + +void LLFloaterGroupBulkBan::impl::closeFloater(void* data) +{ +	LLFloaterGroupBulkBan* floaterp = (LLFloaterGroupBulkBan*)data; +	if(floaterp) +		floaterp->closeFloater(); +} + +//----------------------------------------------------------------------------- +// Implementation +//----------------------------------------------------------------------------- +LLFloaterGroupBulkBan::LLFloaterGroupBulkBan(const LLUUID& group_id/*=LLUUID::null*/) +	: LLFloater(group_id) +{ +	S32 floater_header_size = getHeaderHeight(); +	LLRect contents; + +	mImpl = new impl(group_id); +	mImpl->mBulkBanPanelp = new LLPanelGroupBulkBan(group_id); + +	contents = mImpl->mBulkBanPanelp->getRect(); +	contents.mTop -= floater_header_size; + +	setTitle(mImpl->mBulkBanPanelp->getString("GroupBulkBan")); +	mImpl->mBulkBanPanelp->setCloseCallback(impl::closeFloater, this); +	mImpl->mBulkBanPanelp->setRect(contents); + +	addChild(mImpl->mBulkBanPanelp); +} + +LLFloaterGroupBulkBan::~LLFloaterGroupBulkBan() +{ +	if(mImpl->mGroupID.notNull()) +	{ +		impl::sInstances.erase(mImpl->mGroupID); +	} + +	delete mImpl->mBulkBanPanelp; +	delete mImpl; +} + +void LLFloaterGroupBulkBan::showForGroup(const LLUUID& group_id, uuid_vec_t* agent_ids) +{ +	const LLFloater::Params& floater_params = LLFloater::getDefaultParams(); +	S32 floater_header_size = floater_params.header_height; +	LLRect contents; + +	// Make sure group_id isn't null +	if (group_id.isNull()) +	{ +		llwarns << "LLFloaterGroupInvite::showForGroup with null group_id!" << llendl; +		return; +	} + +	// If we don't have a floater for this group, create one. +	LLFloaterGroupBulkBan* fgb = get_if_there(impl::sInstances, +		group_id, +		(LLFloaterGroupBulkBan*)NULL); +	if (!fgb) +	{ +		fgb = new LLFloaterGroupBulkBan(group_id); +		contents = fgb->mImpl->mBulkBanPanelp->getRect(); +		contents.mTop += floater_header_size; +		fgb->setRect(contents); +		fgb->getDragHandle()->setRect(contents); +		fgb->getDragHandle()->setTitle(fgb->mImpl->mBulkBanPanelp->getString("GroupBulkBan")); + +		impl::sInstances[group_id] = fgb; + +		fgb->mImpl->mBulkBanPanelp->clear(); +	} + +	if (agent_ids != NULL) +	{ +		fgb->mImpl->mBulkBanPanelp->addUsers(*agent_ids); +	} + +	fgb->center(); +	fgb->openFloater(); +	fgb->mImpl->mBulkBanPanelp->update(); +} diff --git a/indra/newview/llfloatergroupbulkban.h b/indra/newview/llfloatergroupbulkban.h new file mode 100644 index 0000000000..5b680a1ba4 --- /dev/null +++ b/indra/newview/llfloatergroupbulkban.h @@ -0,0 +1,48 @@ +/**  +* @file   llfloatergroupbulkban.h +* @brief  This floater is a wrapper for LLPanelGroupBulkBan, which +* is used to ban Residents from a specific group. +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library 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 +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ + +#ifndef LL_LLFLOATERGROUPBULKBAN_H +#define LL_LLFLOATERGROUPBULKBAN_H + +#include "llfloater.h" +#include "lluuid.h" + +class LLFloaterGroupBulkBan : public LLFloater +{ +public: +	virtual ~LLFloaterGroupBulkBan(); + +	static void showForGroup(const LLUUID& group_id, uuid_vec_t* agent_ids = NULL); + +protected: +	LLFloaterGroupBulkBan(const LLUUID& group_id = LLUUID::null); + +	class impl; +	impl* mImpl; +}; + +#endif // LL_LLFLOATERGROUPBULKBAN_H diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index cbd844cdac..7e7098420d 100755 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -231,11 +231,11 @@ LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) :  	mMemberCount(0),  	mRoleCount(0),  	mReceivedRoleMemberPairs(0), -	mMemberDataComplete(FALSE), -	mRoleDataComplete(FALSE), -	mRoleMemberDataComplete(FALSE), -	mGroupPropertiesDataComplete(FALSE), -	mPendingRoleMemberRequest(FALSE), +	mMemberDataComplete(false), +	mRoleDataComplete(false), +	mRoleMemberDataComplete(false), +	mGroupPropertiesDataComplete(false), +	mPendingRoleMemberRequest(false),  	mAccessTime(0.0f)  {  	mMemberVersion.generate(); @@ -424,7 +424,7 @@ void LLGroupMgrGroupData::removeMemberData()  		delete mi->second;  	}  	mMembers.clear(); -	mMemberDataComplete = FALSE; +	mMemberDataComplete = false;  	mMemberVersion.generate();  } @@ -446,8 +446,8 @@ void LLGroupMgrGroupData::removeRoleData()  	}  	mRoles.clear();  	mReceivedRoleMemberPairs = 0; -	mRoleDataComplete = FALSE; -	mRoleMemberDataComplete = FALSE; +	mRoleDataComplete = false; +	mRoleMemberDataComplete= false;  }  void LLGroupMgrGroupData::removeRoleMemberData() @@ -471,7 +471,7 @@ void LLGroupMgrGroupData::removeRoleMemberData()  	}  	mReceivedRoleMemberPairs = 0; -	mRoleMemberDataComplete = FALSE; +	mRoleMemberDataComplete= false;  }  LLGroupMgrGroupData::~LLGroupMgrGroupData() @@ -742,6 +742,20 @@ void LLGroupMgrGroupData::cancelRoleChanges()  	// Clear out all changes!  	mRoleChanges.clear();  } + +void LLGroupMgrGroupData::createBanEntry(const LLUUID& ban_id, const LLGroupBanData& ban_data) +{  +	mBanList[ban_id] = ban_data; +} + +void LLGroupMgrGroupData::removeBanEntry(const LLUUID& ban_id) +{ +	mBanList.erase(ban_id); +} + + + +  //  // LLGroupMgr  // @@ -951,12 +965,12 @@ void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data)  	if (group_datap->mMembers.size() ==  (U32)group_datap->mMemberCount)  	{ -		group_datap->mMemberDataComplete = TRUE; +		group_datap->mMemberDataComplete = true;  		group_datap->mMemberRequestID.setNull();  		// We don't want to make role-member data requests until we have all the members  		if (group_datap->mPendingRoleMemberRequest)  		{ -			group_datap->mPendingRoleMemberRequest = FALSE; +			group_datap->mPendingRoleMemberRequest = false;  			LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_datap->mID);  		}  	} @@ -1026,7 +1040,7 @@ void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data)  	group_datap->mMemberCount = num_group_members;  	group_datap->mRoleCount = num_group_roles + 1; // Add the everyone role. -	group_datap->mGroupPropertiesDataComplete = TRUE; +	group_datap->mGroupPropertiesDataComplete = true;  	group_datap->mChanged = TRUE;  	LLGroupMgr::getInstance()->notifyObservers(GC_PROPERTIES); @@ -1103,12 +1117,12 @@ void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data)  	if (group_datap->mRoles.size() == (U32)group_datap->mRoleCount)  	{ -		group_datap->mRoleDataComplete = TRUE; +		group_datap->mRoleDataComplete = true;  		group_datap->mRoleDataRequestID.setNull();  		// We don't want to make role-member data requests until we have all the role data  		if (group_datap->mPendingRoleMemberRequest)  		{ -			group_datap->mPendingRoleMemberRequest = FALSE; +			group_datap->mPendingRoleMemberRequest = false;  			LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_datap->mID);  		}  	} @@ -1217,7 +1231,7 @@ void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)  			}  		} -        group_datap->mRoleMemberDataComplete = TRUE; +        group_datap->mRoleMemberDataComplete= true;  		group_datap->mRoleMembersRequestID.setNull();  	} @@ -1543,7 +1557,7 @@ void LLGroupMgr::sendGroupRoleMembersRequest(const LLUUID& group_id)  			llinfos << " Pending: " << (group_datap->mPendingRoleMemberRequest ? "Y" : "N")  				<< " MemberDataComplete: " << (group_datap->mMemberDataComplete ? "Y" : "N")  				<< " RoleDataComplete: " << (group_datap->mRoleDataComplete ? "Y" : "N") << llendl; -			group_datap->mPendingRoleMemberRequest = TRUE; +			group_datap->mPendingRoleMemberRequest = true;  			return;  		} @@ -1841,6 +1855,117 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id,  // Responder class for capability group management +class GroupBanDataResponder : public LLHTTPClient::Responder +{ +public: +	GroupBanDataResponder() {} +	virtual ~GroupBanDataResponder() {} +	virtual void result(const LLSD& pContent); +	virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); +}; + +void GroupBanDataResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) +{ +	LL_WARNS("GrpMgr") << "Error receiving group member data [status:"  +		<< pStatus << "]: " << pContent << LL_ENDL; +} + +void GroupBanDataResponder::result(const LLSD& content) +{ +	LLGroupMgr::processGroupBanRequest(content); +} + +void LLGroupMgr::sendGroupBanRequest(	EBanRequestType request_type,  +										const LLUUID& group_id,  +										EBanRequestAction ban_action, /* = BAN_NO_ACTION */ +										const std::vector<LLUUID> ban_list) /* = std::vector<LLUUID>() */ +{ +	LLViewerRegion* currentRegion = gAgent.getRegion(); +	if(!currentRegion) +	{ +		LL_WARNS("GrpMgr") << "Agent does not have a current region. Uh-oh!" << LL_ENDL; +		return; +	} + +	// Check to make sure we have our capabilities +	if(!currentRegion->capabilitiesReceived()) +	{ +		LL_WARNS("GrpMgr") << " Capabilities not received!" << LL_ENDL; +		return; +	} + +	// Get our capability +	std::string cap_url =  currentRegion->getCapability("GroupBan"); +	if(cap_url.empty()) +	{ +		return; +	} +	cap_url += "?group_id=" + group_id.asString(); + +	LLSD body = LLSD::emptyMap(); +	body["ban_action"] = ban_action; +	// Add our list of potential banned agents to the list +	body["ban_ids"]	= LLSD::emptyArray(); +	LLSD ban_entry; + +	uuid_vec_t::const_iterator iter = ban_list.begin(); +	for(;iter != ban_list.end(); ++iter) +	{ +		ban_entry = (*iter); +		body["ban_ids"].append(ban_entry); +	} + +	LLHTTPClient::ResponderPtr grp_ban_responder = new GroupBanDataResponder(); +	switch(request_type) +	{ +	case REQUEST_GET: +		LLHTTPClient::get(cap_url, grp_ban_responder); +		break; +	case REQUEST_POST: +		LLHTTPClient::post(cap_url, body, grp_ban_responder); +		break; +	} +} + + +void LLGroupMgr::processGroupBanRequest(const LLSD& content) +{ +	// Did we get anything in content? +	if(!content.size()) +	{ +		LL_WARNS("GrpMgr") << "No group member data received." << LL_ENDL; +		return; +	} + +	LLUUID group_id = content["group_id"].asUUID(); +	 +	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id); +	if (!gdatap) +		return; +	 +	LLSD::map_const_iterator i		= content["ban_list"].beginMap(); +	LLSD::map_const_iterator iEnd	= content["ban_list"].endMap(); +	for(;i != iEnd; ++i) +	{ +		const LLUUID ban_id(i->first); +		LLSD ban_entry(i->second); +		 +		LLGroupBanData ban_data; +		if(ban_entry.has("ban_date")) +		{ +			ban_data.mBanDate = ban_entry["ban_date"].asDate(); +		} + +		gdatap->createBanEntry(ban_id, ban_data); +	} + +	gdatap->mChanged = TRUE; +	LLGroupMgr::getInstance()->notifyObservers(GC_BANLIST); +} + + + +// Responder class for capability group management  class GroupMemberDataResponder : public LLHTTPClient::Responder  {  public: @@ -1925,7 +2050,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)  	if(num_members < 1)  		return; -	LLUUID	group_id = content["group_id"].asUUID(); +	LLUUID group_id = content["group_id"].asUUID();  	LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id);  	if(!group_datap) @@ -2008,12 +2133,12 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)  		LLGroupMgr::getInstance()->sendGroupTitlesRequest(group_id); -	group_datap->mMemberDataComplete = TRUE; +	group_datap->mMemberDataComplete = true;  	group_datap->mMemberRequestID.setNull();  	// Make the role-member data request  	if (group_datap->mPendingRoleMemberRequest)  	{ -		group_datap->mPendingRoleMemberRequest = FALSE; +		group_datap->mPendingRoleMemberRequest = false;  		LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_id);  	} diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index d8c1ab7ef5..ba767b91ad 100755 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -33,7 +33,11 @@  #include <string>  #include <map> +// Forward Declarations  class LLMessageSystem; +class LLGroupRoleData; +class LLGroupMgr; +  class LLGroupMgrObserver  { @@ -54,8 +58,6 @@ public:  	virtual void changed(const LLUUID& group_id, LLGroupChange gc) = 0;  }; -class LLGroupRoleData; -  class LLGroupMemberData  {  friend class LLGroupMgrGroupData; @@ -190,6 +192,16 @@ struct lluuid_pair_less  	}  }; + +struct LLGroupBanData +{ +	LLGroupBanData(): mBanDate()	{} +	~LLGroupBanData()	{} +	 +	LLDate mBanDate; // Just store something here to ensure it works. +}; + +  struct LLGroupTitle  {  	std::string mTitle; @@ -197,8 +209,6 @@ struct LLGroupTitle  	BOOL		mSelected;  }; -class LLGroupMgr; -  class LLGroupMgrGroupData  {  friend class LLGroupMgr; @@ -228,27 +238,36 @@ public:  	void recalcAllAgentPowers();  	void recalcAgentPowers(const LLUUID& agent_id); -	BOOL isMemberDataComplete() { return mMemberDataComplete; } -	BOOL isRoleDataComplete() { return mRoleDataComplete; } -	BOOL isRoleMemberDataComplete() { return mRoleMemberDataComplete; } -	BOOL isGroupPropertiesDataComplete() { return mGroupPropertiesDataComplete; } +	bool isMemberDataComplete() { return mMemberDataComplete; } +	bool isRoleDataComplete() { return mRoleDataComplete; } +	bool isRoleMemberDataComplete() { return mRoleMemberDataComplete; } +	bool isGroupPropertiesDataComplete() { return mGroupPropertiesDataComplete; }  	F32 getAccessTime() const { return mAccessTime; }  	void setAccessed();  	const LLUUID& getMemberVersion() const { return mMemberVersion; } +	void clearBanList() { mBanList.clear(); } +	void getBanList(const LLUUID& group_id, LLGroupBanData& ban_data); +	const LLGroupBanData& getBanEntry(const LLUUID& ban_id) { return mBanList[ban_id]; } +	 +	void createBanEntry(const LLUUID& ban_id, const LLGroupBanData& ban_data = LLGroupBanData()); +	void removeBanEntry(const LLUUID& ban_id); +	 +  public:  	typedef	std::map<LLUUID,LLGroupMemberData*> member_list_t;  	typedef	std::map<LLUUID,LLGroupRoleData*> role_list_t;  	typedef std::map<lluuid_pair,LLRoleMemberChange,lluuid_pair_less> change_map_t;  	typedef std::map<LLUUID,LLRoleData> role_data_map_t; +	typedef std::map<LLUUID,LLGroupBanData> ban_list_t; +  	member_list_t		mMembers;  	role_list_t			mRoles; - -	  	change_map_t		mRoleMemberChanges;  	role_data_map_t		mRoleChanges; +	ban_list_t			mBanList;  	std::vector<LLGroupTitle> mTitles; @@ -279,12 +298,12 @@ private:  	LLUUID				mTitlesRequestID;  	U32					mReceivedRoleMemberPairs; -	BOOL				mMemberDataComplete; -	BOOL				mRoleDataComplete; -	BOOL				mRoleMemberDataComplete; -	BOOL				mGroupPropertiesDataComplete; +	bool				mMemberDataComplete; +	bool				mRoleDataComplete; +	bool				mRoleMemberDataComplete; +	bool				mGroupPropertiesDataComplete; -	BOOL				mPendingRoleMemberRequest; +	bool				mPendingRoleMemberRequest;  	F32					mAccessTime;  	// Generate a new ID every time mMembers @@ -312,6 +331,22 @@ class LLGroupMgr : public LLSingleton<LLGroupMgr>  	LOG_CLASS(LLGroupMgr);  public: +	enum EBanRequestType +	{ +		REQUEST_GET = 0, +		REQUEST_POST, +		REQUEST_PUT, +		REQUEST_DEL +	}; + +	enum EBanRequestAction +	{ +		BAN_NO_ACTION	= 0, +		BAN_CREATE		= 1, +		BAN_DELETE		= 2 +	}; + +public:  	LLGroupMgr();  	~LLGroupMgr(); @@ -344,8 +379,14 @@ public:  	static void sendGroupMemberInvites(const LLUUID& group_id, std::map<LLUUID,LLUUID>& role_member_pairs);  	static void sendGroupMemberEjects(const LLUUID& group_id,  									  uuid_vec_t& member_ids); +	 +	static void sendGroupBanRequest(EBanRequestType request_type,  +									const LLUUID& group_id,	 +									EBanRequestAction ban_action = BAN_NO_ACTION, +									const uuid_vec_t ban_list = uuid_vec_t()); + +	static void processGroupBanRequest(const LLSD& content); -	// BAKER  	void sendCapGroupMembersRequest(const LLUUID& group_id);  	static void processCapGroupMembersRequest(const LLSD& content); @@ -390,4 +431,3 @@ private:  #endif - diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index 7ddd04fed0..385d3e8ad2 100755 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -65,15 +65,14 @@ LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p)  	mNameColumn(p.name_column.column_name),  	mAllowCallingCardDrop(p.allow_calling_card_drop),  	mShortNames(p.short_names), -	mAvatarNameCacheConnection() +	mAvatarNameCacheConnection(), +	mPendingLookupsRemaining(0)  {}  // public  LLScrollListItem* LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos,  								 BOOL enabled, const std::string& suffix)  { -	//llinfos << "LLNameListCtrl::addNameItem " << agent_id << llendl; -  	NameItem item;  	item.value = agent_id;  	item.enabled = enabled; @@ -335,6 +334,17 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(  					mAvatarNameCacheConnection.disconnect();  				}  				mAvatarNameCacheConnection = LLAvatarNameCache::get(id,boost::bind(&LLNameListCtrl::onAvatarNameCache,this, _1, _2, item->getHandle())); + +				if(mPendingLookupsRemaining <= 0) +				{ +					// BAKER TODO: +					// We might get into a state where mPendingLookupsRemaining might +					//	go negative.  So just reset it right now and figure out if it's +					//	possible later :) +					mPendingLookupsRemaining = 0; +					mNameListCompleteSignal(false); +				} +				mPendingLookupsRemaining++;  			}  			break;  		} @@ -386,6 +396,8 @@ void LLNameListCtrl::removeNameItem(const LLUUID& agent_id)  	{  		selectNthItem(idx); // not sure whether this is needed, taken from previous implementation  		deleteSingleItem(idx); + +		mPendingLookupsRemaining--;  	}  } @@ -412,6 +424,23 @@ void LLNameListCtrl::onAvatarNameCache(const LLUUID& agent_id,  		}  	} +	////////////////////////////////////////////////////////////////////////// +	// BAKER - FIX NameListCtrl + 	//if (mPendingLookupsRemaining <= 0) + 	{ + 		// We might get into a state where mPendingLookupsRemaining might + 		//	go negative.  So just reset it right now and figure out if it's + 		//	possible later :) + 		//mPendingLookupsRemaining = 0; +		 + 		mNameListCompleteSignal(true); + 	} + 	//else + 	{ + 	//	mPendingLookupsRemaining--; + 	} +	////////////////////////////////////////////////////////////////////////// +  	dirtyColumns();  } diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 5aa1e1c458..a3e17eb6df 100755 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -67,6 +67,8 @@ class LLNameListCtrl  :	public LLScrollListCtrl, public LLInstanceTracker<LLNameListCtrl>  {  public: +	typedef boost::signals2::signal<void(bool)> namelist_complete_signal_t; +  	typedef enum e_name_type  	{  		INDIVIDUAL, @@ -151,7 +153,7 @@ public:  	/*virtual*/ void updateColumns(bool force_update); -	/*virtual*/ void	mouseOverHighlightNthItem( S32 index ); +	/*virtual*/ void mouseOverHighlightNthItem( S32 index );  private:  	void showInspector(const LLUUID& avatar_id, bool is_group);  	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, LLHandle<LLNameListItem> item); @@ -162,6 +164,16 @@ private:  	BOOL			mAllowCallingCardDrop;  	bool			mShortNames;  // display name only, no SLID  	boost::signals2::connection mAvatarNameCacheConnection; + +	S32 mPendingLookupsRemaining; +	namelist_complete_signal_t mNameListCompleteSignal; +	 +public: +	boost::signals2::connection setOnNameListCompleteCallback(boost::function<void(bool)> onNameListCompleteCallback)  +	{  +		return mNameListCompleteSignal.connect(onNameListCompleteCallback);  +	} +  }; diff --git a/indra/newview/llpanelgroupbulk.cpp b/indra/newview/llpanelgroupbulk.cpp new file mode 100644 index 0000000000..ed05a5c7d1 --- /dev/null +++ b/indra/newview/llpanelgroupbulk.cpp @@ -0,0 +1,406 @@ +/**  +* @file llpanelgroupbulk.cpp +* @brief Implementation of llpanelgroupbulk +* @author Baker@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library 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 +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelgroupbulk.h" +#include "llpanelgroupbulkimpl.h" + +#include "llagent.h" +#include "llavatarnamecache.h" +#include "llfloateravatarpicker.h" +#include "llbutton.h" +#include "llcallingcard.h" +#include "llcombobox.h" +#include "llgroupactions.h" +#include "llgroupmgr.h" +#include "llnamelistctrl.h" +#include "llnotificationsutil.h" +#include "llscrolllistitem.h" +#include "llspinctrl.h" +#include "lltextbox.h" +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "lluictrlfactory.h" +#include "llviewerwindow.h" + + +////////////////////////////////////////////////////////////////////////// +// Implementation of llpanelgroupbulkimpl.h functions +////////////////////////////////////////////////////////////////////////// +LLPanelGroupBulkImpl::LLPanelGroupBulkImpl(const LLUUID& group_id) : +	mGroupID(group_id), +	mBulkAgentList(NULL), +	mOKButton(NULL), +	mRemoveButton(NULL), +	mGroupName(NULL), +	mLoadingText(), +	mTooManySelected(), +	mCloseCallback(NULL), +	mCloseCallbackUserData(NULL), +	mAvatarNameCacheConnection(), +	mRoleNames(NULL), +	mOwnerWarning(), +	mAlreadyInGroup(), +	mConfirmedOwnerInvite(false) +{} + +LLPanelGroupBulkImpl::~LLPanelGroupBulkImpl() +{ +	if(mAvatarNameCacheConnection.connected()) +	{ +		mAvatarNameCacheConnection.disconnect(); +	} +} + +void LLPanelGroupBulkImpl::callbackClickAdd(void* userdata) +{ +	LLPanelGroupBulk* panelp = (LLPanelGroupBulk*)userdata; + +	if(panelp) +	{ +		//Right now this is hard coded with some knowledge that it is part +		//of a floater since the avatar picker needs to be added as a dependent +		//floater to the parent floater. +		//Soon the avatar picker will be embedded into this panel +		//instead of being it's own separate floater.  But that is next week. +		//This will do for now. -jwolk May 10, 2006 +		LLView* button = panelp->findChild<LLButton>("add_button"); +		LLFloater* root_floater = gFloaterView->getParentFloater(panelp); +		LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( +			boost::bind(callbackAddUsers, _1, panelp->mImplementation), TRUE, FALSE, FALSE, root_floater->getName(), button); +		if(picker) +		{ +			root_floater->addDependentFloater(picker); +		} +	} +} + +void LLPanelGroupBulkImpl::callbackClickRemove(void* userdata) +{ +	LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*)userdata; +	if (selfp)  +		selfp->handleRemove(); +} + +void LLPanelGroupBulkImpl::callbackClickCancel(void* userdata) +{ +	LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*)userdata; +	if(selfp)  +		(*(selfp->mCloseCallback))(selfp->mCloseCallbackUserData); +} + +void LLPanelGroupBulkImpl::callbackSelect(LLUICtrl* ctrl, void* userdata) +{ +	LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*)userdata; +	if (selfp)  +		selfp->handleSelection(); +} + +void LLPanelGroupBulkImpl::callbackAddUsers(const uuid_vec_t& agent_ids, void* user_data) +{ +	std::vector<std::string> names; +	for (S32 i = 0; i < (S32)agent_ids.size(); i++) +	{ +		LLAvatarName av_name; +		if (LLAvatarNameCache::get(agent_ids[i], &av_name)) +		{ +			onAvatarNameCache(agent_ids[i], av_name, user_data); +		} +		else  +		{ +			LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*) user_data; +			if (selfp) +			{ +				if (selfp->mAvatarNameCacheConnection.connected()) +				{ +					selfp->mAvatarNameCacheConnection.disconnect(); +				} +				// *TODO : Add a callback per avatar name being fetched. +				selfp->mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_ids[i],boost::bind(onAvatarNameCache, _1, _2, user_data)); +			} +		} +	} +} + +void LLPanelGroupBulkImpl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, void* user_data) +{ +	LLPanelGroupBulkImpl* selfp = (LLPanelGroupBulkImpl*) user_data; + +	if (selfp) +	{ +		if (selfp->mAvatarNameCacheConnection.connected()) +		{ +			selfp->mAvatarNameCacheConnection.disconnect(); +		} +		std::vector<std::string> names; +		uuid_vec_t agent_ids; +		agent_ids.push_back(agent_id); +		names.push_back(av_name.getCompleteName()); + +		selfp->addUsers(names, agent_ids); +	} +} + +void LLPanelGroupBulkImpl::handleRemove() +{ +	std::vector<LLScrollListItem*> selection = mBulkAgentList->getAllSelected(); +	if (selection.empty())  +		return; + +	mBulkAgentList->deleteSelectedItems(); +	mRemoveButton->setEnabled(FALSE); + +	if(	mOKButton && mOKButton->getEnabled() && +		mBulkAgentList->isEmpty()) +	{ +		mOKButton->setEnabled(FALSE); +	} +} + +void LLPanelGroupBulkImpl::handleSelection() +{ +	std::vector<LLScrollListItem*> selection = mBulkAgentList->getAllSelected(); +	if (selection.empty()) +		mRemoveButton->setEnabled(FALSE); +	else +		mRemoveButton->setEnabled(TRUE); +} + +void LLPanelGroupBulkImpl::addUsers(const std::vector<std::string>& names, const uuid_vec_t& agent_ids) +{ +	std::string name; +	LLUUID id; + +	for (S32 i = 0; i < (S32)names.size(); ++i) +	{ +		name = names[i]; +		id = agent_ids[i]; + +		// Make sure this agent isn't already in the list. +		bool already_in_list = false; +		std::vector<LLScrollListItem*> items = mBulkAgentList->getAllData(); +		std::vector<LLScrollListItem*>::iterator iter = items.begin(); +		for (; iter != items.end(); ++iter) +		{ +			LLScrollListItem* item = *iter; +			if (item->getUUID() == id) +			{ +				already_in_list = true; +				break; +			} +		} +		if (already_in_list) +		{ +			continue; +		} + +		//add the name to the names list +		LLSD row; +		row["id"] = id; +		row["columns"][0]["value"] = name; + +		mBulkAgentList->addElement(row); +		 +		// We've successfully added someone to the list. +		if(mOKButton && !mOKButton->getEnabled()) +			mOKButton->setEnabled(TRUE); +	} +} + +void LLPanelGroupBulkImpl::setGroupName(std::string name) +{ +	if(mGroupName) +		mGroupName->setText(name); +} + + +LLPanelGroupBulk::LLPanelGroupBulk(const LLUUID& group_id) :  +	LLPanel(), +	mImplementation(new LLPanelGroupBulkImpl(group_id)), +	mPendingGroupPropertiesUpdate(false), +	mPendingRoleDataUpdate(false), +	mPendingMemberDataUpdate(false) +{} + +LLPanelGroupBulk::~LLPanelGroupBulk() +{ +	delete mImplementation; +} + +void LLPanelGroupBulk::clear() +{ +	if(mImplementation->mBulkAgentList) +		mImplementation->mBulkAgentList->deleteAllItems(); +	 +	if(mImplementation->mOKButton) +		mImplementation->mOKButton->setEnabled(FALSE); +} + +void LLPanelGroupBulk::update() +{ +	updateGroupName(); +	updateGroupData(); +} + +void LLPanelGroupBulk::draw() +{ +	LLPanel::draw(); +	update(); +} + +void LLPanelGroupBulk::updateGroupName() +{ +	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID); + +	if(	gdatap && +		gdatap->isGroupPropertiesDataComplete()) +	{ +		// Only do work if the current group name differs +		if(mImplementation->mGroupName->getText().compare(gdatap->mName) != 0) +			mImplementation->setGroupName(gdatap->mName); +	} +	else +	{ +		mImplementation->setGroupName(mImplementation->mLoadingText); +	} +} + +void LLPanelGroupBulk::updateGroupData() +{ +	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID); +	if(!gdatap) +	{ +		LL_WARNS("Groups") << "Unable to get group data for group " << mImplementation->mGroupID << LL_ENDL; +		return; +	} + +	if(gdatap->isGroupPropertiesDataComplete()) +		mPendingGroupPropertiesUpdate = false; +	else +	{ +		if(!mPendingGroupPropertiesUpdate) +		{ +			mPendingGroupPropertiesUpdate = true; +			LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID); +		} +	} + +	if(gdatap->isRoleDataComplete()) +		mPendingRoleDataUpdate = false; +	else +	{ +		if(!mPendingRoleDataUpdate) +		{ +			mPendingRoleDataUpdate = true; +			LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID); +		} +	} + +	if(gdatap->isMemberDataComplete()) +		mPendingMemberDataUpdate = false; +	else +	{ +		if(!mPendingMemberDataUpdate) +		{ +			mPendingMemberDataUpdate = true; +			LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID); +		} +	} +} + +void LLPanelGroupBulk::addUserCallback(const LLUUID& id, const LLAvatarName& av_name) +{ +	std::vector<std::string> names; +	uuid_vec_t agent_ids; +	agent_ids.push_back(id); +	names.push_back(av_name.getAccountName()); + +	mImplementation->addUsers(names, agent_ids); +} + +void LLPanelGroupBulk::setCloseCallback(void (*close_callback)(void*), void* data) +{ +	mImplementation->mCloseCallback         = close_callback; +	mImplementation->mCloseCallbackUserData = data; +} + +void LLPanelGroupBulk::addUsers(uuid_vec_t& agent_ids) +{ +	std::vector<std::string> names; +	for (S32 i = 0; i < (S32)agent_ids.size(); i++) +	{ +		std::string fullname; +		LLUUID agent_id = agent_ids[i]; +		LLViewerObject* dest = gObjectList.findObject(agent_id); +		if(dest && dest->isAvatar()) +		{ +			LLNameValue* nvfirst = dest->getNVPair("FirstName"); +			LLNameValue* nvlast = dest->getNVPair("LastName"); +			if(nvfirst && nvlast) +			{ +				fullname = LLCacheName::buildFullName( +					nvfirst->getString(), nvlast->getString()); + +			} +			if (!fullname.empty()) +			{ +				names.push_back(fullname); +			}  +			else  +			{ +				llwarns << "llPanelGroupBulk: Selected avatar has no name: " << dest->getID() << llendl; +				names.push_back("(Unknown)"); +			} +		} +		else +		{ +			//looks like user try to invite offline friend +			//for offline avatar_id gObjectList.findObject() will return null +			//so we need to do this additional search in avatar tracker, see EXT-4732 +			if (LLAvatarTracker::instance().isBuddy(agent_id)) +			{ +				LLAvatarName av_name; +				if (!LLAvatarNameCache::get(agent_id, &av_name)) +				{ +					// actually it should happen, just in case +					LLAvatarNameCache::get(LLUUID(agent_id), boost::bind(&LLPanelGroupBulk::addUserCallback, this, _1, _2)); +					// for this special case! +					//when there is no cached name we should remove resident from agent_ids list to avoid breaking of sequence +					// removed id will be added in callback +					agent_ids.erase(agent_ids.begin() + i); +				} +				else +				{ +					names.push_back(av_name.getAccountName()); +				} +			} +		} +	} +	mImplementation->addUsers(names, agent_ids); +} + diff --git a/indra/newview/llpanelgroupbulk.h b/indra/newview/llpanelgroupbulk.h new file mode 100644 index 0000000000..222931eabc --- /dev/null +++ b/indra/newview/llpanelgroupbulk.h @@ -0,0 +1,74 @@ +/**  +* @file   llpanelgroupbulk.h +* @brief  Header file for llpanelgroupbulk +* @author Baker@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library 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 +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ +#ifndef LL_LLPANELGROUPBULK_H +#define LL_LLPANELGROUPBULK_H + +#include "llpanel.h" +#include "lluuid.h" + +class LLAvatarName; +class LLGroupMgrGroupData; +class LLPanelGroupBulkImpl; + +// Base panel class for bulk group invite / ban floaters +class LLPanelGroupBulk : public LLPanel +{ +public: +	LLPanelGroupBulk(const LLUUID& group_id); +	~LLPanelGroupBulk(); + +public:	 +	static void callbackClickSubmit(void* userdata) {} +	virtual void submit() = 0; + +public: +	virtual void clear(); +	virtual void update(); +	virtual void draw(); + +protected: +	virtual void updateGroupName(); +	virtual void updateGroupData(); + +public: +	// this callback is being used to add a user whose fullname isn't been loaded before invoking of addUsers(). +	virtual void addUserCallback(const LLUUID& id, const LLAvatarName& av_name); +	virtual void setCloseCallback(void (*close_callback)(void*), void* data); + +	virtual void addUsers(uuid_vec_t& agent_ids); + +public: +	LLPanelGroupBulkImpl* mImplementation; + +protected: +	bool mPendingGroupPropertiesUpdate; +	bool mPendingRoleDataUpdate; +	bool mPendingMemberDataUpdate; +}; + +#endif // LL_LLPANELGROUPBULK_H + diff --git a/indra/newview/llpanelgroupbulkban.cpp b/indra/newview/llpanelgroupbulkban.cpp new file mode 100644 index 0000000000..af1809b1f8 --- /dev/null +++ b/indra/newview/llpanelgroupbulkban.cpp @@ -0,0 +1,149 @@ +/**  +* @file llpanelgroupbulkban.cpp +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library 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 +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelgroupbulkban.h" +#include "llpanelgroupbulk.h" +#include "llpanelgroupbulkimpl.h" + +#include "llagent.h" +#include "llavatarnamecache.h" +#include "llfloateravatarpicker.h" +#include "llbutton.h" +#include "llcallingcard.h" +#include "llcombobox.h" +#include "llgroupactions.h" +#include "llgroupmgr.h" +#include "llnamelistctrl.h" +#include "llnotificationsutil.h" +#include "llscrolllistitem.h" +#include "llspinctrl.h" +#include "lltextbox.h" +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "lluictrlfactory.h" +#include "llviewerwindow.h" + + +LLPanelGroupBulkBan::LLPanelGroupBulkBan(const LLUUID& group_id) : LLPanelGroupBulk(group_id) +{ +	// Pass on construction of this panel to the control factory. +	buildFromFile( "panel_group_bulk_ban.xml"); +} + +BOOL LLPanelGroupBulkBan::postBuild() +{ +	BOOL recurse = TRUE; + +	mImplementation->mLoadingText = getString("loading"); +	mImplementation->mGroupName = getChild<LLTextBox>("group_name_text", recurse); +	mImplementation->mBulkAgentList = getChild<LLNameListCtrl>("banned_agent_list", recurse); +	if ( mImplementation->mBulkAgentList ) +	{ +		mImplementation->mBulkAgentList->setCommitOnSelectionChange(TRUE); +		mImplementation->mBulkAgentList->setCommitCallback(LLPanelGroupBulkImpl::callbackSelect, mImplementation); +	} + +	LLButton* button = getChild<LLButton>("add_button", recurse); +	if ( button ) +	{ +		// default to opening avatarpicker automatically +		// (*impl::callbackClickAdd)((void*)this); +		button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickAdd, this); +	} + +	mImplementation->mRemoveButton =  +		getChild<LLButton>("remove_button", recurse); +	if ( mImplementation->mRemoveButton ) +	{ +		mImplementation->mRemoveButton->setClickedCallback(LLPanelGroupBulkImpl::callbackClickRemove, mImplementation); +		mImplementation->mRemoveButton->setEnabled(FALSE); +	} + +	mImplementation->mOKButton =  +		getChild<LLButton>("ban_button", recurse); +	if ( mImplementation->mOKButton ) +	{ +		mImplementation->mOKButton->setClickedCallback(LLPanelGroupBulkBan::callbackClickSubmit, this); +		mImplementation->mOKButton->setEnabled(FALSE); +	} + +	button = getChild<LLButton>("cancel_button", recurse); +	if ( button ) +	{ +		button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickCancel, mImplementation); +	} + +	mImplementation->mTooManySelected = getString("ban_selection_too_large"); + +	update(); + +	// 	return (mImplementation->mRoleNames && +	// 		mImplementation->mBannedAgents && +	// 		mImplementation->mRemoveButton); + +	return (mImplementation->mBulkAgentList && +		mImplementation->mRemoveButton); +} + + +void LLPanelGroupBulkBan::callbackClickSubmit(void* userdata) +{ +	LLPanelGroupBulkBan* selfp = (LLPanelGroupBulkBan*)userdata; + +	if(selfp) +		selfp->submit(); +} + + +void LLPanelGroupBulkBan::submit() +{ +	std::vector<LLUUID> banned_agent_list;	 +	std::vector<LLScrollListItem*> agents = mImplementation->mBulkAgentList->getAllData(); +	std::vector<LLScrollListItem*>::iterator iter = agents.begin(); +	for(;iter != agents.end(); ++iter) +	{ +		LLScrollListItem* agent = *iter; +		banned_agent_list.push_back(agent->getUUID()); +	} + +	const S32 MAX_GROUP_BANS = 100; // Max invites per request. 100 to match server cap. +	if (banned_agent_list.size() > MAX_GROUP_BANS) +	{ +		// Fail! +		LLSD msg; +		msg["MESSAGE"] = mImplementation->mTooManySelected; +		LLNotificationsUtil::add("GenericAlert", msg); +		(*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData); +		return; +	} + +	LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mImplementation->mGroupID, LLGroupMgr::BAN_CREATE, banned_agent_list); + +	//then close +	(*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData); +} + diff --git a/indra/newview/llpanelgroupbulkban.h b/indra/newview/llpanelgroupbulkban.h new file mode 100644 index 0000000000..0684f365a0 --- /dev/null +++ b/indra/newview/llpanelgroupbulkban.h @@ -0,0 +1,47 @@ +/**  +* @file   llpanelgroupbulkban.h +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library 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 +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ + +#ifndef LL_LLPANELGROUPBULKBAN_H +#define LL_LLPANELGROUPBULKBAN_H + +#include "llpanel.h" +#include "lluuid.h" +#include "llpanelgroupbulk.h" + +class LLAvatarName; + +class LLPanelGroupBulkBan : public LLPanelGroupBulk +{ +public: +	LLPanelGroupBulkBan(const LLUUID& group_id); +	~LLPanelGroupBulkBan() {} + +	virtual BOOL postBuild(); + +	static void callbackClickSubmit(void* userdata); +	virtual void submit(); +}; + +#endif // LL_LLPANELGROUPBULKBAN_H diff --git a/indra/newview/llpanelgroupbulkimpl.h b/indra/newview/llpanelgroupbulkimpl.h new file mode 100644 index 0000000000..74da542eb8 --- /dev/null +++ b/indra/newview/llpanelgroupbulkimpl.h @@ -0,0 +1,87 @@ +/**  +* @file   llpanelgroupbulkimpl.h +* @brief  Header file for llpanelgroupbulkimpl +* @author Baker@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library 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 +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA +* $/LicenseInfo$ +*/ +#ifndef LL_LLPANELGROUPBULKIMPL_H +#define LL_LLPANELGROUPBULKIMPL_H + +#include "llpanel.h" +#include "lluuid.h" + +class LLAvatarName; +class LLNameListCtrl; +class LLTextBox; +class LLComboBox; + +class LLPanelGroupBulkImpl +{ +public: +	LLPanelGroupBulkImpl(const LLUUID& group_id); +	~LLPanelGroupBulkImpl(); + +	static void callbackClickAdd(void* userdata); +	static void callbackClickRemove(void* userdata); + +	static void callbackClickCancel(void* userdata); + +	static void callbackSelect(LLUICtrl* ctrl, void* userdata); +	static void callbackAddUsers(const uuid_vec_t& agent_ids, void* user_data); + +	static void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, void* user_data); + +	void handleRemove(); +	void handleSelection(); + +	void addUsers(const std::vector<std::string>& names, const uuid_vec_t& agent_ids); +	void setGroupName(std::string name); + + +public: +	LLUUID			mGroupID; + +	LLNameListCtrl*	mBulkAgentList; +	LLButton*		mOKButton; +	LLButton*		mRemoveButton; +	LLTextBox*		mGroupName; + +	std::string		mLoadingText; +	std::string		mTooManySelected; + +	void (*mCloseCallback)(void* data); +	void* mCloseCallbackUserData; +	boost::signals2::connection mAvatarNameCacheConnection; + +	// The following are for the LLPanelGroupInvite subclass only.   +	// These aren't needed for LLPanelGroupBulkBan, but if we have to add another  +	// group bulk floater for some reason, we'll have these objects too. +public: +	LLComboBox*		mRoleNames; +	std::string		mOwnerWarning; +	std::string		mAlreadyInGroup; +	bool			mConfirmedOwnerInvite; +}; + +#endif // LL_LLPANELGROUPBULKIMPL_H + diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index a9a3c686a6..43d94b36fc 100755 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -26,6 +26,8 @@  #include "llviewerprecompiledheaders.h"  #include "llpanelgroupinvite.h" +#include "llpanelgroupbulk.h" +#include "llpanelgroupbulkimpl.h"  #include "llagent.h"  #include "llavatarnamecache.h" @@ -45,203 +47,213 @@  #include "lluictrlfactory.h"  #include "llviewerwindow.h" -class LLPanelGroupInvite::impl + +bool invite_owner_callback(LLHandle<LLPanel> panel_handle, const LLSD& notification, const LLSD& response)  { -public: -	impl(const LLUUID& group_id); -	~impl(); - -	void addUsers(const std::vector<std::string>& names, -				  const uuid_vec_t& agent_ids); -	void submitInvitations(); -	void addRoleNames(LLGroupMgrGroupData* gdatap); -	void handleRemove(); -	void handleSelection(); - -	static void callbackClickCancel(void* userdata); -	static void callbackClickOK(void* userdata); -	static void callbackClickAdd(void* userdata); -	static void callbackClickRemove(void* userdata); -	static void callbackSelect(LLUICtrl* ctrl, void* userdata); -	static void callbackAddUsers(const uuid_vec_t& agent_ids, -								 void* user_data); -	 -	static void onAvatarNameCache(const LLUUID& agent_id, -											 const LLAvatarName& av_name, -											 void* user_data); - -	bool inviteOwnerCallback(const LLSD& notification, const LLSD& response); - -public: -	LLUUID mGroupID; - -	std::string		mLoadingText; -	LLNameListCtrl	*mInvitees; -	LLComboBox      *mRoleNames; -	LLButton		*mOKButton; - 	LLButton		*mRemoveButton; -	LLTextBox		*mGroupName; -	std::string		mOwnerWarning; -	std::string		mAlreadyInGroup; -	std::string		mTooManySelected; -	bool		mConfirmedOwnerInvite; -	std::set<LLUUID>	mInviteeIDs; - -	void (*mCloseCallback)(void* data); - -	void* mCloseCallbackUserData; - -	boost::signals2::connection mAvatarNameCacheConnection; -}; - - -LLPanelGroupInvite::impl::impl(const LLUUID& group_id): -	mGroupID( group_id ), -	mLoadingText (), -	mInvitees ( NULL ), -	mRoleNames( NULL ), -	mOKButton ( NULL ), -	mRemoveButton( NULL ), -	mGroupName( NULL ), -	mConfirmedOwnerInvite( false ), -	mCloseCallback( NULL ), -	mCloseCallbackUserData( NULL ), -	mAvatarNameCacheConnection() +	LLPanelGroupInvite* panel = dynamic_cast<LLPanelGroupInvite*>(panel_handle.get()); +	if(!panel) +		return false; + +	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); +	switch(option) +	{ +	case 0: +		// user confirmed that they really want a new group owner +		panel->mImplementation->mConfirmedOwnerInvite = true; +		panel->submit(); +		break; +	case 1: +		// fall through +	default: +		break; +	} + 	return false; +} + + +LLPanelGroupInvite::LLPanelGroupInvite(const LLUUID& group_id) : LLPanelGroupBulk(group_id)  { +	// Pass on construction of this panel to the control factory. +	buildFromFile( "panel_group_invite.xml");  } -LLPanelGroupInvite::impl::~impl() +void LLPanelGroupInvite::clear()  { -	if (mAvatarNameCacheConnection.connected()) +	LLPanelGroupBulk::clear(); + +	if(mImplementation->mRoleNames)  	{ -		mAvatarNameCacheConnection.disconnect(); +		mImplementation->mRoleNames->clear(); +		mImplementation->mRoleNames->removeall(); +		mImplementation->mRoleNames->setCurrentByID(LLUUID::null);  	}  } -const S32 MAX_GROUP_INVITES = 100; // Max invites per request. 100 to match server cap. +void LLPanelGroupInvite::update() +{ +	LLPanelGroupBulk::update(); -void LLPanelGroupInvite::impl::addUsers(const std::vector<std::string>& names, -										const uuid_vec_t& agent_ids) +	if(mImplementation->mRoleNames) +	{ +		LLUUID store_selected_role = mImplementation->mRoleNames->getCurrentID(); +		mImplementation->mRoleNames->clear(); +		mImplementation->mRoleNames->removeall(); +		mImplementation->mRoleNames->setCurrentByID(LLUUID::null); + +		if(!mPendingRoleDataUpdate && !mPendingMemberDataUpdate) +		{ +			////////////////////////////////////////////////////////////////////////// +			// Add role names +			 addRoleNames(); +			//////////////////////////////////////////////////////////////////////////// +			mImplementation->mRoleNames->setCurrentByID(store_selected_role); +		} +		else +		{ +			mImplementation->mRoleNames->add(mImplementation->mLoadingText, LLUUID::null, ADD_BOTTOM); +		} +		 +	} +} + +BOOL LLPanelGroupInvite::postBuild()  { -	std::string name; -	LLUUID id; +	BOOL recurse = TRUE; -	if (names.size() + mInviteeIDs.size() > MAX_GROUP_INVITES) +	mImplementation->mLoadingText = getString("loading"); +	mImplementation->mRoleNames = getChild<LLComboBox>("role_name", +															   recurse); +	mImplementation->mGroupName = getChild<LLTextBox>("group_name_text", recurse); +	mImplementation->mBulkAgentList = getChild<LLNameListCtrl>("invitee_list", recurse); +	if ( mImplementation->mBulkAgentList )  	{ -		// Fail! Show a warning and don't add any names. -		LLSD msg; -		msg["MESSAGE"] = mTooManySelected; -		LLNotificationsUtil::add("GenericAlert", msg); -		return; +		mImplementation->mBulkAgentList->setCommitOnSelectionChange(TRUE); +		mImplementation->mBulkAgentList->setCommitCallback(LLPanelGroupBulkImpl::callbackSelect, mImplementation);  	} -	for (S32 i = 0; i < (S32)names.size(); i++) +	LLButton* button = getChild<LLButton>("add_button", recurse); +	if ( button )  	{ -		name = names[i]; -		id = agent_ids[i]; +		// default to opening avatarpicker automatically +		// (*impl::callbackClickAdd)((void*)this); +		button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickAdd, this); +	} -		// Make sure this agent isn't already in the list. -		if (mInviteeIDs.find(id) != mInviteeIDs.end()) -		{ -			continue; -		} +	mImplementation->mRemoveButton =  +			getChild<LLButton>("remove_button", recurse); +	if ( mImplementation->mRemoveButton ) +	{ +		mImplementation->mRemoveButton->setClickedCallback(LLPanelGroupBulkImpl::callbackClickRemove, mImplementation); +		mImplementation->mRemoveButton->setEnabled(FALSE); +	} -		//add the name to the names list -		LLSD row; -		row["id"] = id; -		row["columns"][0]["value"] = name; +	mImplementation->mOKButton = getChild<LLButton>("invite_button", recurse); +	if ( mImplementation->mOKButton ) + 	{ +		mImplementation->mOKButton->setClickedCallback(LLPanelGroupInvite::callbackClickSubmit, this); +		mImplementation->mOKButton->setEnabled(FALSE); + 	} -		mInvitees->addElement(row); -		mInviteeIDs.insert(id); +	button = getChild<LLButton>("cancel_button", recurse); +	if ( button ) +	{ +		button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickCancel, mImplementation);  	} + +	mImplementation->mOwnerWarning = getString("confirm_invite_owner_str"); +	mImplementation->mAlreadyInGroup = getString("already_in_group"); +	mImplementation->mTooManySelected = getString("invite_selection_too_large"); + +	update(); +	 +	return (mImplementation->mRoleNames && +			mImplementation->mBulkAgentList && +			mImplementation->mRemoveButton); +} + +void LLPanelGroupInvite::callbackClickSubmit(void* userdata) +{ +	LLPanelGroupInvite* selfp = (LLPanelGroupInvite*)userdata; + +	if(selfp) +		selfp->submit();  } -void LLPanelGroupInvite::impl::submitInvitations() +void LLPanelGroupInvite::submit()  {  	std::map<LLUUID, LLUUID> role_member_pairs; -	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); +	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID);  	// Default to everyone role.  	LLUUID role_id = LLUUID::null; -	if (mRoleNames) +	if (mImplementation->mRoleNames)  	{ -		role_id = mRoleNames->getCurrentID(); -		 +		role_id = mImplementation->mRoleNames->getCurrentID(); + +		//LLUUID t_ownerUUID = gdatap->mOwnerRole; +		//bool t_confirmInvite = mImplementation->mConfirmedOwnerInvite; +  		// owner role: display confirmation and wait for callback -		if ((role_id == gdatap->mOwnerRole) && (!mConfirmedOwnerInvite)) +		if ((role_id == gdatap->mOwnerRole) && (!mImplementation->mConfirmedOwnerInvite))  		{  			LLSD args; -			args["MESSAGE"] = mOwnerWarning; -			LLNotificationsUtil::add("GenericAlertYesCancel", args, LLSD(), boost::bind(&LLPanelGroupInvite::impl::inviteOwnerCallback, this, _1, _2)); +			args["MESSAGE"] = mImplementation->mOwnerWarning; +			LLNotificationsUtil::add(	"GenericAlertYesCancel",  +										args,  +										LLSD(),  +										boost::bind(invite_owner_callback,  +													this->getHandle(),  +													_1, _2));  			return; // we'll be called again if user confirms  		}  	}  	bool already_in_group = false;  	//loop over the users -	std::vector<LLScrollListItem*> items = mInvitees->getAllData(); +	std::vector<LLScrollListItem*> items = mImplementation->mBulkAgentList->getAllData();  	for (std::vector<LLScrollListItem*>::iterator iter = items.begin(); -		 iter != items.end(); ++iter) +		iter != items.end(); ++iter)  	{  		LLScrollListItem* item = *iter; -		if(LLGroupActions::isAvatarMemberOfGroup(mGroupID, item->getUUID())) +		if(LLGroupActions::isAvatarMemberOfGroup(mImplementation->mGroupID, item->getUUID()))  		{  			already_in_group = true;  			continue;  		}  		role_member_pairs[item->getUUID()] = role_id;  	} -	 + +	const S32 MAX_GROUP_INVITES = 100; // Max invites per request. 100 to match server cap.  	if (role_member_pairs.size() > MAX_GROUP_INVITES)  	{  		// Fail!  		LLSD msg; -		msg["MESSAGE"] = mTooManySelected; +		msg["MESSAGE"] = mImplementation->mTooManySelected;  		LLNotificationsUtil::add("GenericAlert", msg); -		(*mCloseCallback)(mCloseCallbackUserData); +		(*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData);  		return;  	} -	LLGroupMgr::getInstance()->sendGroupMemberInvites(mGroupID, role_member_pairs); -	 +	LLGroupMgr::getInstance()->sendGroupMemberInvites(mImplementation->mGroupID, role_member_pairs); +  	if(already_in_group)  	{  		LLSD msg; -		msg["MESSAGE"] = mAlreadyInGroup; +		msg["MESSAGE"] = mImplementation->mAlreadyInGroup;  		LLNotificationsUtil::add("GenericAlert", msg);  	}  	//then close -	(*mCloseCallback)(mCloseCallbackUserData); +	(*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData);  } -bool LLPanelGroupInvite::impl::inviteOwnerCallback(const LLSD& notification, const LLSD& response) +void LLPanelGroupInvite::addRoleNames()  { -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - -	switch(option) -	{ -	case 0: -		// user confirmed that they really want a new group owner -		mConfirmedOwnerInvite = true; -		submitInvitations(); -		break; -	case 1: -		// fall through -	default: -		break; -	} -	return false; -} - +	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID); - -void LLPanelGroupInvite::impl::addRoleNames(LLGroupMgrGroupData* gdatap) -{ -	LLGroupMgrGroupData::member_list_t::iterator agent_iter = -		gdatap->mMembers.find(gAgent.getID()); +	LLGroupMgrGroupData::member_list_t::iterator agent_iter = gdatap->mMembers.find(gAgent.getID());  	//get the member data for the agent if it exists  	if ( agent_iter != gdatap->mMembers.end() ) @@ -251,7 +263,7 @@ void LLPanelGroupInvite::impl::addRoleNames(LLGroupMgrGroupData* gdatap)  		//loop over the agent's roles in the group  		//then add those roles to the list of roles that the agent  		//can invite people to be -		if ( member_data && mRoleNames) +		if ( member_data && mImplementation->mRoleNames)  		{  			//if the user is the owner then we add  			//all of the roles in the group @@ -261,10 +273,10 @@ void LLPanelGroupInvite::impl::addRoleNames(LLGroupMgrGroupData* gdatap)  			//we add every role the user is in  			//else we just add to everyone  			bool is_owner   = member_data->isInRole(gdatap->mOwnerRole); -			bool can_assign_any = gAgent.hasPowerInGroup(mGroupID, -												 GP_ROLE_ASSIGN_MEMBER); -			bool can_assign_limited = gAgent.hasPowerInGroup(mGroupID, -												 GP_ROLE_ASSIGN_MEMBER_LIMITED); +			bool can_assign_any = gAgent.hasPowerInGroup(mImplementation->mGroupID, +				GP_ROLE_ASSIGN_MEMBER); +			bool can_assign_limited = gAgent.hasPowerInGroup(mImplementation->mGroupID, +				GP_ROLE_ASSIGN_MEMBER_LIMITED);  			LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.begin();  			LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end(); @@ -279,401 +291,18 @@ void LLPanelGroupInvite::impl::addRoleNames(LLGroupMgrGroupData* gdatap)  					// Owners can add any role.  					if ( is_owner   						// Even 'can_assign_any' can't add owner role. -						 || (can_assign_any && role_id != gdatap->mOwnerRole) +						|| (can_assign_any && role_id != gdatap->mOwnerRole)  						// Add all roles user is in -						 || (can_assign_limited && member_data->isInRole(role_id)) +						|| (can_assign_limited && member_data->isInRole(role_id))  						// Everyone role. -						 || role_id == LLUUID::null ) +						|| role_id == LLUUID::null )  					{ -							mRoleNames->add(rd.mRoleName, -											role_id, -											ADD_BOTTOM); +						mImplementation->mRoleNames->add(rd.mRoleName, +							role_id, +							ADD_BOTTOM);  					}  				}  			}  		}//end if member data is not null  	}//end if agent is in the group  } - -//static -void LLPanelGroupInvite::impl::callbackClickAdd(void* userdata) -{ -	LLPanelGroupInvite* panelp = (LLPanelGroupInvite*) userdata; - -	if ( panelp ) -	{ -		//Right now this is hard coded with some knowledge that it is part -		//of a floater since the avatar picker needs to be added as a dependent -		//floater to the parent floater. -		//Soon the avatar picker will be embedded into this panel -		//instead of being it's own separate floater.  But that is next week. -		//This will do for now. -jwolk May 10, 2006 -        LLView * button = panelp->findChild<LLButton>("add_button"); -        LLFloater * root_floater = gFloaterView->getParentFloater(panelp); -		LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( -			boost::bind(impl::callbackAddUsers, _1, panelp->mImplementation), TRUE, FALSE, FALSE, root_floater->getName(), button); -		if (picker) -		{ -			root_floater->addDependentFloater(picker); -		} -	} -} - -//static -void LLPanelGroupInvite::impl::callbackClickRemove(void* userdata) -{ -	impl* selfp = (impl*) userdata; - -	if ( selfp ) selfp->handleRemove(); -} - -void LLPanelGroupInvite::impl::handleRemove() -{ -	// Check if there is anything selected. -	std::vector<LLScrollListItem*> selection =  -			mInvitees->getAllSelected(); -	if (selection.empty()) return; - -	std::vector<LLScrollListItem*>::iterator iter; -	for(iter = selection.begin(); iter != selection.end(); ++iter) -	{ -		mInviteeIDs.erase( (*iter)->getUUID() ); -	} - -	// Remove all selected invitees. -	mInvitees->deleteSelectedItems(); -	mRemoveButton->setEnabled(FALSE); -} - -// static -void LLPanelGroupInvite::impl::callbackSelect( -									LLUICtrl* ctrl, void* userdata) -{ -	impl* selfp = (impl*) userdata; -	if ( selfp ) selfp->handleSelection(); -} - -void LLPanelGroupInvite::impl::handleSelection() -{ -	// Check if there is anything selected. -	std::vector<LLScrollListItem*> selection =  -			mInvitees->getAllSelected(); -	if (selection.empty()) -	{ -		mRemoveButton->setEnabled(FALSE); -	} -	else -	{ -		mRemoveButton->setEnabled(TRUE); -	} -} - -void LLPanelGroupInvite::impl::callbackClickCancel(void* userdata) -{ -	impl* selfp = (impl*) userdata; - -	if ( selfp )  -	{ -		(*(selfp->mCloseCallback))(selfp->mCloseCallbackUserData); -	} -} - -void LLPanelGroupInvite::impl::callbackClickOK(void* userdata) -{ -	impl* selfp = (impl*) userdata; - -	if ( selfp ) selfp->submitInvitations(); -} - - - -//static -void LLPanelGroupInvite::impl::callbackAddUsers(const uuid_vec_t& agent_ids, void* user_data) -{	 -	std::vector<std::string> names; -	for (S32 i = 0; i < (S32)agent_ids.size(); i++) -	{ -		LLAvatarName av_name; -		if (LLAvatarNameCache::get(agent_ids[i], &av_name)) -		{ -			LLPanelGroupInvite::impl::onAvatarNameCache(agent_ids[i], av_name, user_data); -		} -		else  -		{ -			impl* selfp = (impl*) user_data; -			if (selfp) -			{ -				if (selfp->mAvatarNameCacheConnection.connected()) -				{ -					selfp->mAvatarNameCacheConnection.disconnect(); -				} -				// *TODO : Add a callback per avatar name being fetched. -				selfp->mAvatarNameCacheConnection = LLAvatarNameCache::get(agent_ids[i],boost::bind(&LLPanelGroupInvite::impl::onAvatarNameCache, _1, _2, user_data)); -			} -		} -	}	 -	 -} - -void LLPanelGroupInvite::impl::onAvatarNameCache(const LLUUID& agent_id, -											 const LLAvatarName& av_name, -											 void* user_data) -{ -	impl* selfp = (impl*) user_data; - -	if (selfp) -	{ -		if (selfp->mAvatarNameCacheConnection.connected()) -		{ -			selfp->mAvatarNameCacheConnection.disconnect(); -		} -		std::vector<std::string> names; -		uuid_vec_t agent_ids; -		agent_ids.push_back(agent_id); -		names.push_back(av_name.getCompleteName()); -		 -		selfp->addUsers(names, agent_ids); -	} -} - - -LLPanelGroupInvite::LLPanelGroupInvite(const LLUUID& group_id) -	: LLPanel(), -	  mImplementation(new impl(group_id)), -	  mPendingUpdate(FALSE) -{ -	// Pass on construction of this panel to the control factory. -	buildFromFile( "panel_group_invite.xml"); -} - -LLPanelGroupInvite::~LLPanelGroupInvite() -{ -	delete mImplementation; -} - -void LLPanelGroupInvite::setCloseCallback(void (*close_callback)(void*), -										  void* data) -{ -	mImplementation->mCloseCallback         = close_callback; -	mImplementation->mCloseCallbackUserData = data; -} - -void LLPanelGroupInvite::clear() -{ -	mStoreSelected = LLUUID::null; -	mImplementation->mInvitees->deleteAllItems(); -	mImplementation->mRoleNames->clear(); -	mImplementation->mRoleNames->removeall(); -	mImplementation->mOKButton->setEnabled(FALSE); -	mImplementation->mInviteeIDs.clear(); -} - -void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids) -{ -	std::vector<std::string> names; -	for (S32 i = 0; i < (S32)agent_ids.size(); i++) -	{ -		std::string fullname; -		LLUUID agent_id = agent_ids[i]; -		LLViewerObject* dest = gObjectList.findObject(agent_id); -		if(dest && dest->isAvatar()) -		{ -			LLNameValue* nvfirst = dest->getNVPair("FirstName"); -			LLNameValue* nvlast = dest->getNVPair("LastName"); -			if(nvfirst && nvlast) -			{ -				fullname = LLCacheName::buildFullName( -					nvfirst->getString(), nvlast->getString()); - -			} -			if (!fullname.empty()) -			{ -				names.push_back(fullname); -			}  -			else  -			{ -				llwarns << "llPanelGroupInvite: Selected avatar has no name: " << dest->getID() << llendl; -				names.push_back("(Unknown)"); -			} -		} -		else -		{ -			//looks like user try to invite offline friend -			//for offline avatar_id gObjectList.findObject() will return null -			//so we need to do this additional search in avatar tracker, see EXT-4732 -			if (LLAvatarTracker::instance().isBuddy(agent_id)) -			{ -				LLAvatarName av_name; -				if (!LLAvatarNameCache::get(agent_id, &av_name)) -				{ -					// actually it should happen, just in case -					//LLAvatarNameCache::get(LLUUID(agent_id), boost::bind(&LLPanelGroupInvite::addUserCallback, this, _1, _2)); -					// for this special case! -					//when there is no cached name we should remove resident from agent_ids list to avoid breaking of sequence -					// removed id will be added in callback -					agent_ids.erase(agent_ids.begin() + i); -				} -				else -				{ -					names.push_back(av_name.getAccountName()); -				} -			} -		} -	} -	mImplementation->addUsers(names, agent_ids); -} - -void LLPanelGroupInvite::addUserCallback(const LLUUID& id, const LLAvatarName& av_name) -{ -	std::vector<std::string> names; -	uuid_vec_t agent_ids; -	agent_ids.push_back(id); -	names.push_back(av_name.getAccountName()); - -	mImplementation->addUsers(names, agent_ids); -} - -void LLPanelGroupInvite::draw() -{ -	LLPanel::draw(); -	if (mPendingUpdate) -	{ -		updateLists(); -	} -} -  -void LLPanelGroupInvite::update() -{ -	mPendingUpdate = FALSE; -	if (mImplementation->mGroupName)  -	{ -		mImplementation->mGroupName->setText(mImplementation->mLoadingText); -	} -	if ( mImplementation->mRoleNames )  -	{ -		mStoreSelected = mImplementation->mRoleNames->getCurrentID(); -		mImplementation->mRoleNames->clear(); -		mImplementation->mRoleNames->removeall(); -		mImplementation->mRoleNames->add(mImplementation->mLoadingText, LLUUID::null, ADD_BOTTOM); -		mImplementation->mRoleNames->setCurrentByID(LLUUID::null); -	} - -	updateLists(); -} - -void LLPanelGroupInvite::updateLists() -{ -	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID); -	bool waiting = false; - -	if (gdatap)  -	{ -		if (gdatap->isGroupPropertiesDataComplete())  -		{ -			if (mImplementation->mGroupName)  -			{ -				mImplementation->mGroupName->setText(gdatap->mName); -			} -		}  -		else  -		{ -			waiting = true; -		} -		if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete())  -		{ -			if ( mImplementation->mRoleNames ) -			{ -				mImplementation->mRoleNames->clear(); -				mImplementation->mRoleNames->removeall(); - -				//add the role names and select the everybody role by default -				mImplementation->addRoleNames(gdatap); -				mImplementation->mRoleNames->setCurrentByID(mStoreSelected); -			} -		}  -		else  -		{ -			waiting = true; -		} -	}  -	else  -	{ -		waiting = true; -	} - -	if (waiting)  -	{ -		if (!mPendingUpdate)  -		{ -			LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID); -			LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID); -			LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID); -		} -		mPendingUpdate = TRUE; -	}  -	else -	{ -		mPendingUpdate = FALSE; -		if (mImplementation->mOKButton && mImplementation->mRoleNames->getItemCount())  -		{ -			mImplementation->mOKButton->setEnabled(TRUE); -		} -	} -} - -BOOL LLPanelGroupInvite::postBuild() -{ -	BOOL recurse = TRUE; - -	mImplementation->mLoadingText = getString("loading"); -	mImplementation->mRoleNames = getChild<LLComboBox>("role_name", -															   recurse); -	mImplementation->mGroupName = getChild<LLTextBox>("group_name_text", recurse); -	mImplementation->mInvitees =  -		getChild<LLNameListCtrl>("invitee_list", recurse); -	if ( mImplementation->mInvitees ) -	{ -		mImplementation->mInvitees->setCommitOnSelectionChange(TRUE); -		mImplementation->mInvitees->setCommitCallback(impl::callbackSelect, mImplementation); -	} - -	LLButton* button = getChild<LLButton>("add_button", recurse); -	if ( button ) -	{ -		// default to opening avatarpicker automatically -		// (*impl::callbackClickAdd)((void*)this); -		button->setClickedCallback(impl::callbackClickAdd, this); -	} - -	mImplementation->mRemoveButton =  -			getChild<LLButton>("remove_button", recurse); -	if ( mImplementation->mRemoveButton ) -	{ -		mImplementation->mRemoveButton->setClickedCallback(impl::callbackClickRemove, mImplementation); -		mImplementation->mRemoveButton->setEnabled(FALSE); -	} - -	mImplementation->mOKButton =  -		getChild<LLButton>("ok_button", recurse); -	if ( mImplementation->mOKButton ) - 	{ -		mImplementation->mOKButton->setClickedCallback(impl::callbackClickOK, mImplementation); -		mImplementation->mOKButton->setEnabled(FALSE); - 	} - -	button = getChild<LLButton>("cancel_button", recurse); -	if ( button ) -	{ -		button->setClickedCallback(impl::callbackClickCancel, mImplementation); -	} - -	mImplementation->mOwnerWarning = getString("confirm_invite_owner_str"); -	mImplementation->mAlreadyInGroup = getString("already_in_group"); -	mImplementation->mTooManySelected = getString("invite_selection_too_large"); - -	update(); -	 -	return (mImplementation->mRoleNames && -			mImplementation->mInvitees && -			mImplementation->mRemoveButton); -} diff --git a/indra/newview/llpanelgroupinvite.h b/indra/newview/llpanelgroupinvite.h index 9f7b5ae9be..b87a5883b8 100755 --- a/indra/newview/llpanelgroupinvite.h +++ b/indra/newview/llpanelgroupinvite.h @@ -27,36 +27,27 @@  #define LL_LLPANELGROUPINVITE_H  #include "llpanel.h" +#include "llpanelgroupbulk.h"  #include "lluuid.h"  class LLAvatarName; -class LLPanelGroupInvite -: public LLPanel +class LLPanelGroupInvite : public LLPanelGroupBulk  {  public:  	LLPanelGroupInvite(const LLUUID& group_id); -	~LLPanelGroupInvite(); +	~LLPanelGroupInvite() {}; -	void addUsers(uuid_vec_t& agent_ids); -	/** -	 * this callback is being used to add a user whose fullname isn't been loaded before invoking of addUsers(). -	 */   -	void addUserCallback(const LLUUID& id, const LLAvatarName& av_name); -	void clear(); -	void update(); +	virtual void clear(); +	virtual void update(); -	void setCloseCallback(void (*close_callback)(void*), void* data); - -	virtual void draw();  	virtual BOOL postBuild(); -protected: -	class impl; -	impl* mImplementation; -	BOOL mPendingUpdate; -	LLUUID mStoreSelected; -	void updateLists(); +	static void callbackClickSubmit(void* userdata); +	virtual void submit(); + +private: +	void addRoleNames();  };  #endif diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index fdcd1f5ebb..01baedefb7 100755 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -32,6 +32,7 @@  #include "llavatarnamecache.h"  #include "llbutton.h"  #include "llfiltereditor.h" +#include "llfloatergroupbulkban.h"  #include "llfloatergroupinvite.h"  #include "llavataractions.h"  #include "lliconctrl.h" @@ -109,8 +110,10 @@ bool agentCanAddToRole(const LLUUID& group_id,  	return false;  } -// static +// LLPanelGroupRoles ///////////////////////////////////////////////////// + +// static  LLPanelGroupRoles::LLPanelGroupRoles()  :	LLPanelGroupTab(),  	mCurrentTab(NULL), @@ -297,7 +300,6 @@ bool LLPanelGroupRoles::onModalClose(const LLSD& notification, const LLSD& respo  	return false;  } -  bool LLPanelGroupRoles::apply(std::string& mesg)  {  	// Pass this along to the currently visible sub tab. @@ -334,7 +336,6 @@ void LLPanelGroupRoles::update(LLGroupChange gc)  {  	if (mGroupID.isNull()) return; -	  	LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();  	if (panelp)  	{ @@ -351,39 +352,33 @@ void LLPanelGroupRoles::activate()  {  	// Start requesting member and role data if needed.  	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); -	//if (!gdatap || mFirstUse) +	if (!gdatap || !gdatap->isMemberDataComplete() )  	{ -		// Check member data. -		 -		if (!gdatap || !gdatap->isMemberDataComplete() ) -		{ -			LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); -		} - -		// Check role data. -		if (!gdatap || !gdatap->isRoleDataComplete() ) -		{ -			// Mildly hackish - clear all pending changes -			cancel(); +		LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); +	} -			LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID); -		} +	if (!gdatap || !gdatap->isRoleDataComplete() ) +	{ +		// Mildly hackish - clear all pending changes +		cancel(); -		// Check role-member mapping data. -		if (!gdatap || !gdatap->isRoleMemberDataComplete() ) -		{ -			LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID); -		} +		LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID); +	} -		// Need this to get base group member powers -		if (!gdatap || !gdatap->isGroupPropertiesDataComplete() ) -		{ -			LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID); -		} +	// Check role-member mapping data. +	if (!gdatap || !gdatap->isRoleMemberDataComplete() ) +	{ +		LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID); +	} -		mFirstUse = FALSE; +	// Need this to get base group member powers +	if (!gdatap || !gdatap->isGroupPropertiesDataComplete() ) +	{ +		LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mGroupID);  	} +	mFirstUse = FALSE; +  	LLPanelGroupTab* panelp = (LLPanelGroupTab*) mSubTabContainer->getCurrentPanel();  	if (panelp) panelp->activate();  } @@ -412,10 +407,32 @@ BOOL LLPanelGroupRoles::hasModal()  	return panelp->hasModal();  } +void LLPanelGroupRoles::setGroupID(const LLUUID& id) +{ +	LLPanelGroupTab::setGroupID(id); + +	LLPanelGroupMembersSubTab* group_members_tab = findChild<LLPanelGroupMembersSubTab>("members_sub_tab"); +	LLPanelGroupRolesSubTab*  group_roles_tab = findChild<LLPanelGroupRolesSubTab>("roles_sub_tab"); +	LLPanelGroupActionsSubTab* group_actions_tab = findChild<LLPanelGroupActionsSubTab>("actions_sub_tab"); +	LLPanelGroupBanListSubTab* group_ban_tab = findChild<LLPanelGroupBanListSubTab>("banlist_sub_tab"); + +	if(group_members_tab) group_members_tab->setGroupID(id); +	if(group_roles_tab) group_roles_tab->setGroupID(id); +	if(group_actions_tab) group_actions_tab->setGroupID(id); +	if(group_ban_tab) group_ban_tab->setGroupID(id); + +	LLButton* button = getChild<LLButton>("member_invite"); +	if ( button ) +		button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE)); + +	if(mSubTabContainer) +		mSubTabContainer->selectTab(0); + +	activate(); +} + -//////////////////////////// -// LLPanelGroupSubTab -//////////////////////////// +// LLPanelGroupSubTab ////////////////////////////////////////////////////  LLPanelGroupSubTab::LLPanelGroupSubTab()  :	LLPanelGroupTab(),  	mHeader(NULL), @@ -728,11 +745,8 @@ void LLPanelGroupSubTab::setFooterEnabled(BOOL enable)  	}  } -//////////////////////////// -// LLPanelGroupMembersSubTab -//////////////////////////// - +// LLPanelGroupMembersSubTab /////////////////////////////////////////////  static LLRegisterPanelClassWrapper<LLPanelGroupMembersSubTab> t_panel_group_members_subtab("panel_group_members_subtab");  LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab() @@ -810,6 +824,13 @@ BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root)  		mEjectBtn->setEnabled(FALSE);  	} +	mBanBtn = parent->getChild<LLButton>("member_ban", recurse); +	if(mBanBtn) +	{ +		mBanBtn->setClickedCallback(onBanMember, this); +		mBanBtn->setEnabled(FALSE); +	} +  	return TRUE;  } @@ -823,34 +844,6 @@ void LLPanelGroupMembersSubTab::setGroupID(const LLUUID& id)  	LLPanelGroupSubTab::setGroupID(id);  } -void LLPanelGroupRolesSubTab::setGroupID(const LLUUID& id) -{ -	if(mRolesList) mRolesList->deleteAllItems(); -	if(mAssignedMembersList) mAssignedMembersList->deleteAllItems(); -	if(mAllowedActionsList) mAllowedActionsList->deleteAllItems(); - -	if(mRoleName) mRoleName->clear(); -	if(mRoleDescription) mRoleDescription->clear(); -	if(mRoleTitle) mRoleTitle->clear(); - -	mHasRoleChange = FALSE; - -	setFooterEnabled(FALSE); - -	LLPanelGroupSubTab::setGroupID(id); -} -void LLPanelGroupActionsSubTab::setGroupID(const LLUUID& id) -{ -	if(mActionList) mActionList->deleteAllItems(); -	if(mActionRoles) mActionRoles->deleteAllItems(); -	if(mActionMembers) mActionMembers->deleteAllItems(); - -	if(mActionDescription) mActionDescription->clear(); - -	LLPanelGroupSubTab::setGroupID(id); -} - -  // static  void LLPanelGroupMembersSubTab::onMemberSelect(LLUICtrl* ctrl, void* user_data)  { @@ -916,8 +909,8 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()  	LLGroupMgrGroupData::role_list_t::iterator iter = gdatap->mRoles.begin();  	LLGroupMgrGroupData::role_list_t::iterator end  = gdatap->mRoles.end(); -	BOOL can_eject_members = gAgent.hasPowerInGroup(mGroupID, -													GP_MEMBER_EJECT); +	BOOL can_ban_members = gAgent.hasPowerInGroup(mGroupID,	GP_GROUP_BAN_ACCESS); +	BOOL can_eject_members = gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_EJECT);  	BOOL member_is_owner = FALSE;  	for( ; iter != end; ++iter) @@ -986,6 +979,7 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()  			if (role_id.notNull() && (count > 0))  			{  				can_eject_members = FALSE; +				can_ban_members = FALSE;  				if (role_id == gdatap->mOwnerRole)  				{  					member_is_owner = TRUE; @@ -1047,7 +1041,10 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()  	mAssignedRolesList->setEnabled(TRUE);  	if (gAgent.isGodlike()) +	{  		can_eject_members = TRUE; +		can_ban_members = TRUE; +	}  	if (!can_eject_members && !member_is_owner)  	{ @@ -1060,10 +1057,12 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()  			if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )  			{  				can_eject_members = TRUE; +				can_ban_members = TRUE;  			}  		}  	} +	mBanBtn->setEnabled(can_ban_members);  	mEjectBtn->setEnabled(can_eject_members);  } @@ -1101,61 +1100,26 @@ void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata)  }  void LLPanelGroupMembersSubTab::handleEjectMembers() -{	 +{ +	//send down an eject message +	uuid_vec_t selected_members; +  	std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();  	if (selection.empty()) return; -	 -	S32 selection_count = selection.size(); -	if (selection_count == 1) -	{ -		LLSD args; -		LLUUID selected_avatar = mMembersList->getValue().asUUID(); -		std::string fullname = LLSLURL("agent", selected_avatar, "inspect").getSLURLString(); -		args["AVATAR_NAME"] = fullname; -		LLSD payload; -		LLNotificationsUtil::add("EjectGroupMemberWarning", -								 args, -								 payload, -								 boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2)); -	} -	else -	{ -		LLSD args; -		args["COUNT"] = llformat("%d", selection_count); -		LLSD payload; -		LLNotificationsUtil::add("EjectGroupMembersWarning", -								 args, -								 payload, -								 boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2)); -	} -} -bool LLPanelGroupMembersSubTab::handleEjectCallback(const LLSD& notification, const LLSD& response) -{ -	S32 option = LLNotificationsUtil::getSelectedOption(notification, response); -	if (0 == option) // Eject button +	std::vector<LLScrollListItem*>::iterator itor; +	for (itor = selection.begin() ;  +		 itor != selection.end(); ++itor)  	{ -		//send down an eject message -		uuid_vec_t selected_members; -		 -		std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected(); -		if (selection.empty()) return false; -		 -		std::vector<LLScrollListItem*>::iterator itor; -		for (itor = selection.begin() ; -			 itor != selection.end(); ++itor) -		{ -			LLUUID member_id = (*itor)->getUUID(); -			selected_members.push_back( member_id ); -		} -		 -		mMembersList->deleteSelectedItems(); -		 -		sendEjectNotifications(mGroupID, selected_members); -		 -		LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID, selected_members); +		LLUUID member_id = (*itor)->getUUID(); +		selected_members.push_back( member_id );  	} -	return false; + +	mMembersList->deleteSelectedItems(); + +	sendEjectNotifications(mGroupID, selected_members); + +	LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID, selected_members);  }  void LLPanelGroupMembersSubTab::sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members) @@ -1188,7 +1152,6 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,  	BOOL   is_owner_role = ( gdatap->mOwnerRole == role_id );  	LLUUID member_id; -	  	std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();  	if (selection.empty()) @@ -1199,7 +1162,6 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,  	for (std::vector<LLScrollListItem*>::iterator itor = selection.begin() ;   		 itor != selection.end(); ++itor)  	{ -  		member_id = (*itor)->getUUID();  		//see if we requested a change for this member before @@ -1265,7 +1227,6 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,  					 FALSE);  } -  // static   void LLPanelGroupMembersSubTab::onRoleCheck(LLUICtrl* ctrl, void* user_data)  { @@ -1634,8 +1595,9 @@ void LLPanelGroupMembersSubTab::addMemberToList(LLGroupMemberData* data)  	item_params.columns.add().column("donated").value(donated.getString())  			.font.name("SANSSERIF_SMALL").style("NORMAL"); -	item_params.columns.add().column("online").value(data->getOnlineStatus()) -			.font.name("SANSSERIF_SMALL").style("NORMAL"); + 	item_params.columns.add().column("online").value(data->getOnlineStatus()) + 			.font.name("SANSSERIF_SMALL").style("NORMAL"); +	  	mMembersList->addNameItemRow(item_params);  	mHasMatch = TRUE; @@ -1687,13 +1649,12 @@ void LLPanelGroupMembersSubTab::updateMembers()  		return;  	} -	//cleanup list only for first iretation +	//cleanup list only for first iteration  	if(mMemberProgress == gdatap->mMembers.begin())  	{  		mMembersList->deleteAllItems();  	} -  	LLGroupMgrGroupData::member_list_t::iterator end = gdatap->mMembers.end();  	LLTimer update_time; @@ -1746,12 +1707,44 @@ void LLPanelGroupMembersSubTab::updateMembers()  	handleMemberSelect();  } +void LLPanelGroupMembersSubTab::onBanMember(void* user_data) +{ +	LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data); +	self->handleBanMember(); +} + +void LLPanelGroupMembersSubTab::handleBanMember() +{ +	LLGroupMgrGroupData* gdatap	= LLGroupMgr::getInstance()->getGroupData(mGroupID); +	if(!gdatap)  +	{ +		LL_WARNS("Groups") << "Unable to get group data for group " << mGroupID << LL_ENDL; +		return; +	} + +	std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected(); +	if(selection.empty()) +	{ +		return; +	} + +	uuid_vec_t ban_ids; +	std::vector<LLScrollListItem*>::iterator itor; +	for(itor = selection.begin(); itor != selection.end(); ++itor) +	{ +		LLUUID ban_id = (*itor)->getUUID(); +		ban_ids.push_back(ban_id); +		 +		LLGroupBanData ban_data; +		gdatap->createBanEntry(ban_id, ban_data); +	}	 +	LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mGroupID, LLGroupMgr::BAN_CREATE, ban_ids); +	handleEjectMembers(); +} -//////////////////////////// -// LLPanelGroupRolesSubTab -//////////////////////////// +// LLPanelGroupRolesSubTab ///////////////////////////////////////////////  static LLRegisterPanelClassWrapper<LLPanelGroupRolesSubTab> t_panel_group_roles_subtab("panel_group_roles_subtab");  LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab() @@ -1996,7 +1989,7 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc)  		mRolesList->sortByColumn(std::string("name"), TRUE);  		if ( (gdatap->mRoles.size() < (U32)MAX_ROLES) -			&& gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CREATE) ) +			&& gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS) )  		{  			mCreateRoleButton->setEnabled(TRUE);  		} @@ -2044,6 +2037,9 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc)  void LLPanelGroupRolesSubTab::onRoleSelect(LLUICtrl* ctrl, void* user_data)  {  	LLPanelGroupRolesSubTab* self = static_cast<LLPanelGroupRolesSubTab*>(user_data); +	if (!self)  +		return; +  	self->handleRoleSelect();  } @@ -2284,7 +2280,6 @@ bool LLPanelGroupRolesSubTab::addActionCB(const LLSD& notification, const LLSD&  	return false;  } -  // static  void LLPanelGroupRolesSubTab::onPropertiesKey(LLLineEditor* ctrl, void* user_data)  { @@ -2462,13 +2457,28 @@ void LLPanelGroupRolesSubTab::saveRoleChanges(bool select_saved_role)  		mHasRoleChange = FALSE;  	}  } -//////////////////////////// -// LLPanelGroupActionsSubTab -//////////////////////////// -static LLRegisterPanelClassWrapper<LLPanelGroupActionsSubTab> t_panel_group_actions_subtab("panel_group_actions_subtab"); +void LLPanelGroupRolesSubTab::setGroupID(const LLUUID& id) +{ +	if(mRolesList) mRolesList->deleteAllItems(); +	if(mAssignedMembersList) mAssignedMembersList->deleteAllItems(); +	if(mAllowedActionsList) mAllowedActionsList->deleteAllItems(); + +	if(mRoleName) mRoleName->clear(); +	if(mRoleDescription) mRoleDescription->clear(); +	if(mRoleTitle) mRoleTitle->clear(); + +	mHasRoleChange = FALSE; + +	setFooterEnabled(FALSE); + +	LLPanelGroupSubTab::setGroupID(id); +} +// LLPanelGroupActionsSubTab ///////////////////////////////////////////// +static LLRegisterPanelClassWrapper<LLPanelGroupActionsSubTab> t_panel_group_actions_subtab("panel_group_actions_subtab"); +  LLPanelGroupActionsSubTab::LLPanelGroupActionsSubTab()  : LLPanelGroupSubTab()  { @@ -2641,26 +2651,245 @@ void LLPanelGroupActionsSubTab::handleActionSelect()  	}  } -void LLPanelGroupRoles::setGroupID(const LLUUID& id) +void LLPanelGroupActionsSubTab::setGroupID(const LLUUID& id)  { -	LLPanelGroupTab::setGroupID(id); +	if(mActionList) mActionList->deleteAllItems(); +	if(mActionRoles) mActionRoles->deleteAllItems(); +	if(mActionMembers) mActionMembers->deleteAllItems(); + +	if(mActionDescription) mActionDescription->clear(); + +	LLPanelGroupSubTab::setGroupID(id); +} + + +// LLPanelGroupBanListSubTab ///////////////////////////////////////////// +static LLRegisterPanelClassWrapper<LLPanelGroupBanListSubTab> t_panel_group_ban_subtab("panel_group_banlist_subtab"); + +LLPanelGroupBanListSubTab::LLPanelGroupBanListSubTab() +	: LLPanelGroupSubTab(), +	  mBanList(NULL), +	  mCreateBanButton(NULL), +	  mDeleteBanButton(NULL) +{} + +BOOL LLPanelGroupBanListSubTab::postBuildSubTab(LLView* root) +{ +	LLPanelGroupSubTab::postBuildSubTab(root); + +	// Upcast parent so we can ask it for sibling controls. +	LLPanelGroupRoles* parent = (LLPanelGroupRoles*)root; + +	// Look recursively from the parent to find all our widgets. +	bool recurse = true; -	LLPanelGroupMembersSubTab* group_members_tab = findChild<LLPanelGroupMembersSubTab>("members_sub_tab"); -	LLPanelGroupRolesSubTab*  group_roles_tab = findChild<LLPanelGroupRolesSubTab>("roles_sub_tab"); -	LLPanelGroupActionsSubTab* group_actions_tab = findChild<LLPanelGroupActionsSubTab>("actions_sub_tab"); +	mHeader	= parent->getChild<LLPanel>("banlist_header", recurse); +	mFooter	= parent->getChild<LLPanel>("banlist_footer", recurse); +	 +	mBanList = parent->getChild<LLNameListCtrl>("ban_list", recurse); +	 +	mCreateBanButton		= parent->getChild<LLButton>("ban_create", recurse); +	mDeleteBanButton		= parent->getChild<LLButton>("ban_delete", recurse); +	mRefreshBanListButton	= parent->getChild<LLButton>("ban_refresh", recurse); -	if(group_members_tab) group_members_tab->setGroupID(id); -	if(group_roles_tab) group_roles_tab->setGroupID(id); -	if(group_actions_tab) group_actions_tab->setGroupID(id); +	if(!mBanList || !mCreateBanButton || !mDeleteBanButton || !mRefreshBanListButton) +		return FALSE; -	LLButton* button = getChild<LLButton>("member_invite"); -	if ( button ) -		button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE)); +	mBanList->setCommitOnSelectionChange(TRUE); +	mBanList->setCommitCallback(onBanEntrySelect, this); -	if(mSubTabContainer) -		mSubTabContainer->selectTab(0); +	mCreateBanButton->setClickedCallback(onCreateBanEntry, this); +	mCreateBanButton->setEnabled(TRUE); -	activate(); +	mDeleteBanButton->setClickedCallback(onDeleteBanEntry, this); +	mDeleteBanButton->setEnabled(FALSE); +	 +	mRefreshBanListButton->setClickedCallback(onRefreshBanList, this); +	mRefreshBanListButton->setEnabled(FALSE); + +	mBanList->setOnNameListCompleteCallback(boost::bind(&LLPanelGroupBanListSubTab::onBanListCompleted, this, _1)); +	 +	setFooterEnabled(FALSE); +	return TRUE;  } +void LLPanelGroupBanListSubTab::activate() +{ +	LLPanelGroupSubTab::activate(); + +	mBanList->deselectAllItems(); +	mDeleteBanButton->setEnabled(FALSE); + +	// BAKER: Should I really request everytime activate() is called? +	//		  Perhaps I should only do it on a force refresh, or if an action on the list happens... +	//		  Because it's not going to live-update the list anyway... You'd have to refresh if you  +	//		  wanted to see someone else's additions anyway... +	//		   +	LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID); + +	setFooterEnabled(FALSE); +	update(GC_ALL); +} + +void LLPanelGroupBanListSubTab::update(LLGroupChange gc) +{ +	populateBanList(); +} + +void LLPanelGroupBanListSubTab::draw() +{ +	LLPanelGroupSubTab::draw(); + +	// BAKER: Might be good to put it here instead of update, maybe.. See how often draw gets hit. +	//	populateBanList(); +} + +void LLPanelGroupBanListSubTab::onBanEntrySelect(LLUICtrl* ctrl, void* user_data) +{ +	LLPanelGroupBanListSubTab* self = static_cast<LLPanelGroupBanListSubTab*>(user_data); +	if (!self)  +		return; + +	self->handleBanEntrySelect(); +} + +void LLPanelGroupBanListSubTab::handleBanEntrySelect() +{ +	if (gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS)) +		mDeleteBanButton->setEnabled(TRUE); +} + +void LLPanelGroupBanListSubTab::onCreateBanEntry(void* user_data) +{ +	LLPanelGroupBanListSubTab* self = static_cast<LLPanelGroupBanListSubTab*>(user_data); +	if (!self)  +		return; + +	self->handleCreateBanEntry(); +} + +void LLPanelGroupBanListSubTab::handleCreateBanEntry() +{ +	LLFloaterGroupBulkBan::showForGroup(mGroupID); +	populateBanList(); +} + +void LLPanelGroupBanListSubTab::onDeleteBanEntry(void* user_data) +{ +	LLPanelGroupBanListSubTab* self = static_cast<LLPanelGroupBanListSubTab*>(user_data); +	if (!self)  +		return; + +	self->handleDeleteBanEntry(); +} + +void LLPanelGroupBanListSubTab::handleDeleteBanEntry() +{ +	LLGroupMgrGroupData* gdatap	= LLGroupMgr::getInstance()->getGroupData(mGroupID); +	if(!gdatap)  +	{ +		LL_WARNS("Groups") << "Unable to get group data for group " << mGroupID << LL_ENDL; +		return; +	} + +	std::vector<LLScrollListItem*> selection = mBanList->getAllSelected(); +	if(selection.empty()) +	{ +		return; +	} + +	bool can_ban_members = false; +	if (gAgent.isGodlike() || +		gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS)) +	{ +		can_ban_members	= true; +	} +	 +	// Owners can ban anyone in the group. +	LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find(gAgent.getID()); +	if (mi != gdatap->mMembers.end()) +	{ +		LLGroupMemberData* member_data = (*mi).second; +		if ( member_data && member_data->isInRole(gdatap->mOwnerRole) ) +		{ +			can_ban_members	= true; +		} +	} + +	std::vector<LLUUID> ban_ids; +	std::vector<LLScrollListItem*>::iterator itor; +	for(itor = selection.begin(); itor != selection.end(); ++itor) +	{ +		LLUUID ban_id = (*itor)->getUUID(); +		ban_ids.push_back(ban_id); +		 +		gdatap->removeBanEntry(ban_id); +		mBanList->removeNameItem(ban_id); +	 +		// Removing an item removes the selection, we shouldn't be able to click +		// the button anymore until we reselect another entry. +		mDeleteBanButton->setEnabled(FALSE); +	} +	 +	LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mGroupID, LLGroupMgr::BAN_DELETE, ban_ids); +} + +void LLPanelGroupBanListSubTab::onRefreshBanList(void* user_data) +{ +	LLPanelGroupBanListSubTab* self = static_cast<LLPanelGroupBanListSubTab*>(user_data); +	if (!self)  +		return; + +	self->handleRefreshBanList(); +} + +void LLPanelGroupBanListSubTab::handleRefreshBanList() +{ +	mRefreshBanListButton->setEnabled(FALSE); +	LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID); +} + +void LLPanelGroupBanListSubTab::onBanListCompleted(bool isComplete) +{ +	if(isComplete) +	{ +		mRefreshBanListButton->setEnabled(TRUE); +		populateBanList(); +	} +} + +void LLPanelGroupBanListSubTab::populateBanList() +{ +	LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); +	if(!gdatap)  +	{ +		LL_WARNS("Groups") << "Unable to get group data for group " << mGroupID << LL_ENDL; +		return; +	} + +	mBanList->deleteAllItems(); +	std::map<LLUUID,LLGroupBanData>::const_iterator entry = gdatap->mBanList.begin(); +	for(; entry != gdatap->mBanList.end(); entry++) +	{ +		LLNameListCtrl::NameItem ban_entry; +		ban_entry.value = entry->first; +		LLGroupBanData bd = entry->second; +		 +		ban_entry.columns.add().column("name").font.name("SANSSERIF_SMALL").style("NORMAL"); +		ban_entry.columns.add().column("ban_date").value(bd.mBanDate.toHTTPDateString("%Y/%m/%d")).font.name("SANSSERIF_SMALL").style("NORMAL"); + +		mBanList->addNameItemRow(ban_entry); +	} +	  +	mRefreshBanListButton->setEnabled(TRUE); +} + +void LLPanelGroupBanListSubTab::setGroupID(const LLUUID& id) +{ +	if(mBanList) +		mBanList->deleteAllItems(); + +	setFooterEnabled(FALSE); +	LLPanelGroupSubTab::setGroupID(id);  +} diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index 0cf272f3ee..e74e4f746d 100755 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -39,11 +39,9 @@ class LLScrollListCtrl;  class LLScrollListItem;  class LLTextEditor; -// Forward declare for friend usage. -//virtual BOOL LLPanelGroupSubTab::postBuildSubTab(LLView*); -  typedef std::map<std::string,std::string> icon_map_t; +  class LLPanelGroupRoles : public LLPanelGroupTab  {  public: @@ -92,6 +90,7 @@ protected:  	std::string				mWantApplyMesg;  }; +  class LLPanelGroupSubTab : public LLPanelGroupTab  {  public: @@ -147,6 +146,7 @@ protected:  	void setOthersVisible(BOOL b);  }; +  class LLPanelGroupMembersSubTab : public LLPanelGroupSubTab  {  public: @@ -173,6 +173,10 @@ public:  	void handleRoleCheck(const LLUUID& role_id,  						 LLRoleMemberChangeType type); +	static void onBanMember(void* user_data); +	void handleBanMember(); + +  	void applyMemberChanges();  	bool addOwnerCB(const LLSD& notification, const LLSD& response); @@ -206,6 +210,7 @@ protected:  	LLScrollListCtrl*	mAssignedRolesList;  	LLScrollListCtrl*	mAllowedActionsList;  	LLButton*           mEjectBtn; +	LLButton*			mBanBtn;  	BOOL mChanged;  	BOOL mPendingMemberUpdate; @@ -218,6 +223,7 @@ protected:  	boost::signals2::connection mAvatarNameCacheConnection;  }; +  class LLPanelGroupRolesSubTab : public LLPanelGroupSubTab  {  public: @@ -280,6 +286,7 @@ protected:  	std::string mRemoveEveryoneTxt;  }; +  class LLPanelGroupActionsSubTab : public LLPanelGroupSubTab  {  public: @@ -307,4 +314,44 @@ protected:  }; +class LLPanelGroupBanListSubTab : public LLPanelGroupSubTab +{ +public: +	LLPanelGroupBanListSubTab(); +	virtual ~LLPanelGroupBanListSubTab() {} + +	virtual BOOL postBuildSubTab(LLView* root); + +	virtual void activate(); +	virtual void update(LLGroupChange gc); +	virtual void draw(); + +	static void onBanEntrySelect(LLUICtrl* ctrl, void* user_data); +	void handleBanEntrySelect(); +	 +	static void onCreateBanEntry(void* user_data); +	void handleCreateBanEntry(); +	 +	static void onDeleteBanEntry(void* user_data); +	void handleDeleteBanEntry(); + +	static void onRefreshBanList(void* user_data); +	void handleRefreshBanList(); + +	void onBanListCompleted(bool isComplete); + +protected: +	void populateBanList(); + +public: +	virtual void setGroupID(const LLUUID& id); + +protected: +	LLNameListCtrl* mBanList; +	LLButton* mCreateBanButton; +	LLButton* mDeleteBanButton; +	LLButton* mRefreshBanListButton; + +}; +  #endif // LL_LLPANELGROUPROLES_H diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index e6fc82f761..c959166efd 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1600,6 +1600,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)  	capabilityNames.append("GetObjectCost");  	capabilityNames.append("GetObjectPhysicsData");  	capabilityNames.append("GetTexture"); +	capabilityNames.append("GroupBan");  	capabilityNames.append("GroupMemberData");  	capabilityNames.append("GroupProposalBallot");  	capabilityNames.append("HomeLocation"); diff --git a/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml b/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml new file mode 100644 index 0000000000..3baed595da --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + height="330" + label="Ban Residents" + layout="topleft" + left="0" + name="bulk_ban_panel" + top="330" + width="210"> +  <panel.string +   name="loading"> +    (loading...) +  </panel.string> +  <panel.string +     name="ban_selection_too_large"> +    Group Invitations not sent: too many Residents selected. Group Invitations are limited to 100 per request. +  </panel.string> +  <text +   type="string" +   length="1" +   height="54" +   layout="topleft" +   left="7" +   name="help_text" +   top="28" +   word_wrap="true" +   width="200"> +    You can select multiple Residents to ban from your group. Click 'Open Resident Chooser' to start. +  </text> +  <button +   height="20" +   label="Open Resident Chooser" +   layout="topleft" +   left_delta="-2" +   name="add_button" +   top_delta="44" +   width="200" /> +  <name_list +   allow_calling_card_drop="true" +   column_padding="0" +   height="174" +   layout="topleft" +   left_delta="0" +   multi_select="true" +   name="banned_agent_list" +   tool_tip="Hold the Ctrl key and click Resident names to multi-select" +   top_pad="4" +   width="200" /> +  <button +   height="20" +   label="Remove Selected from List" +   layout="topleft" +   left_delta="0" +   name="remove_button" +   tool_tip="Removes the Residents selected above from the ban list" +   top_pad="4" +   width="200" /> +  <button +   height="20" +   label="BAN THIS SICK FILTH" +   layout="topleft" +   left="4" +   name="ban_button" +   top_delta="30" +   width="135" /> +  <button +   height="20" +   label="Cancel" +   layout="topleft" +   left_pad="2" +   name="cancel_button" +   top_delta="0" +   width="65" /> +  <string +  name="GroupBulkBan"> +    Group Ban +  </string> +</panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_invite.xml b/indra/newview/skins/default/xui/en/panel_group_invite.xml index 124c0596c3..944a496fba 100755 --- a/indra/newview/skins/default/xui/en/panel_group_invite.xml +++ b/indra/newview/skins/default/xui/en/panel_group_invite.xml @@ -88,7 +88,7 @@       label="Send Invitations"       layout="topleft"       left="4" -     name="ok_button" +     name="invite_button"       top="356"       width="135" />      <button diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml index df91ad8b5e..15ddc8f313 100755 --- a/indra/newview/skins/default/xui/en/panel_group_roles.xml +++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml @@ -7,125 +7,132 @@   top="0"   name="roles_tab"   width="304"> -    <panel.string -     name="default_needs_apply_text"> -        There are unsaved changes -    </panel.string> -    <panel.string -     name="want_apply_text"> -        Do you want to save your changes? -    </panel.string> -    <panel.string -     name="help_text" /> -    <tab_container -    border="false" -     follows="left|top|right" -     height="552" -     halign="center" +  <panel.string +   name="default_needs_apply_text"> +    There are unsaved changes +  </panel.string> +  <panel.string +   name="want_apply_text"> +    Do you want to save your changes? +  </panel.string> +  <panel.string +   name="help_text" /> +  <tab_container +  border="false" +   follows="left|top|right" +   height="552" +   halign="center" +   layout="topleft" +   left="0" +   right="-1" +   name="roles_tab_container" +   tab_position="top" +   tab_height="22" +   tab_min_width="90" +   top="0" +   width="304"> +    <panel +     border="false" +     follows="all" +     height="303" +     label="MEMBERS"       layout="topleft"       left="0"       right="-1" -     name="roles_tab_container" -     tab_position="top" -     tab_height="22" -     tab_min_width="90" -     top="0" -     width="304"> -        <panel -         border="false" -         follows="all" -         height="303" -         label="MEMBERS" -         layout="topleft" -         left="0" -         right="-1" -         help_topic="roles_members_tab" -         name="members_sub_tab" -         tool_tip="Members" -         class="panel_group_members_subtab"> -            <panel.string -             name="help_text"> -                You can add or remove Roles assigned to Members. -Select multiple Members by holding the Ctrl key and -clicking on their names. -            </panel.string> -            <panel.string -             name="donation_area"> -                [AREA] m² -            </panel.string> -            <panel.string -             name="power_folder_icon" translate="false"> -                Inv_FolderClosed -            </panel.string> -            <panel.string -             name="power_all_have_icon" translate="false"> -                Checkbox_On -            </panel.string> -            <panel.string -             name="power_partial_icon" translate="false"> -                Checkbox_Off -            </panel.string> -         <filter_editor -         layout="topleft" -         top="5" -         left="5" -         right="-5" -         height="22" -         search_button_visible="false" -         follows="left|top|right" -         label="Filter Members" -         name="filter_input" /> -            <name_list -             column_padding="2" -             draw_heading="true" -             height="240" -             follows="left|top|right" -             layout="topleft" -             left="0" -             right="-1" -             multi_select="true" -             name="member_list" -             short_names="false"  -             top_pad="5"> -                <name_list.columns -                 label="Member" -                 name="name" -               relative_width="0.44" /> -                <name_list.columns -                 label="Donation" -                 name="donated" -         relative_width="0.25" /> -                <name_list.columns -                 label="Status" -                 name="online" -                 relative_width="0.14" /> -            </name_list> -            <button -             height="23" -             follows="top|left" -             label="Invite" -             left="5" -             name="member_invite" -             width="100" /> -            <button -             height="23" -             label="Eject" -             follows="top|left" -             left_pad="10" -             name="member_eject" -             width="100" /> -        </panel> -        <panel -         border="false" -         height="303" -         label="ROLES" -         layout="topleft" -         left="0" -         right="-1" -         help_topic="roles_roles_tab" -         name="roles_sub_tab" -         class="panel_group_roles_subtab"> -           <!-- <button +     help_topic="roles_members_tab" +     name="members_sub_tab" +     tool_tip="Members" +     class="panel_group_members_subtab"> +      <panel.string +       name="help_text"> +        You can add or remove Roles assigned to Members. +        Select multiple Members by holding the Ctrl key and +        clicking on their names. +      </panel.string> +      <panel.string +       name="donation_area"> +        [AREA] m² +      </panel.string> +      <panel.string +       name="power_folder_icon" translate="false"> +        Inv_FolderClosed +      </panel.string> +      <panel.string +       name="power_all_have_icon" translate="false"> +        Checkbox_On +      </panel.string> +      <panel.string +       name="power_partial_icon" translate="false"> +        Checkbox_Off +      </panel.string> +      <filter_editor +      layout="topleft" +      top="5" +      left="5" +      right="-5" +      height="22" +      search_button_visible="false" +      follows="left|top|right" +      label="Filter Members" +      name="filter_input" /> +      <name_list +       column_padding="2" +       draw_heading="true" +       height="240" +       follows="left|top|right" +       layout="topleft" +       left="0" +       right="-1" +       multi_select="true" +       name="member_list" +       short_names="false" +       top_pad="5"> +        <name_list.columns +         label="Member" +         name="name" +       relative_width="0.44" /> +        <name_list.columns +         label="Donation" +         name="donated" + relative_width="0.25" /> +        <name_list.columns +         label="Status" +         name="online" +         relative_width="0.14" /> +      </name_list> +      <button +       height="23" +       follows="top|left" +       label="Invite" +       left="5" +       name="member_invite" +       width="100" /> +      <button +       height="23" +       label="Eject" +       follows="top|left" +       left_pad="10" +       name="member_eject" +       width="100" /> +      <button +       height="23" +       label="Ban" +       follows="top|left" +       left_pad="10" +       name="member_ban" +       width="100" /> +    </panel> +    <panel +     border="false" +     height="303" +     label="ROLES" +     layout="topleft" +     left="0" +     right="-1" +     help_topic="roles_roles_tab" +     name="roles_sub_tab" +     class="panel_group_roles_subtab"> +      <!-- <button               enabled="false"               height="20"               label="Show All" @@ -134,454 +141,532 @@ clicking on their names.               right="-5"               name="show_all_button"               width="100" />--> -            <panel.string -             name="help_text"> -                Roles have a title and an allowed list of Abilities -that Members can perform. Members can belong to -one or more Roles. A group can have up to 10 Roles, -including the Everyone and Owner Roles. -            </panel.string> -            <panel.string -             name="cant_delete_role"> -                The 'Everyone' and 'Owners' Roles are special and can't be deleted. -            </panel.string> -            <panel.string -             name="power_folder_icon" translate="false"> -                Inv_FolderClosed -            </panel.string> -            <panel.string -             name="power_all_have_icon" translate="false"> -                Checkbox_On -            </panel.string> -            <panel.string -             name="power_partial_icon" translate="false"> -                Checkbox_Off -            </panel.string> -         <filter_editor -         layout="topleft" -         top="5" -         left="5" -         right="-5" -         height="22" -         search_button_visible="false" -         follows="left|top|right" -         label="Filter Roles" -         name="filter_input" /> -            <scroll_list -             column_padding="0" -             draw_heading="true" -             draw_stripes="false" -             heading_height="23" -             height="132" -             layout="topleft" -             search_column="1" -             left="0" -             follows="left|top|right" -             right="-1" -             name="role_list" -             top_pad="2" -             width="310"> -                <scroll_list.columns -                 label="Role" -                 name="name" -               relative_width="0.45"  /> -                <scroll_list.columns -                 label="Title" -                 name="title" -               relative_width="0.45"  /> -                <scroll_list.columns -                 label="#" -                 name="members" -               relative_width="0.15"  /> -            </scroll_list> -            <button -            follows="top|left" -             height="23" -             label="New Role" -             layout="topleft" -             left="0" -             name="role_create" -             width="120" /> -            <button -             height="23" -             follows="top|left" -             label="Delete Role" -             layout="topleft" -             left_pad="10" -             name="role_delete" -             width="120" /> -        </panel> -        <panel -         border="false" -         height="303" -         label="ABILITIES" -         layout="topleft" -         left="0" -         right="-1" -         help_topic="roles_actions_tab" -         name="actions_sub_tab" -         class="panel_group_actions_subtab" -         tool_tip="You can view an Ability's Description and which Roles and Members can execute the Ability." -         width="310"> -            <panel.string -             name="help_text"> -                Abilities allow Members in Roles to do specific -things in this group. There's a broad variety of Abilities. -            </panel.string> -            <panel.string -             name="power_folder_icon" translate="false"> -                Inv_FolderClosed -            </panel.string> -            <panel.string -             name="power_all_have_icon" translate="false"> -                Checkbox_On -            </panel.string> -            <panel.string -             name="power_partial_icon" translate="false"> -                Checkbox_Off -            </panel.string> -         <filter_editor -         layout="topleft" -         top="5" -         left="5" -         right="-5" -         height="22" -         search_button_visible="false" -         follows="left|top|right" -         label="Filter Abilities" -         name="filter_input" /> -        <scroll_list -         column_padding="0" -         draw_stripes="true" -         height="200" -         follows="left|top|right" -         layout="topleft" -         left="0" -         right="-1" -         name="action_list" -         search_column="2" -         tool_tip="Select an Ability to view more details" -         top_pad="5" -         width="300"> -            <scroll_list.columns -             label="" -             name="icon" -             width="2" /> -            <scroll_list.columns -             label="" -             name="checkbox" -             width="20" /> -            <scroll_list.columns -             label="" -             name="action" -             width="270" /> -        </scroll_list> -        </panel> -    </tab_container> +      <panel.string +       name="help_text"> +        Roles have a title and an allowed list of Abilities +        that Members can perform. Members can belong to +        one or more Roles. A group can have up to 10 Roles, +        including the Everyone and Owner Roles. +      </panel.string> +      <panel.string +       name="cant_delete_role"> +        The 'Everyone' and 'Owners' Roles are special and can't be deleted. +      </panel.string> +      <panel.string +       name="power_folder_icon" translate="false"> +        Inv_FolderClosed +      </panel.string> +      <panel.string +       name="power_all_have_icon" translate="false"> +        Checkbox_On +      </panel.string> +      <panel.string +       name="power_partial_icon" translate="false"> +        Checkbox_Off +      </panel.string> +      <filter_editor +      layout="topleft" +      top="5" +      left="5" +      right="-5" +      height="22" +      search_button_visible="false" +      follows="left|top|right" +      label="Filter Roles" +      name="filter_input" /> +      <scroll_list +       column_padding="0" +       draw_heading="true" +       draw_stripes="false" +       heading_height="23" +       height="132" +       layout="topleft" +       search_column="1" +       left="0" +       follows="left|top|right" +       right="-1" +       name="role_list" +       top_pad="2" +       width="310"> +        <scroll_list.columns +         label="Role" +         name="name" +       relative_width="0.45"  /> +        <scroll_list.columns +         label="Title" +         name="title" +       relative_width="0.45"  /> +        <scroll_list.columns +         label="#" +         name="members" +       relative_width="0.15"  /> +      </scroll_list> +      <button +      follows="top|left" +       height="23" +       label="New Role" +       layout="topleft" +       left="0" +       name="role_create" +       width="120" /> +      <button +       height="23" +       follows="top|left" +       label="Delete Role" +       layout="topleft" +       left_pad="10" +       name="role_delete" +       width="120" /> +    </panel>      <panel -     height="350" -     background_visible="false" -     bg_alpha_color="FloaterUnfocusBorderColor" +     border="false" +     height="303" +     label="ABILITIES"       layout="topleft" -     follows="top|left|right"       left="0"       right="-1" -     width="313" -     mouse_opaque="false" -     name="members_footer" -     top="325" -     visible="false"> -        <text -         type="string" -         height="16" -         layout="topleft" -         follows="left|top" -         left="5" -         top="8" -         text_color="EmphasisColor" -         name="static" -         width="300"> -            Assigned Roles -        </text> -        <scroll_list -         draw_stripes="true" -        follows="left|top|right" -         height="150" -         layout="topleft" -         left="0" -         right="-1" -         name="member_assigned_roles" -         top_pad="0"> -            <scroll_list.columns -             label="" -             name="checkbox" -             width="20" /> -            <scroll_list.columns -             label="" -             name="role" -             width="270" /> -        </scroll_list> -          <text -         type="string" -         height="16" -         layout="topleft" -         follows="left|top" -         left="5" -         top_pad="5" -         text_color="EmphasisColor" -         name="static2" -         width="285"> -            Allowed Abilities -        </text> -        <scroll_list -         draw_stripes="true" -             follows="left|top|right" -         height="150" -         layout="topleft" -         left="0" -         right="-1" -         name="member_allowed_actions" -         search_column="2" -         tool_tip="For details of each allowed ability see the abilities tab" -         top_pad="0"> -            <scroll_list.columns -             label="" -             name="icon" -             width="2" /> -            <scroll_list.columns -             label="" -             name="checkbox" -             width="20" /> -            <scroll_list.columns -             label="" -             name="action" -             width="270" /> -        </scroll_list> +     help_topic="roles_actions_tab" +     name="actions_sub_tab" +     class="panel_group_actions_subtab" +     tool_tip="You can view an Ability's Description and which Roles and Members can execute the Ability." +     width="310"> +      <panel.string +       name="help_text"> +        Abilities allow Members in Roles to do specific +        things in this group. There's a broad variety of Abilities. +      </panel.string> +      <panel.string +       name="power_folder_icon" translate="false"> +        Inv_FolderClosed +      </panel.string> +      <panel.string +       name="power_all_have_icon" translate="false"> +        Checkbox_On +      </panel.string> +      <panel.string +       name="power_partial_icon" translate="false"> +        Checkbox_Off +      </panel.string> +      <filter_editor +      layout="topleft" +      top="5" +      left="5" +      right="-5" +      height="22" +      search_button_visible="false" +      follows="left|top|right" +      label="Filter Abilities" +      name="filter_input" /> +      <scroll_list +       column_padding="0" +       draw_stripes="true" +       height="200" +       follows="left|top|right" +       layout="topleft" +       left="0" +       right="-1" +       name="action_list" +       search_column="2" +       tool_tip="Select an Ability to view more details" +       top_pad="5" +       width="300"> +        <scroll_list.columns +         label="" +         name="icon" +         width="2" /> +        <scroll_list.columns +         label="" +         name="checkbox" +         width="20" /> +        <scroll_list.columns +         label="" +         name="action" +         width="270" /> +      </scroll_list>      </panel>      <panel -     height="550" -     background_visible="false" -     bg_alpha_color="FloaterUnfocusBorderColor" +     border="false" +     height="303" +     label="BANNED AGENTS"       layout="topleft" -     follows="top|left|right"       left="0"       right="-1" -     width="313" -     mouse_opaque="false" -     name="roles_footer" -     top_delta="0" -     top="209" -     visible="false"> -        <text -         type="string" -         height="16" -         layout="topleft" -         follows="left|top" -         left="5" -         top="5" -         name="static" -         width="300"> -           Role Name -        </text> -        <line_editor -         type="string" -         height="20" -         layout="topleft" -         left="0" -         follows="left|top|right" -         right="-1" -         max_length_bytes="20" -         name="role_name" -         top_pad="0" -         width="300"> -        </line_editor> -        <text -         type="string" -         height="16" -         layout="topleft" -         follows="left|top" -         left="5" -         name="static3" -         top_pad="5" -         width="300"> -           Role Title -        </text> -        <line_editor -         type="string" -         height="20" -         layout="topleft" -         left="0" -         follows="left|top|right" -         right="-1" -         max_length_bytes="20" -         name="role_title" -         top_pad="0" -         width="300"> -        </line_editor> -               <text -         type="string" -         height="16" -         layout="topleft" -         follows="left|top" -         left="5" -         name="static2" -         top_pad="5" -         width="200"> -            Description -        </text> -        <text_editor -         type="string" -         layout="topleft" -         left="0" -         follows="left|top|right" -         right="-1" -         max_length="295" -         height="35" -         name="role_description" -         top_pad="0" -         width="300" -         word_wrap="true"> -        </text_editor> -        <text -         type="string" -         height="16" -         layout="topleft" -         follows="left|top" -         left="5" -         text_color="EmphasisColor" -         name="static4" -         top_pad="5" -         width="300"> -            Assigned Members -        </text> -        <name_list -         draw_stripes="true" -         height="128" -         layout="topleft" -         left="0" -         follows="left|top|right" -         right="-1" -         name="role_assigned_members" -         top_pad="0" -         width="300" /> -        <check_box -         height="15" -         label="Reveal members" -         left="5" -         layout="topleft" -         name="role_visible_in_list" -         tool_tip="Sets whether members of this role are visible in the General tab to people outside of the group." -         top_pad="4" -         width="300" /> -         <text -         type="string" -         height="16" -         layout="topleft" -         follows="left|top" -         left="5" -         text_color="EmphasisColor" -         name="static5" -         top_pad="2" -         width="300"> -            Allowed Abilities -        </text> -        <scroll_list -         draw_stripes="true" -         height="140" -         layout="topleft" -         left="0" -         follows="left|top|right" -         right="-1" -         name="role_allowed_actions" -         search_column="2" -         tool_tip="For details of each allowed ability see the abilities tab" -         top_pad="0" -         width="300"> -            <scroll_list.columns -             label="" -             name="icon" -             width="2" /> -            <scroll_list.columns -             label="" -             name="checkbox" -             width="20" /> -            <scroll_list.columns -             label="" -             name="action" -             width="270" /> -        </scroll_list> +     help_topic="roles_banlist_tab" +     name="banlist_sub_tab" +     class="panel_group_banlist_subtab" +     tool_tip="View the banned agents from this group." +     width="310"> +      <panel.string +       name="help_text"> +        Any resident on the ban list will be unable to join the group. +      </panel.string> +      <filter_editor +      layout="topleft" +      top="5" +      left="5" +      right="-5" +      height="22" +      search_button_visible="false" +      follows="left|top|right" +      label="Filter Bans" +      name="filter_bans" /> +      <name_list +           column_padding="0" +           draw_heading="true" +           height="400" +           follows="left|top|right" +           layout="topleft" +           left="0" +           right="-1" +           multi_select="true" +           name="ban_list" +           short_names="false" +           top_pad="5"> +        <name_list.columns +         label="Resident" +         name="name" +         font.name="SANSSERIF_SMALL" +         font.style="NORMAL" +         relative_width="0.7" /> +        <name_list.columns +         label="Date Banned" +         name="ban_date" +         relative_width="0.3" /> +      </name_list> +      <button +        follows="top|left" +        height="23" +        label="Ban!" +        layout="topleft" +        left="3" +        name="ban_create" +        tool_tip="Ban residents from your group" +        width="120" /> +      <button +        follows="top|left" +        height="23" +        label="Unban!" +        layout="topleft" +        left_pad="5" +        name="ban_delete" +        tool_tip="Unban selected residents from your group" +        width="120" /> +      <button +        follows="top|left" +        height="23" +        width="23" +        image_overlay="Refresh_Off" +        layout="topleft" +        left_pad="5" +        name="ban_refresh" +        tool_tip="Refresh the ban list" +        />      </panel> -   <panel -     height="424" -     background_visible="false" -     bg_alpha_color="FloaterUnfocusBorderColor" +  </tab_container> +  <panel +   height="350" +   background_visible="false" +   bg_alpha_color="FloaterUnfocusBorderColor" +   layout="topleft" +   follows="top|left|right" +   left="0" +   right="-1" +   width="313" +   mouse_opaque="false" +   name="members_footer" +   top="325" +   visible="false"> +    <text +     type="string" +     height="16" +     layout="topleft" +     follows="left|top" +     left="5" +     top="8" +     text_color="EmphasisColor" +     name="static" +     width="300"> +      Assigned Roles +    </text> +    <scroll_list +     draw_stripes="true" +    follows="left|top|right" +     height="150"       layout="topleft" -     follows="top|left|right"       left="0"       right="-1" -     width="313" -     mouse_opaque="false" -     name="actions_footer" -     top_delta="0" -     top="255" -     visible="false"> -        <text_editor -       bg_readonly_color="Transparent" -       text_readonly_color="EmphasisColor" -       font="SansSerifSmall" -         type="string" -         enabled="false" -         halign="left" -         layout="topleft" +     name="member_assigned_roles" +     top_pad="0"> +      <scroll_list.columns +       label="" +       name="checkbox" +       width="20" /> +      <scroll_list.columns +       label="" +       name="role" +       width="270" /> +    </scroll_list> +    <text +   type="string" +   height="16" +   layout="topleft" +   follows="left|top" +   left="5" +   top_pad="5" +   text_color="EmphasisColor" +   name="static2" +   width="285"> +      Allowed Abilities +    </text> +    <scroll_list +     draw_stripes="true"           follows="left|top|right" -         left="0" -         right="-1" -         height="90" -         max_length="512" -         name="action_description" -         top="0" -         word_wrap="true"> -            This Ability is 'Eject Members from this Group'. Only an Owner can eject another Owner. -        </text_editor> -        <text +     height="150" +     layout="topleft" +     left="0" +     right="-1" +     name="member_allowed_actions" +     search_column="2" +     tool_tip="For details of each allowed ability see the abilities tab" +     top_pad="0"> +      <scroll_list.columns +       label="" +       name="icon" +       width="2" /> +      <scroll_list.columns +       label="" +       name="checkbox" +       width="20" /> +      <scroll_list.columns +       label="" +       name="action" +       width="270" /> +    </scroll_list> +  </panel> +  <panel +   height="550" +   background_visible="false" +   bg_alpha_color="FloaterUnfocusBorderColor" +   layout="topleft" +   follows="top|left|right" +   left="0" +   right="-1" +   width="313" +   mouse_opaque="false" +   name="roles_footer" +   top_delta="0" +   top="209" +   visible="false"> +    <text +     type="string" +     height="16" +     layout="topleft" +     follows="left|top" +     left="5" +     top="5" +     name="static" +     width="300"> +      Role Name +    </text> +    <line_editor +     type="string" +     height="20" +     layout="topleft" +     left="0" +     follows="left|top|right" +     right="-1" +     max_length_bytes="20" +     name="role_name" +     top_pad="0" +     width="300"> +    </line_editor> +    <text +     type="string" +     height="16" +     layout="topleft" +     follows="left|top" +     left="5" +     name="static3" +     top_pad="5" +     width="300"> +      Role Title +    </text> +    <line_editor +     type="string" +     height="20" +     layout="topleft" +     left="0" +     follows="left|top|right" +     right="-1" +     max_length_bytes="20" +     name="role_title" +     top_pad="0" +     width="300"> +    </line_editor> +    <text           type="string"           height="16"           layout="topleft"           follows="left|top"           left="5"           name="static2" -         top_pad="1" -         width="300"> -            Roles with this ability -        </text> -        <scroll_list -         height="172" -         layout="topleft" -         follows="left|top|right" -         left="5" -         right="-1" -         name="action_roles" -         top_pad="0" -         width="300" /> -        <text -         type="string" -         height="16" -         layout="topleft" -         follows="left|top" -         left="5" -         name="static3"           top_pad="5" -         width="300"> -            Members with this ability -        </text> -        <name_list -         height="122" -         follows="left|top|right" -         layout="topleft" -         left="5" -         right="-1" -         name="action_members" -         top_pad="0" -         width="300" /> -    </panel> +         width="200"> +      Description +    </text> +    <text_editor +     type="string" +     layout="topleft" +     left="0" +     follows="left|top|right" +     right="-1" +     max_length="295" +     height="35" +     name="role_description" +     top_pad="0" +     width="300" +     word_wrap="true"> +    </text_editor> +    <text +     type="string" +     height="16" +     layout="topleft" +     follows="left|top" +     left="5" +     text_color="EmphasisColor" +     name="static4" +     top_pad="5" +     width="300"> +      Assigned Members +    </text> +    <name_list +     draw_stripes="true" +     height="128" +     layout="topleft" +     left="0" +     follows="left|top|right" +     right="-1" +     name="role_assigned_members" +     top_pad="0" +     width="300" /> +    <check_box +     height="15" +     label="Reveal members" +     left="5" +     layout="topleft" +     name="role_visible_in_list" +     tool_tip="Sets whether members of this role are visible in the General tab to people outside of the group." +     top_pad="4" +     width="300" /> +    <text +    type="string" +    height="16" +    layout="topleft" +    follows="left|top" +    left="5" +    text_color="EmphasisColor" +    name="static5" +    top_pad="2" +    width="300"> +      Allowed Abilities +    </text> +    <scroll_list +     draw_stripes="true" +     height="140" +     layout="topleft" +     left="0" +     follows="left|top|right" +     right="-1" +     name="role_allowed_actions" +     search_column="2" +     tool_tip="For details of each allowed ability see the abilities tab" +     top_pad="0" +     width="300"> +      <scroll_list.columns +       label="" +       name="icon" +       width="2" /> +      <scroll_list.columns +       label="" +       name="checkbox" +       width="20" /> +      <scroll_list.columns +       label="" +       name="action" +       width="270" /> +    </scroll_list> +  </panel> +  <panel +    height="424" +    background_visible="false" +    bg_alpha_color="FloaterUnfocusBorderColor" +    layout="topleft" +    follows="top|left|right" +    left="0" +    right="-1" +    width="313" +    mouse_opaque="false" +    name="actions_footer" +    top_delta="0" +    top="255" +    visible="false"> +    <text_editor +   bg_readonly_color="Transparent" +   text_readonly_color="EmphasisColor" +   font="SansSerifSmall" +     type="string" +     enabled="false" +     halign="left" +     layout="topleft" +     follows="left|top|right" +     left="0" +     right="-1" +     height="90" +     max_length="512" +     name="action_description" +     top="0" +     word_wrap="true"> +      This Ability is 'Eject Members from this Group'. Only an Owner can eject another Owner. +    </text_editor> +    <text +     type="string" +     height="16" +     layout="topleft" +     follows="left|top" +     left="5" +     name="static2" +     top_pad="1" +     width="300"> +      Roles with this ability +    </text> +    <scroll_list +     height="172" +     layout="topleft" +     follows="left|top|right" +     left="5" +     right="-1" +     name="action_roles" +     top_pad="0" +     width="300" /> +    <text +     type="string" +     height="16" +     layout="topleft" +     follows="left|top" +     left="5" +     name="static3" +     top_pad="5" +     width="300"> +      Members with this ability +    </text> +    <name_list +     height="122" +     follows="left|top|right" +     layout="topleft" +     left="5" +     right="-1" +     name="action_members" +     top_pad="0" +     width="300" /> +  </panel>  </panel> diff --git a/indra/newview/skins/default/xui/en/role_actions.xml b/indra/newview/skins/default/xui/en/role_actions.xml index 0eeccbeac5..7459fdae98 100755 --- a/indra/newview/skins/default/xui/en/role_actions.xml +++ b/indra/newview/skins/default/xui/en/role_actions.xml @@ -1,5 +1,12 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <role_actions> +  <action_set +      description="These Abilities include powers to ban and un-ban residents from the group." +      name="Bans"> +    <action description="Manage ban list." +            longdescription="Allows the group member to ban / un-ban Residents from this group." +            name="allow ban" value="49" /> +  </action_set>  	<action_set  	     description="These Abilities include powers to add and remove group Members, and allow new Members to join without an invitation."  	     name="Membership"> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 73601ecb9f..0a3a46106a 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3675,6 +3675,7 @@ Abuse Report</string>    <string name="LocalEstimateUSD">US$ [AMOUNT]</string>    <!-- Group Profile roles and powers --> +  <string name="Group Ban">Group Ban</string>    <string name="Membership">Membership</string>    <string name="Roles">Roles</string>    <string name="Group Identity">Group Identity</string> | 
