From 4945ae17d3692f089ce6c996f6585a5e5b308e4d Mon Sep 17 00:00:00 2001 From: Baker Linden Date: Thu, 29 Aug 2013 11:36:45 -0700 Subject: Initial commit for GroupBan - Lots of crap isn't working as intended yet. --- indra/llcommon/roles_constants.h | 100 +-- indra/llcommon/stdenums.h | 1 + indra/newview/CMakeLists.txt | 7 + indra/newview/llfloatergroupbulkban.cpp | 134 ++++ indra/newview/llfloatergroupbulkban.h | 48 ++ indra/newview/llgroupmgr.cpp | 172 +++++- indra/newview/llgroupmgr.h | 83 ++- indra/newview/llpanelgroupbulk.cpp | 403 ++++++++++++ indra/newview/llpanelgroupbulk.h | 74 +++ indra/newview/llpanelgroupbulkban.cpp | 156 +++++ indra/newview/llpanelgroupbulkban.h | 47 ++ indra/newview/llpanelgroupbulkimpl.h | 87 +++ indra/newview/llpanelgroupinvite.cpp | 673 +++++---------------- indra/newview/llpanelgroupinvite.h | 29 +- indra/newview/llpanelgrouproles.cpp | 512 ++++++++++++++-- indra/newview/llpanelgrouproles.h | 57 ++ indra/newview/llviewerregion.cpp | 1 + .../skins/default/xui/en/panel_group_bulk_ban.xml | 78 +++ .../skins/default/xui/en/panel_group_invite.xml | 2 +- .../skins/default/xui/en/panel_group_roles.xml | 73 +++ .../newview/skins/default/xui/en/role_actions.xml | 7 + indra/newview/skins/default/xui/en/strings.xml | 1 + 22 files changed, 2072 insertions(+), 673 deletions(-) create mode 100644 indra/newview/llfloatergroupbulkban.cpp create mode 100644 indra/newview/llfloatergroupbulkban.h create mode 100644 indra/newview/llpanelgroupbulk.cpp create mode 100644 indra/newview/llpanelgroupbulk.h create mode 100644 indra/newview/llpanelgroupbulkban.cpp create mode 100644 indra/newview/llpanelgroupbulkban.h create mode 100644 indra/newview/llpanelgroupbulkimpl.h create mode 100644 indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml (limited to 'indra') 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 d06cee5ee6..6a9f91ffcd 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -229,6 +229,7 @@ set(viewer_SOURCE_FILES llfloaterfonttest.cpp llfloatergesture.cpp llfloatergodtools.cpp + llfloatergroupbulkban.cpp llfloatergroupinvite.cpp llfloatergroups.cpp llfloaterhandler.cpp @@ -398,6 +399,8 @@ set(viewer_SOURCE_FILES llpanelface.cpp llpanelgenerictip.cpp llpanelgroup.cpp + llpanelgroupbulk.cpp + llpanelgroupbulkban.cpp llpanelgroupgeneral.cpp llpanelgroupinvite.cpp llpanelgrouplandmoney.cpp @@ -812,6 +815,7 @@ set(viewer_HEADER_FILES llfloaterfonttest.h llfloatergesture.h llfloatergodtools.h + llfloatergroupbulkban.h llfloatergroupinvite.h llfloatergroups.h llfloaterhandler.h @@ -974,6 +978,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 sInstances; +}; + +// +// Globals +// +std::map 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..0d4b678019 100755 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -231,11 +231,13 @@ 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), + mGroupBanStatus(STATUS_INIT), + mGroupBanDataComplete(false), + mPendingRoleMemberRequest(false), mAccessTime(0.0f) { mMemberVersion.generate(); @@ -424,7 +426,7 @@ void LLGroupMgrGroupData::removeMemberData() delete mi->second; } mMembers.clear(); - mMemberDataComplete = FALSE; + mMemberDataComplete = false; mMemberVersion.generate(); } @@ -446,8 +448,8 @@ void LLGroupMgrGroupData::removeRoleData() } mRoles.clear(); mReceivedRoleMemberPairs = 0; - mRoleDataComplete = FALSE; - mRoleMemberDataComplete = FALSE; + mRoleDataComplete = false; + mRoleMemberDataComplete= false; } void LLGroupMgrGroupData::removeRoleMemberData() @@ -471,7 +473,7 @@ void LLGroupMgrGroupData::removeRoleMemberData() } mReceivedRoleMemberPairs = 0; - mRoleMemberDataComplete = FALSE; + mRoleMemberDataComplete= false; } LLGroupMgrGroupData::~LLGroupMgrGroupData() @@ -742,6 +744,22 @@ 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; +} + +bool LLGroupMgrGroupData::removeBanEntry(const LLUUID& ban_id) +{ + // Once we get this hooked up to the backend, we want to confirm the create or delete worked. + mBanList.erase(ban_id); + return true; +} + + + + // // LLGroupMgr // @@ -951,12 +969,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 +1044,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 +1121,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 +1235,7 @@ void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data) } } - group_datap->mRoleMemberDataComplete = TRUE; + group_datap->mRoleMemberDataComplete= true; group_datap->mRoleMembersRequestID.setNull(); } @@ -1543,7 +1561,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; } @@ -1840,6 +1858,122 @@ 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) +{ + LL_INFOS("GrpMgr") << "[BAKER] Received ban data!" << LL_ENDL; + LLGroupMgr::processGroupBanRequest(content); +} + +void LLGroupMgr::sendGroupBanRequest(EBanRequestType request_type, const LLUUID& group_id, const std::vector ban_list /* = std::vector() */) +{ + 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; + } + + LLHTTPClient::ResponderPtr grp_ban_responder = new GroupBanDataResponder(); + // PUT to our service. Add a body containing the group_id and list of agents to ban. + LLSD ban_ids = LLSD::emptyMap(); + ban_ids["group_id"] = group_id; + // Add our list of potential banned agents to the list + ban_ids["ban_ids"] = LLSD::emptyArray(); + LLSD ban_entry; + std::vector::const_iterator iter = ban_list.cbegin(); + for(;iter != ban_list.end(); ++iter) + { + ban_entry = (*iter); + ban_ids["ban_ids"].append(ban_entry); + } + + switch(request_type) + { + case REQUEST_GET: + cap_url += "?group_id=" + group_id.asString(); + LLHTTPClient::get(cap_url, grp_ban_responder); + break; + case REQUEST_PUT: + // BAKER TODO: Figure out which 'body' is correct. + LLHTTPClient::put(cap_url, ban_ids, grp_ban_responder, LLSD(), 60); + break; + case REQUEST_DEL: + LLHTTPClient::del(cap_url, grp_ban_responder, ban_ids, 60); + break; + } + + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id); + if (gdatap) + gdatap->setGroupBanStatus(LLGroupMgrGroupData::STATUS_REQUESTING); +} + + +void LLGroupMgr::processGroupBanRequest(const LLSD& content) +{ + // Did we get anything in content? + if(!content.size()) + { + LL_DEBUGS("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 banlist = LLSD::emptyMap(); + + + 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); + // We have nothing right now inside our banlist map. + // Once ban_date is implemented, set that here! + // + gdatap->createBanEntry(ban_id, LLGroupBanData()); + } + + gdatap->mChanged = TRUE; + gdatap->setGroupBanStatus(LLGroupMgrGroupData::STATUS_COMPLETE); + LLGroupMgr::getInstance()->notifyObservers(GC_BANLIST); +} + + + // Responder class for capability group management class GroupMemberDataResponder : public LLHTTPClient::Responder { @@ -1925,7 +2059,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 +2142,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..876883e87e 100755 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -33,7 +33,11 @@ #include #include +// 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 = "00/00/0000"; } + ~LLGroupBanData() {} + + std::string mBanDate; // Just store something here to ensure it works. +}; + + struct LLGroupTitle { std::string mTitle; @@ -197,11 +209,17 @@ struct LLGroupTitle BOOL mSelected; }; -class LLGroupMgr; - class LLGroupMgrGroupData { friend class LLGroupMgr; +public: + enum EGroupDataStatus + { + STATUS_NONE, + STATUS_REQUESTING, + STATUS_COMPLETE + }; + public: LLGroupMgrGroupData(const LLUUID& id); @@ -228,27 +246,46 @@ 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; } + bool isGroupBanDataComplete() { return mGroupBanDataComplete; } + + EGroupDataStatus getGroupBanStatus() { return mGroupBanStatus; } + void setGroupBanStatus(EGroupDataStatus status) { mGroupBanStatus = status; } F32 getAccessTime() const { return mAccessTime; } void setAccessed(); const LLUUID& getMemberVersion() const { return mMemberVersion; } + ////////////////////////////////////////////////////////////////////////// + // BAN LIST + ////////////////////////////////////////////////////////////////////////// + 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()); + bool removeBanEntry(const LLUUID& ban_id); + + + + public: typedef std::map member_list_t; typedef std::map role_list_t; typedef std::map change_map_t; typedef std::map role_data_map_t; + typedef std::map 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 mTitles; @@ -279,12 +316,16 @@ private: LLUUID mTitlesRequestID; U32 mReceivedRoleMemberPairs; - BOOL mMemberDataComplete; - BOOL mRoleDataComplete; - BOOL mRoleMemberDataComplete; - BOOL mGroupPropertiesDataComplete; + bool mMemberDataComplete; + bool mRoleDataComplete; + bool mRoleMemberDataComplete; + bool mGroupPropertiesDataComplete; + + EGroupDataStatus mGroupBanStatus; + bool mGroupBanDataComplete; + bool mGroupBanDataPending; - BOOL mPendingRoleMemberRequest; + bool mPendingRoleMemberRequest; F32 mAccessTime; // Generate a new ID every time mMembers @@ -311,6 +352,14 @@ class LLGroupMgr : public LLSingleton { LOG_CLASS(LLGroupMgr); +public: + enum EBanRequestType + { + REQUEST_GET = 0, + REQUEST_PUT, + REQUEST_DEL + }; + public: LLGroupMgr(); ~LLGroupMgr(); @@ -344,6 +393,9 @@ public: static void sendGroupMemberInvites(const LLUUID& group_id, std::map& role_member_pairs); static void sendGroupMemberEjects(const LLUUID& group_id, uuid_vec_t& member_ids); + // BAKER - Group Ban + static void sendGroupBanRequest(EBanRequestType request_type, const LLUUID& group_id, const std::vector ban_list = std::vector()); + static void processGroupBanRequest(const LLSD& content); // BAKER void sendCapGroupMembersRequest(const LLUUID& group_id); @@ -390,4 +442,3 @@ private: #endif - diff --git a/indra/newview/llpanelgroupbulk.cpp b/indra/newview/llpanelgroupbulk.cpp new file mode 100644 index 0000000000..6c6fd8cfe0 --- /dev/null +++ b/indra/newview/llpanelgroupbulk.cpp @@ -0,0 +1,403 @@ +/** +* @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("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 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 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 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 selection = mBulkAgentList->getAllSelected(); + if (selection.empty()) + mRemoveButton->setEnabled(FALSE); + else + mRemoveButton->setEnabled(TRUE); +} + +void LLPanelGroupBulkImpl::addUsers(const std::vector& 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 items = mBulkAgentList->getAllData(); + std::vector::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) + 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 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 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..57bab0c813 --- /dev/null +++ b/indra/newview/llpanelgroupbulkban.cpp @@ -0,0 +1,156 @@ +/** +* @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("group_name_text", recurse); + mImplementation->mBulkAgentList = getChild("banned_agent_list", recurse); + if ( mImplementation->mBulkAgentList ) + { + mImplementation->mBulkAgentList->setCommitOnSelectionChange(TRUE); + mImplementation->mBulkAgentList->setCommitCallback(LLPanelGroupBulkImpl::callbackSelect, mImplementation); + } + + LLButton* button = getChild("add_button", recurse); + if ( button ) + { + // default to opening avatarpicker automatically + // (*impl::callbackClickAdd)((void*)this); + button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickAdd, this); + } + + mImplementation->mRemoveButton = + getChild("remove_button", recurse); + if ( mImplementation->mRemoveButton ) + { + mImplementation->mRemoveButton->setClickedCallback(LLPanelGroupBulkImpl::callbackClickRemove, mImplementation); + mImplementation->mRemoveButton->setEnabled(FALSE); + } + + mImplementation->mOKButton = + getChild("ban_button", recurse); + if ( mImplementation->mOKButton ) + { + mImplementation->mOKButton->setClickedCallback(LLPanelGroupBulkBan::callbackClickSubmit, this); + mImplementation->mOKButton->setEnabled(FALSE); + } + + button = getChild("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 banned_agent_list; + std::vector agents = mImplementation->mBulkAgentList->getAllData(); + std::vector::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_PUT, mImplementation->mGroupID, banned_agent_list); + + // BAKER TEMP: + // For now, don't close, but clear the list. + mImplementation->mBulkAgentList->deleteAllItems(); + + //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& 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 133b269c11..c990584d22 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,216 @@ #include "lluictrlfactory.h" #include "llviewerwindow.h" -class LLPanelGroupInvite::impl + +// BAKER TODO: +// Figure out how to use LLHandle to make this safer +//bool invite_owner_callback(LLPanelGroupInvite panel, const LLSD& notification, const LLSD& response) +bool invite_owner_callback(LLHandle panel_handle, const LLSD& notification, const LLSD& response) { -public: - impl(const LLUUID& group_id); - ~impl(); - - void addUsers(const std::vector& 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; - - 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(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); } } -void LLPanelGroupInvite::impl::addUsers(const std::vector& names, - const uuid_vec_t& agent_ids) +void LLPanelGroupInvite::update() { - std::string name; - LLUUID id; + LLPanelGroupBulk::update(); - for (S32 i = 0; i < (S32)names.size(); i++) + if(mImplementation->mRoleNames) { - name = names[i]; - id = agent_ids[i]; - - // Make sure this agent isn't already in the list. - bool already_in_list = false; - std::vector items = mInvitees->getAllData(); - for (std::vector::iterator iter = items.begin(); - iter != items.end(); ++iter) + LLUUID store_selected_role = mImplementation->mRoleNames->getCurrentID(); + mImplementation->mRoleNames->clear(); + mImplementation->mRoleNames->removeall(); + mImplementation->mRoleNames->setCurrentByID(LLUUID::null); + + if(!mPendingRoleDataUpdate && !mPendingMemberDataUpdate) { - LLScrollListItem* item = *iter; - if (item->getUUID() == id) - { - already_in_list = true; - break; - } + ////////////////////////////////////////////////////////////////////////// + // Add role names + addRoleNames(); + //////////////////////////////////////////////////////////////////////////// + mImplementation->mRoleNames->setCurrentByID(store_selected_role); } - if (already_in_list) + else { - continue; + mImplementation->mRoleNames->add(mImplementation->mLoadingText, LLUUID::null, ADD_BOTTOM); } + + } +} + +BOOL LLPanelGroupInvite::postBuild() +{ + BOOL recurse = TRUE; - //add the name to the names list - LLSD row; - row["id"] = id; - row["columns"][0]["value"] = name; + mImplementation->mLoadingText = getString("loading"); + mImplementation->mRoleNames = getChild("role_name", + recurse); + mImplementation->mGroupName = getChild("group_name_text", recurse); + mImplementation->mBulkAgentList = getChild("invitee_list", recurse); + if ( mImplementation->mBulkAgentList ) + { + mImplementation->mBulkAgentList->setCommitOnSelectionChange(TRUE); + mImplementation->mBulkAgentList->setCommitCallback(LLPanelGroupBulkImpl::callbackSelect, mImplementation); + } - mInvitees->addElement(row); + LLButton* button = getChild("add_button", recurse); + if ( button ) + { + // default to opening avatarpicker automatically + // (*impl::callbackClickAdd)((void*)this); + button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickAdd, this); } + + mImplementation->mRemoveButton = + getChild("remove_button", recurse); + if ( mImplementation->mRemoveButton ) + { + mImplementation->mRemoveButton->setClickedCallback(LLPanelGroupBulkImpl::callbackClickRemove, mImplementation); + mImplementation->mRemoveButton->setEnabled(FALSE); + } + + mImplementation->mOKButton = getChild("invite_button", recurse); + if ( mImplementation->mOKButton ) + { + mImplementation->mOKButton->setClickedCallback(LLPanelGroupInvite::callbackClickSubmit, this); + mImplementation->mOKButton->setEnabled(FALSE); + } + + button = getChild("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 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 items = mInvitees->getAllData(); + std::vector items = mImplementation->mBulkAgentList->getAllData(); for (std::vector::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 +266,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 +276,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,394 +294,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("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 selection = - mInvitees->getAllSelected(); - if (selection.empty()) return; - - // 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 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 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 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); -} - -void LLPanelGroupInvite::addUsers(uuid_vec_t& agent_ids) -{ - std::vector 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 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("role_name", - recurse); - mImplementation->mGroupName = getChild("group_name_text", recurse); - mImplementation->mInvitees = - getChild("invitee_list", recurse); - if ( mImplementation->mInvitees ) - { - mImplementation->mInvitees->setCommitOnSelectionChange(TRUE); - mImplementation->mInvitees->setCommitCallback(impl::callbackSelect, mImplementation); - } - - LLButton* button = getChild("add_button", recurse); - if ( button ) - { - // default to opening avatarpicker automatically - // (*impl::callbackClickAdd)((void*)this); - button->setClickedCallback(impl::callbackClickAdd, this); - } - - mImplementation->mRemoveButton = - getChild("remove_button", recurse); - if ( mImplementation->mRemoveButton ) - { - mImplementation->mRemoveButton->setClickedCallback(impl::callbackClickRemove, mImplementation); - mImplementation->mRemoveButton->setEnabled(FALSE); - } - - mImplementation->mOKButton = - getChild("ok_button", recurse); - if ( mImplementation->mOKButton ) - { - mImplementation->mOKButton->setClickedCallback(impl::callbackClickOK, mImplementation); - mImplementation->mOKButton->setEnabled(FALSE); - } - - button = getChild("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 cfdac11d26..8d7b3c38ee 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,9 @@ bool agentCanAddToRole(const LLUUID& group_id, return false; } -// static +// LLPanelGroupRoles ///////////////////////////////////////////////////// +// static LLPanelGroupRoles::LLPanelGroupRoles() : LLPanelGroupTab(), mCurrentTab(NULL), @@ -412,6 +414,35 @@ BOOL LLPanelGroupRoles::hasModal() return panelp->hasModal(); } +// BAKER -- Moved this from all the way at the bottom +void LLPanelGroupRoles::setGroupID(const LLUUID& id) +{ + LLPanelGroupTab::setGroupID(id); + + LLPanelGroupMembersSubTab* group_members_tab = findChild("members_sub_tab"); + LLPanelGroupRolesSubTab* group_roles_tab = findChild("roles_sub_tab"); + LLPanelGroupActionsSubTab* group_actions_tab = findChild("actions_sub_tab"); + LLPanelGroupBanListSubTab* group_ban_tab = findChild("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("member_invite"); + if ( button ) + button->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_MEMBER_INVITE)); + + if(mSubTabContainer) + mSubTabContainer->selectTab(0); + + activate(); +} + +////////////////////////////////////////////////////////////////////////// + + +// LLPanelGroupSubTab //////////////////////////////////////////////////// //////////////////////////// // LLPanelGroupSubTab @@ -728,11 +759,14 @@ void LLPanelGroupSubTab::setFooterEnabled(BOOL enable) } } +////////////////////////////////////////////////////////////////////////// + + +// LLPanelGroupMembersSubTab ///////////////////////////////////////////// + //////////////////////////// // LLPanelGroupMembersSubTab //////////////////////////// - - static LLRegisterPanelClassWrapper t_panel_group_members_subtab("panel_group_members_subtab"); LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab() @@ -810,6 +844,14 @@ BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root) mEjectBtn->setEnabled(FALSE); } + mBanBtn = parent->getChild("member_ban", recurse); + if(mBanBtn) + { + mBanBtn->setClickedCallback(onBanMember, this); + mBanBtn->setEnabled(FALSE); + } + + return TRUE; } @@ -823,34 +865,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,6 +930,12 @@ void LLPanelGroupMembersSubTab::handleMemberSelect() LLGroupMgrGroupData::role_list_t::iterator iter = gdatap->mRoles.begin(); LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end(); + ////////////////////////////////////////////////////////////////////////// + // BAKER STUB: + // Check if the member has the power to ban (just like the eject below) + // Right now, just give it to them (for testing) + 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; @@ -986,6 +1006,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 +1068,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 +1084,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); } @@ -1231,7 +1257,6 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id, FALSE); } - // static void LLPanelGroupMembersSubTab::onRoleCheck(LLUICtrl* ctrl, void* user_data) { @@ -1653,7 +1678,7 @@ void LLPanelGroupMembersSubTab::updateMembers() return; } - //cleanup list only for first iretation + //cleanup list only for first iteration if(mMemberProgress == gdatap->mMembers.begin()) { mMembersList->deleteAllItems(); @@ -1712,12 +1737,55 @@ void LLPanelGroupMembersSubTab::updateMembers() handleMemberSelect(); } +// BAKER +void LLPanelGroupMembersSubTab::onBanMember(void* user_data) +{ + LLPanelGroupMembersSubTab* self = static_cast(user_data); + self->handleBanMember(); +} +void LLPanelGroupMembersSubTab::handleBanMember() +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupMembersSubTab::handleBanMember()" << LL_ENDL; + + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); + if(!gdatap) + { + llwarns << "LLPanelGroupMembersSubTab::handleMemberSelect() " + << "-- No group data!" << llendl; + return; + } + + std::vector selection = mMembersList->getAllSelected(); + if(selection.empty()) + { + LL_WARNS("BAKER") << "[BAKER] Empty selection!" << LL_ENDL; + return; + } + + std::vector::iterator itor; + for(itor = selection.begin(); itor != selection.end(); ++itor) + { + LLUUID ban_id = (*itor)->getUUID(); + LLGroupBanData ban_data; + + // DEL to People API somewhere in this chain... + gdatap->createBanEntry(ban_id, ban_data); + mMembersList->removeNameItem(ban_id); + + } + + +} + +////////////////////////////////////////////////////////////////////////// + + +// LLPanelGroupRolesSubTab /////////////////////////////////////////////// //////////////////////////// // LLPanelGroupRolesSubTab //////////////////////////// - static LLRegisterPanelClassWrapper t_panel_group_roles_subtab("panel_group_roles_subtab"); LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab() @@ -1962,7 +2030,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); } @@ -2010,6 +2078,9 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc) void LLPanelGroupRolesSubTab::onRoleSelect(LLUICtrl* ctrl, void* user_data) { LLPanelGroupRolesSubTab* self = static_cast(user_data); + if (!self) + return; + self->handleRoleSelect(); } @@ -2250,7 +2321,6 @@ bool LLPanelGroupRolesSubTab::addActionCB(const LLSD& notification, const LLSD& return false; } - // static void LLPanelGroupRolesSubTab::onPropertiesKey(LLLineEditor* ctrl, void* user_data) { @@ -2428,13 +2498,34 @@ void LLPanelGroupRolesSubTab::saveRoleChanges(bool select_saved_role) mHasRoleChange = FALSE; } } + +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 ///////////////////////////////////////////// + //////////////////////////// // LLPanelGroupActionsSubTab //////////////////////////// - static LLRegisterPanelClassWrapper t_panel_group_actions_subtab("panel_group_actions_subtab"); - LLPanelGroupActionsSubTab::LLPanelGroupActionsSubTab() : LLPanelGroupSubTab() { @@ -2607,26 +2698,343 @@ 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 t_panel_group_ban_subtab("panel_group_banlist_subtab"); + +LLPanelGroupBanListSubTab::LLPanelGroupBanListSubTab() + : LLPanelGroupSubTab(), + mBanList(NULL), + mCreateBanButton(NULL), + mDeleteBanButton(NULL), + mUpdateBanList(true) +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::ctor()" << LL_ENDL; +} + +BOOL LLPanelGroupBanListSubTab::postBuildSubTab(LLView* root) +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::postBuildSubTab()" << LL_ENDL; + + 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("members_sub_tab"); - LLPanelGroupRolesSubTab* group_roles_tab = findChild("roles_sub_tab"); - LLPanelGroupActionsSubTab* group_actions_tab = findChild("actions_sub_tab"); + // BAKER TODO: + // What are these? Looks like something inhereted from LLPanelGroupSubTab + mHeader = parent->getChild("banlist_header", recurse); + mFooter = parent->getChild("banlist_footer", recurse); + ////////////////////////////////////////////////////////////////////////// + + mBanList = parent->getChild("ban_list", recurse); + mCreateBanButton = parent->getChild("ban_create", recurse); + mDeleteBanButton = parent->getChild("ban_delete", 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) + return FALSE; - LLButton* button = getChild("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(FALSE); + + mDeleteBanButton->setClickedCallback(onDeleteBanEntry, this); + mDeleteBanButton->setEnabled(FALSE); + + setFooterEnabled(FALSE); - activate(); + return TRUE; +} + +void LLPanelGroupBanListSubTab::activate() +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::activate()" << LL_ENDL; + + LLPanelGroupSubTab::activate(); + + mBanList->deselectAllItems(); + mDeleteBanButton->setEnabled(FALSE); + + setFooterEnabled(FALSE); + update(GC_ALL); +} + +void LLPanelGroupBanListSubTab::deactivate() +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::deactivate()" << LL_ENDL; + + LLPanelGroupSubTab::deactivate(); +} + +bool LLPanelGroupBanListSubTab::needsApply(std::string& mesg) +{ + LL_INFOS("BAKER") << "LLPanelGroupBanListSubTab::needsApply()" << LL_ENDL; + + // STUB + return false; +} + +bool LLPanelGroupBanListSubTab::apply(std::string& mesg) +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::apply()" << LL_ENDL; + + + + + // STUB + return true; } +void LLPanelGroupBanListSubTab::update(LLGroupChange gc) +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::update()" << LL_ENDL; + + if (gc != GC_ALL || gc != GC_BANLIST) + return; + + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); + if(!gdatap) + { + LL_INFOS("BAKER") << "[BAKER] No group data!" << LL_ENDL; + return; + } + + switch(gdatap->getGroupBanStatus()) + { + // Must be initial update [ Check if I should request this at panel creation + // with everything else -- might as well] + // Request our ban list! + case LLGroupMgrGroupData::STATUS_INIT: + LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID); + break; + + // Already have a request out -- don't bother sending another one + // Repeat sending won't make a difference, as it'll be behind a load balancer + case LLGroupMgrGroupData::STATUS_REQUESTING: + break; + + // See if the list needs updating -- if we call update, but nothing changed, + // there's no reason to send another request. + // [NOTHING CHANGED] - Do Nothing! + // [SOMETHING CHANGED] - Don't panic! Just repopulate the ban list! + case LLGroupMgrGroupData::STATUS_COMPLETE: + populateBanList(); + + + break; + } +} + + +void LLPanelGroupBanListSubTab::populateBanList() +{ + //if(gdatap->getGroupBanStatus() == ) + + + +// mBanList->deleteAllItems(); +// LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID); +// +// std::map::const_iterator entry = gdatap->mBanList.begin(); +// for(; entry != gdatap->mBanList.end(); entry++) +// { +// LLNameListCtrl::NameItem ban_entry; +// ban_entry.value = entry->first; +// mBanList->addNameItemRow(ban_entry); +// } + + mUpdateBanList = false; +} + + +void LLPanelGroupBanListSubTab::onBanEntrySelect(LLUICtrl* ctrl, void* user_data) +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::onBanEntrySelect()" << LL_ENDL; + + LLPanelGroupBanListSubTab* self = static_cast(user_data); + if (!self) + return; + + self->handleBanEntrySelect(); +} + +void LLPanelGroupBanListSubTab::handleBanEntrySelect() +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::handleBanEntrySelect()" << LL_ENDL; + + // BAKER TODO: -- MOVE TO SELECT BAN ENTRY + // Make sure only authorized people have access to adding / deleting bans + //if (gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS)) + mCreateBanButton->setEnabled(TRUE); + + // Check if the agent has the ability to unban this person + //if (gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS)) + mDeleteBanButton->setEnabled(TRUE); +} + + +void LLPanelGroupBanListSubTab::onBanGroupMember(void* user_data) +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::onBanGroupMember()" << LL_ENDL; + + LLPanelGroupBanListSubTab* self = static_cast(user_data); + if (!self) + return; + + self->handleBanGroupMember(); +} + +void LLPanelGroupBanListSubTab::handleBanGroupMember() +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::handleBanGroupMember()" << LL_ENDL; + + ////////////////////////////////////////////////////////////////////////// + // BAKER TEMP + // Getting viewer functionality working, so I'm gonna cheat a bit here for now + // Assume everything worked on the back end + // + // First, get the entries added to the ban list + ////////////////////////////////////////////////////////////////////////// + +} + + +void LLPanelGroupBanListSubTab::onCreateBanEntry(void* user_data) +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::onCreateBanEntry()" << LL_ENDL; + + LLPanelGroupBanListSubTab* self = static_cast(user_data); + if (!self) + return; + + self->handleCreateBanEntry(); +} + +void LLPanelGroupBanListSubTab::handleCreateBanEntry() +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::handleCreateBanEntry()" << LL_ENDL; + + // STUB + // Attempt to add an entry into the database + // If there was a problem, don't add the entry to the local list + // Otherwise, add it + // + // For now, let's just add it to the local list for testing. We can hook it up + // at the end. + + + LLFloaterGroupBulkBan::showForGroup(mGroupID); + +} + + +void LLPanelGroupBanListSubTab::onDeleteBanEntry(void* user_data) +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::onDeleteBanEntry()" << LL_ENDL; + + LLPanelGroupBanListSubTab* self = static_cast(user_data); + if (!self) + return; + + self->handleDeleteBanEntry(); +} + +void LLPanelGroupBanListSubTab::handleDeleteBanEntry() +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::handleDeleteBanEntry()" << LL_ENDL; + + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); + if(!gdatap) + { + llwarns << "LLPanelGroupMembersSubTab::handleMemberSelect() " + << "-- No group data!" << llendl; + return; + } + + std::vector selection = mBanList->getAllSelected(); + if(selection.empty()) + { + LL_WARNS("BAKER") << "[BAKER] Empty selection!" << LL_ENDL; + return; + } + + ////////////////////////////////////////////////////////////////////////// + // BAKER STUB: + // Check if the member has the power to ban (just like the eject below) + 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::iterator itor; + for(itor = selection.begin(); itor != selection.end(); ++itor) + { + // STUB + // Attempt to remove entry from the database + // If there was a problem with the delete, don't remove it from the list yet! + // Otherwise, remove it from our local list. + // + + LLUUID ban_id = (*itor)->getUUID(); + if(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); + } + } + + +} + + +void LLPanelGroupBanListSubTab::setGroupID(const LLUUID& id) +{ + LL_INFOS("BAKER") << "[BAKER] LLPanelGroupBanListSubTab::setGroupID()" << LL_ENDL; + + if(mBanList) + mBanList->deleteAllItems(); + + setFooterEnabled(FALSE); + LLPanelGroupSubTab::setGroupID(id); +} + + + + diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index 78bb3c57a1..1695097fc5 100755 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -172,6 +172,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); @@ -205,6 +209,7 @@ protected: LLScrollListCtrl* mAssignedRolesList; LLScrollListCtrl* mAllowedActionsList; LLButton* mEjectBtn; + LLButton* mBanBtn; BOOL mChanged; BOOL mPendingMemberUpdate; @@ -305,5 +310,57 @@ protected: LLTextEditor* mActionDescription; }; +class LLPanelGroupBanListSubTab : public LLPanelGroupSubTab +{ +public: + LLPanelGroupBanListSubTab(); + virtual ~LLPanelGroupBanListSubTab() {} + + virtual BOOL postBuildSubTab(LLView* root); + + // Triggered when the tab becomes active. + virtual void activate(); + + // Triggered when the tab becomes inactive. + virtual void deactivate(); + + // Asks if something needs to be applied. + // If returning true, this function should modify the message to the user. + virtual bool needsApply(std::string& mesg); + + // Request to apply current data. + // If returning fail, this function should modify the message to the user. + virtual bool apply(std::string& mesg); + + // Triggered when group information changes in the group manager. + virtual void update(LLGroupChange gc); + + + static void onBanEntrySelect(LLUICtrl* ctrl, void* user_data); + void handleBanEntrySelect(); + + static void onBanGroupMember(void* user_data); + void handleBanGroupMember(); + + static void onCreateBanEntry(void* user_data); + void handleCreateBanEntry(); + + static void onDeleteBanEntry(void* user_data); + void handleDeleteBanEntry(); + + virtual void setGroupID(const LLUUID& id); + +protected: + void populateBanList(); + + +protected: + LLNameListCtrl* mBanList; + LLButton* mCreateBanButton; + LLButton* mDeleteBanButton; + + bool mUpdateBanList; + +}; #endif // LL_LLPANELGROUPROLES_H diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 8422708add..cfbfc983fb 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 @@ + + + + (loading...) + + + Group Invitations not sent: too many Residents selected. Group Invitations are limited to 100 per request. + + + You can select multiple Residents to ban from your group. Click 'Open Resident Chooser' to start. + +