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. + + - - Stretch Both Sides - + label_text.wrap="true" + label_text.width="100" + width="134" /> Date: Tue, 25 Feb 2014 17:06:06 +0200 Subject: MAINT-3671 Fix is changed to solve issue with other multi-previews --- indra/newview/llpreview.cpp | 2 ++ indra/newview/llpreviewscript.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp index 04934b13f1..2caf186b70 100755 --- a/indra/newview/llpreview.cpp +++ b/indra/newview/llpreview.cpp @@ -91,6 +91,7 @@ void LLPreview::setObjectID(const LLUUID& object_id) { loadAsset(); } + refreshFromItem(); } void LLPreview::setItem( LLInventoryItem* item ) @@ -100,6 +101,7 @@ void LLPreview::setItem( LLInventoryItem* item ) { loadAsset(); } + refreshFromItem(); } const LLInventoryItem *LLPreview::getItem() const diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 26c46d543c..18bbf110f7 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1879,7 +1879,7 @@ void LLLiveLSLEditor::loadAsset() mIsModifiable = item && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE); - refreshFromItem(); + // This is commented out, because we don't completely // handle script exports yet. /* -- cgit v1.2.3 From c23aebf89d678fdbd27ac12b92dabb22c0822166 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Wed, 26 Feb 2014 12:50:43 +0200 Subject: MAINT-3746 FIXED After replacing LLEnvManagerNew::setRegionChangeCallback with LLAgent::addRegionChangedCallback we should call RegionChanged callbacks to update NavMesh status. --- indra/newview/llagent.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index f150ceda67..27d2a92f77 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -850,12 +850,9 @@ boost::signals2::connection LLAgent::addParcelChangedCallback(parcel_changed_cal //----------------------------------------------------------------------------- void LLAgent::setRegion(LLViewerRegion *regionp) { - bool notifyRegionChange; - llassert(regionp); if (mRegionp != regionp) { - notifyRegionChange = true; std::string ip = regionp->getHost().getString(); LL_INFOS("AgentLocation") << "Moving agent into region: " << regionp->getName() @@ -908,10 +905,7 @@ void LLAgent::setRegion(LLViewerRegion *regionp) // Pass new region along to metrics components that care about this level of detail. LLAppViewer::metricsUpdateRegion(regionp->getHandle()); } - else - { - notifyRegionChange = false; - } + mRegionp = regionp; // TODO - most of what follows probably should be moved into callbacks @@ -947,11 +941,8 @@ void LLAgent::setRegion(LLViewerRegion *regionp) mRegionp->setCapabilitiesReceivedCallback(boost::bind(&LLAgent::handleServerBakeRegionTransition,this,_1)); } - if (notifyRegionChange) - { - LL_DEBUGS("AgentLocation") << "Calling RegionChanged callbacks" << LL_ENDL; - mRegionChangedSignal(); - } + LL_DEBUGS("AgentLocation") << "Calling RegionChanged callbacks" << LL_ENDL; + mRegionChangedSignal(); } -- cgit v1.2.3 From 3085c6e18847debc0f7fb6cf3dbcec66aec23687 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Thu, 27 Feb 2014 12:22:02 +0200 Subject: MAINT-3778 Develop>RenderMetadata>LOD Info no longer displays values for objects --- indra/newview/llvovolume.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index c233221e5f..87c7d26cc0 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1288,7 +1288,7 @@ BOOL LLVOVolume::calcLOD() if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && mDrawable->getFace(0)) { - //setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail)); + setDebugText(llformat("%.2f:%.2f, %d", mDrawable->mDistanceWRTCamera, radius, cur_detail)); //setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex())); } -- cgit v1.2.3 From a8e22e11c5d26b3cdfa2d67919fdde8272d52ea4 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Thu, 27 Feb 2014 17:49:50 -0600 Subject: MAINT-2980 Rename "Texture Memory" to "Video Memory" in hardware floater and increase limit. Limit should be however much vram is installed, but underneath the hood, fudge how much memory is used for textures to avoid swapping. Also, catch exceptions when attempting to build a GL context on windows and display an error dialog instead of crashing. --- indra/llwindow/llwindowwin32.cpp | 17 +++++++++++++++-- indra/newview/llfloaterhardwaresettings.cpp | 17 ++++++++++++++++- indra/newview/llfloaterhardwaresettings.h | 2 ++ indra/newview/llviewertexture.h | 2 +- indra/newview/llviewertexturelist.cpp | 15 ++++++--------- .../skins/default/xui/en/floater_hardware_settings.xml | 3 +-- 6 files changed, 41 insertions(+), 15 deletions(-) (limited to 'indra') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 30f5526500..767676b9b8 100755 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -85,6 +85,18 @@ void show_window_creation_error(const std::string& title) LL_WARNS("Window") << title << LL_ENDL; } +HGLRC SafeCreateContext(HDC hdc) +{ + __try + { + return wglCreateContext(hdc); + } + __except(EXCEPTION_EXECUTE_HANDLER) + { + return NULL; + } +} + //static BOOL LLWindowWin32::sIsClassRegistered = FALSE; @@ -1166,14 +1178,15 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO return FALSE; } - if (!(mhRC = wglCreateContext(mhDC))) + + if (!(mhRC = SafeCreateContext(mhDC))) { close(); OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); return FALSE; } - + if (!wglMakeCurrent(mhDC, mhRC)) { close(); diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp index 792a2a5d25..6923308ce9 100755 --- a/indra/newview/llfloaterhardwaresettings.cpp +++ b/indra/newview/llfloaterhardwaresettings.cpp @@ -87,15 +87,30 @@ void LLFloaterHardwareSettings::refresh() refreshEnabledState(); } +void LLFloaterHardwareSettings::onSetVRAM() +{ + S32 vram = childGetValue("GraphicsCardTextureMemory").asInteger(); + + //give the texture system plenty of leeway to avoid swapping + vram /= 3; + + gSavedSettings.setS32("TextureMemory", vram); +} + void LLFloaterHardwareSettings::refreshEnabledState() { F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); S32 min_tex_mem = LLViewerTextureList::getMinVideoRamSetting(); - S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier); + S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(true, mem_multiplier); getChild("GraphicsCardTextureMemory")->setMinValue(min_tex_mem); getChild("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem); + S32 vram = gSavedSettings.getS32("TextureMemory"); + vram = vram*3; + + getChild("GraphicsCardTextureMemory")->setValue(vram); + getChild("GraphicsCardTextureMemory")->setCommitCallback(boost::bind(&LLFloaterHardwareSettings::onSetVRAM, this)); if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") || !gGLManager.mHasVertexBufferObject) { diff --git a/indra/newview/llfloaterhardwaresettings.h b/indra/newview/llfloaterhardwaresettings.h index 626771b1d2..63d86d5667 100755 --- a/indra/newview/llfloaterhardwaresettings.h +++ b/indra/newview/llfloaterhardwaresettings.h @@ -64,6 +64,8 @@ public: /// don't apply the changed values void cancel(); + void onSetVRAM(); + /// refresh the enabled values void refreshEnabledState(); diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 10101a4b9b..78db136427 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -40,7 +40,7 @@ #include #define MIN_VIDEO_RAM_IN_MEGA_BYTES 32 -#define MAX_VIDEO_RAM_IN_MEGA_BYTES 512 // 512MB max for performance reasons. +#define MAX_VIDEO_RAM_IN_MEGA_BYTES 4096 class LLImageGL ; class LLImageRaw; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 783d1f2202..26f32941bf 100755 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1270,7 +1270,7 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_m // - it's going to be swapping constantly regardless S32 max_vram = gGLManager.mVRAM; - if(gGLManager.mIsATI) + if(!get_recommended && gGLManager.mIsATI) { //shrink the availabe vram for ATI cards because some of them do not handel texture swapping well. max_vram = (S32)(max_vram * 0.75f); @@ -1285,15 +1285,15 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_m { if (!get_recommended) { - max_texmem = 512; + max_texmem = 2048; } else if (gSavedSettings.getBOOL("NoHardwareProbe")) //did not do hardware detection at startup { - max_texmem = 512; + max_texmem = 2048; } else { - max_texmem = 128; + max_texmem = 512; } llwarns << "VRAM amount not detected, defaulting to " << max_texmem << " MB" << llendl; @@ -1301,10 +1301,7 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_m S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); // In MB //llinfos << "*** DETECTED " << system_ram << " MB of system memory." << llendl; - if (get_recommended) - max_texmem = llmin(max_texmem, (S32)(system_ram/2)); - else - max_texmem = llmin(max_texmem, (S32)(system_ram)); + max_texmem = llmin(max_texmem, (S32)(system_ram)); // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise max_texmem = llmin(max_texmem, (S32) (mem_multiplier * (F32) max_texmem)); @@ -1334,7 +1331,7 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem) mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting(false, mem_multiplier)); if (mem != cur_mem) { - gSavedSettings.setS32("TextureMemory", mem); + gSavedSettings.setS32("TextureMemory", mem/3); return; //listener will re-enter this function } diff --git a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml index 9deb0d2030..05594c2d86 100755 --- a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml @@ -155,13 +155,12 @@ tool_tip="Compresses textures in video memory, allowing for higher resolution textures to be loaded at the cost of some color quality." width="315" /> Date: Fri, 28 Feb 2014 15:33:09 +0200 Subject: MAINT-358 FIXED [PUBLIC]Verbs buttons are available for landmarks folder if it was selected via keyboard --- indra/llui/llfolderview.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 13d231d712..173279fa81 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1127,18 +1127,18 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if((mSelectedItems.size() > 0) && mScrollContainer) { LLFolderViewItem* last_selected = getCurSelectedItem(); + BOOL shift_select = mask & MASK_SHIFT; + // don't shift select down to children of folders (they are implicitly selected through parent) + LLFolderViewItem* next = last_selected->getNextOpenNode(!shift_select); - if (!mKeyboardSelection) + if (!mKeyboardSelection || (!shift_select && (!next || next == last_selected))) { setSelection(last_selected, FALSE, TRUE); mKeyboardSelection = TRUE; } - LLFolderViewItem* next = NULL; - if (mask & MASK_SHIFT) + if (shift_select) { - // don't shift select down to children of folders (they are implicitly selected through parent) - next = last_selected->getNextOpenNode(FALSE); if (next) { if (next->isSelected()) @@ -1155,7 +1155,6 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) } else { - next = last_selected->getNextOpenNode(); if( next ) { if (next == last_selected) @@ -1191,18 +1190,18 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) if((mSelectedItems.size() > 0) && mScrollContainer) { LLFolderViewItem* last_selected = mSelectedItems.back(); + BOOL shift_select = mask & MASK_SHIFT; + // don't shift select down to children of folders (they are implicitly selected through parent) + LLFolderViewItem* prev = prev = last_selected->getPreviousOpenNode(!shift_select); - if (!mKeyboardSelection) + if (!mKeyboardSelection || (!shift_select && prev == this)) { setSelection(last_selected, FALSE, TRUE); mKeyboardSelection = TRUE; } - LLFolderViewItem* prev = NULL; - if (mask & MASK_SHIFT) + if (shift_select) { - // don't shift select down to children of folders (they are implicitly selected through parent) - prev = last_selected->getPreviousOpenNode(FALSE); if (prev) { if (prev->isSelected()) @@ -1219,7 +1218,6 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) } else { - prev = last_selected->getPreviousOpenNode(); if( prev ) { if (prev == this) -- cgit v1.2.3 From 80ba9cfeb1351664a57dd1390ee815f3901e3bb5 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Fri, 28 Feb 2014 15:37:41 +0200 Subject: MAINT-2613 Two entries for 'DisablePrecacheDelayAfterTeleporting' in settings.xml --- indra/newview/app_settings/settings.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 2a01b81943..6ebda3ff6a 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -14936,6 +14936,17 @@ Value 7000 + DisablePrecacheDelayAfterTeleporting + + Comment + Disables the artificial delay in the viewer that precaches some incoming assets + Persist + 0 + Type + Boolean + Value + 0 + VersionChannelName Comment -- cgit v1.2.3 From d9d2659e11991ba41a052e011c610a213872d705 Mon Sep 17 00:00:00 2001 From: andreylproductengine Date: Fri, 28 Feb 2014 16:47:18 +0200 Subject: MAINT-3752: Changed the "Show me in Search result" checkbox caption --- indra/newview/skins/default/xui/da/panel_preferences_privacy.xml | 2 +- indra/newview/skins/default/xui/de/panel_preferences_privacy.xml | 2 +- indra/newview/skins/default/xui/en/panel_preferences_privacy.xml | 2 +- indra/newview/skins/default/xui/es/panel_preferences_privacy.xml | 2 +- indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml | 4 ++-- indra/newview/skins/default/xui/it/panel_preferences_privacy.xml | 2 +- indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml | 2 +- indra/newview/skins/default/xui/pl/panel_preferences_privacy.xml | 2 +- indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml | 2 +- indra/newview/skins/default/xui/ru/panel_preferences_privacy.xml | 2 +- indra/newview/skins/default/xui/tr/panel_preferences_privacy.xml | 2 +- indra/newview/skins/default/xui/zh/panel_preferences_privacy.xml | 2 +- 12 files changed, 13 insertions(+), 13 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/da/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/da/panel_preferences_privacy.xml index 0df330b016..6d48180707 100755 --- a/indra/newview/skins/default/xui/da/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/da/panel_preferences_privacy.xml @@ -7,7 +7,7 @@ (Lokationer, billeder, web, søge historik) - + diff --git a/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml index e21bed6bb5..afde50b981 100755 --- a/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml @@ -7,7 +7,7 @@ (Standorte, Bilder, Web, Suchverlauf) - + diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index 78743d26bb..d7ffb73dda 100755 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -47,7 +47,7 @@ (Localizaciones, imágenes, web, historial de búsqueda) - + diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml index cf1a374da6..a89676d119 100755 --- a/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml @@ -7,13 +7,13 @@ (endroits, images, web, historique des recherches) - + - Journaux de chat : + Journaux de chat : diff --git a/indra/newview/skins/default/xui/it/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/it/panel_preferences_privacy.xml index 41e7a59139..241ed8f162 100755 --- a/indra/newview/skins/default/xui/it/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/it/panel_preferences_privacy.xml @@ -7,7 +7,7 @@ (Luoghi, immagini, web, cronologia ricerche) - + diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml index 420bbed572..3787f390e4 100755 --- a/indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml @@ -7,7 +7,7 @@ (位置、画像、web、検索履歴) - + diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/pl/panel_preferences_privacy.xml index 5af2fed142..30b64bc977 100755 --- a/indra/newview/skins/default/xui/pl/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/pl/panel_preferences_privacy.xml @@ -7,7 +7,7 @@ (Miejsca, obrazy, przeglądarka internetowa, wyszukiwarka historii) - + diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml index d7fb585e35..8ca05c948a 100755 --- a/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/pt/panel_preferences_privacy.xml @@ -7,7 +7,7 @@ (Locações, imagens, web, histórico de busca) - + diff --git a/indra/newview/skins/default/xui/ru/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/ru/panel_preferences_privacy.xml index 20bb839eed..ed6bed439c 100755 --- a/indra/newview/skins/default/xui/ru/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/ru/panel_preferences_privacy.xml @@ -7,7 +7,7 @@ (Места, картинки, страницы, журнал поиска) - + diff --git a/indra/newview/skins/default/xui/tr/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/tr/panel_preferences_privacy.xml index 9111594979..285670a6ac 100755 --- a/indra/newview/skins/default/xui/tr/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/tr/panel_preferences_privacy.xml @@ -7,7 +7,7 @@ (Konumlar, görüntüler, web, arama geçmişi) - + diff --git a/indra/newview/skins/default/xui/zh/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/zh/panel_preferences_privacy.xml index 07fdfd87e3..d768cacb94 100755 --- a/indra/newview/skins/default/xui/zh/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/zh/panel_preferences_privacy.xml @@ -7,7 +7,7 @@ (位置、圖像、網頁、搜尋的歷史紀錄) - + -- cgit v1.2.3 From 100b0f48a9d9aa2883e12ee2c52fc380540711bb Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Mon, 3 Mar 2014 20:13:09 +0200 Subject: MAINT-2902 FIXED Browser secure session indicator should be prominent --- indra/newview/llfloaterwebcontent.cpp | 16 +++++----------- indra/newview/llfloaterwebcontent.h | 1 - 2 files changed, 5 insertions(+), 12 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 68dbb5ae33..3e9051967c 100755 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -70,8 +70,7 @@ LLFloaterWebContent::LLFloaterWebContent( const Params& params ) mShowPageTitle(params.show_page_title), mAllowNavigation(true), mCurrentURL(""), - mDisplayURL(""), - mSecureURL(false) + mDisplayURL("") { mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this )); mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this )); @@ -315,9 +314,6 @@ void LLFloaterWebContent::draw() mBtnBack->setEnabled( mWebBrowser->canNavigateBack() && mAllowNavigation); mBtnForward->setEnabled( mWebBrowser->canNavigateForward() && mAllowNavigation); - // Show/hide the lock icon - mSecureLockIcon->setVisible(mSecureURL && !mAddressCombo->hasFocus()); - LLFloater::draw(); } @@ -362,8 +358,6 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent // we populate the status bar with URLs as they change so clear it now we're done const std::string end_str = ""; mStatusBarText->setText( end_str ); - mAddressCombo->setLeftTextPadding(22); - mAddressCombo->setLeftTextPadding(2); } else if(event == MEDIA_EVENT_CLOSE_REQUEST) { @@ -430,10 +424,10 @@ void LLFloaterWebContent::set_current_url(const std::string& url) static const std::string secure_prefix = std::string("https://"); std::string prefix = mCurrentURL.substr(0, secure_prefix.length()); LLStringUtil::toLower(prefix); - mSecureURL = (prefix == secure_prefix); - - // Hack : we move the text a bit to make space for the lock icon in the secure URL case - mDisplayURL = (mSecureURL ? " " + mCurrentURL : mCurrentURL); + bool secure_url = (prefix == secure_prefix); + mSecureLockIcon->setVisible(secure_url); + mAddressCombo->setLeftTextPadding(secure_url ? 22 : 2); + mDisplayURL = mCurrentURL; // Clean up browsing list (prevent dupes) and add/select the new URL to it mAddressCombo->remove(mCurrentURL); diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index f22940cd07..2206784e37 100755 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -112,7 +112,6 @@ protected: std::string mUUID; bool mShowPageTitle; bool mAllowNavigation; - bool mSecureURL; // true when the current url is prefixed "https://" }; #endif // LL_LLFLOATERWEBCONTENT_H -- cgit v1.2.3 From 65850279964bed111e0d11b99f26867cd46b91b7 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Wed, 5 Mar 2014 12:25:52 +0200 Subject: fix build problem --- indra/llui/llfolderview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 173279fa81..c9ea0c0e1b 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1192,7 +1192,7 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask ) LLFolderViewItem* last_selected = mSelectedItems.back(); BOOL shift_select = mask & MASK_SHIFT; // don't shift select down to children of folders (they are implicitly selected through parent) - LLFolderViewItem* prev = prev = last_selected->getPreviousOpenNode(!shift_select); + LLFolderViewItem* prev = last_selected->getPreviousOpenNode(!shift_select); if (!mKeyboardSelection || (!shift_select && prev == this)) { -- cgit v1.2.3 From e62e7319932448eac55486e218d31048dbd034fc Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Wed, 5 Mar 2014 15:15:50 +0200 Subject: MAINT-3698 FIXED Reduce Abuse type options available in the abuse report dialog --- .../skins/default/xui/en/floater_report_abuse.xml | 128 +++------------------ 1 file changed, 16 insertions(+), 112 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml index 9561f67941..24f95950d8 100755 --- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml @@ -203,47 +203,15 @@ + value="31" /> - - - - - + value="35" /> - - - + value="39" /> - - - - + value="45" /> + value="50" /> - - - - - + value="55" /> - - - + value="60" /> - + value="61" /> + value="63" /> - - - + value="67" /> Date: Thu, 6 Mar 2014 05:51:49 +0200 Subject: MAINT-3610 FIXED SL viewer partly 'eats' chat-messages --- indra/llui/llchatentry.cpp | 10 +--------- indra/llui/lltexteditor.cpp | 5 +++-- indra/llui/lltexteditor.h | 2 ++ 3 files changed, 6 insertions(+), 11 deletions(-) (limited to 'indra') diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index c04b70eb64..dac001afab 100755 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -51,6 +51,7 @@ LLChatEntry::LLChatEntry(const Params& p) mCurrentHistoryLine = mLineHistory.begin(); mAutoIndent = false; + keepSelectionOnReturn(true); } LLChatEntry::~LLChatEntry() @@ -179,15 +180,6 @@ BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask) { BOOL handled = FALSE; - // In the case of a chat entry, pressing RETURN when something is selected - // should NOT erase the selection (unlike a notecard, for example) - if (key == KEY_RETURN) - { - endOfDoc(); - startSelection(); - endSelection(); - } - LLTextEditor::handleSpecialKey(key, mask); switch(key) diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3bac15c5d4..6c4d031907 100755 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -264,7 +264,8 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : mContextMenu(NULL), mShowContextMenu(p.show_context_menu), mEnableTooltipPaste(p.enable_tooltip_paste), - mPassDelete(FALSE) + mPassDelete(FALSE), + mKeepSelectionOnReturn(false) { mSourceID.generate(); @@ -1664,7 +1665,7 @@ BOOL LLTextEditor::handleSpecialKey(const KEY key, const MASK mask) case KEY_RETURN: if (mask == MASK_NONE) { - if( hasSelection() ) + if( hasSelection() && !mKeepSelectionOnReturn ) { deleteSelection(FALSE); } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index d3b7bc0eb7..02a76d2f8a 100755 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -295,6 +295,7 @@ protected: /*virtual*/ void updateSegments(); void updateLinkSegments(); + void keepSelectionOnReturn(bool keep) { mKeepSelectionOnReturn = keep; } private: // @@ -338,6 +339,7 @@ private: bool mParseOnTheFly; bool mEnableTooltipPaste; bool mPassDelete; + bool mKeepSelectionOnReturn; // disabling of removing selected text after pressing of Enter LLUUID mSourceID; -- cgit v1.2.3 From 08c7787393d5b9f2875788b344d68a541108b65b Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Tue, 11 Mar 2014 12:19:54 +0200 Subject: MAINT-2737 FIXED Disable button if multiple parcels are selected --- indra/newview/llpanelland.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanelland.cpp b/indra/newview/llpanelland.cpp index 5321ebc777..1946b9c523 100755 --- a/indra/newview/llpanelland.cpp +++ b/indra/newview/llpanelland.cpp @@ -145,7 +145,7 @@ void LLPanelLandInfo::refresh() && ((gAgent.getID() == auth_buyer_id) || (auth_buyer_id.isNull()))); - if (is_public) + if (is_public && !LLViewerParcelMgr::getInstance()->getParcelSelection()->getMultipleOwners()) { getChildView("button buy land")->setEnabled(TRUE); } -- cgit v1.2.3 From 0fb8400e3462ac3585a2af4076d23c20cee8d458 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Tue, 11 Mar 2014 12:51:40 +0200 Subject: MAINT-3778 Develop>RenderMetadata>LOD Info no longer displays values for objects --- indra/newview/llvovolume.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 87c7d26cc0..3d41e248de 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1288,9 +1288,9 @@ BOOL LLVOVolume::calcLOD() if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_LOD_INFO) && mDrawable->getFace(0)) { - setDebugText(llformat("%.2f:%.2f, %d", mDrawable->mDistanceWRTCamera, radius, cur_detail)); + //setDebugText(llformat("%.2f:%.2f, %d", mDrawable->mDistanceWRTCamera, radius, cur_detail)); - //setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex())); + setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex())); } if (cur_detail != mLOD) -- cgit v1.2.3 From 504509c2882b098997ff4ab2648cc555c2314c2f Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Fri, 7 Mar 2014 20:27:12 +0200 Subject: MAINT-3789 FIXED When moving items between inventory folders, the moved item is no longer highlighted in the new folder. --- indra/newview/llinventorypanel.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra') diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index d27f7d2527..ed217718c1 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -529,6 +529,14 @@ void LLInventoryPanel::modelChanged(U32 mask) // Item is to be moved and we found its new parent in the panel's directory, so move the item's UI. view_item->addToFolder(new_parent); addItemID(viewmodel_item->getUUID(), view_item); + if (mInventory) + { + const LLUUID trash_id = mInventory->findCategoryUUIDForType(LLFolderType::FT_TRASH); + if (trash_id != model_item->getParentUUID() && (mask & LLInventoryObserver::INTERNAL) && new_parent->isOpen()) + { + setSelection(item_id, FALSE); + } + } } else { -- cgit v1.2.3 From 2ae011dc5ce8b2112c65757ac85e0567165975cf Mon Sep 17 00:00:00 2001 From: andreylproductengine Date: Tue, 11 Mar 2014 19:22:11 +0200 Subject: MAINT-3786 FIXED When bringing focus back to the viewer with a single click in world view, a double click teleport to clicked point happens under certain circumstances --- indra/llwindow/llwindowwin32.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'indra') diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 30f5526500..e45a511e6d 100755 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1831,6 +1831,10 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // This helps prevent avatar walking after maximizing the window by double-clicking the title bar. static bool sHandleLeftMouseUp = true; + // Ignore the double click received right after activating app. + // This is to avoid triggering double click teleport after returning focus (see MAINT-3786). + static bool sHandleDoubleClick = true; + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(h_wnd, GWL_USERDATA); @@ -1958,6 +1962,11 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ } } + if (!activating) + { + sHandleDoubleClick = false; + } + window_imp->mCallbacks->handleActivateApp(window_imp, activating); break; @@ -2182,6 +2191,7 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_NCLBUTTONDOWN"); // A click in a non-client area, e.g. title bar or window border. sHandleLeftMouseUp = false; + sHandleDoubleClick = true; } break; @@ -2226,6 +2236,13 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ //case WM_RBUTTONDBLCLK: { window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_LBUTTONDBLCLK"); + + if (!sHandleDoubleClick) + { + sHandleDoubleClick = true; + break; + } + // Because we move the cursor position in the app, we need to query // to find out where the cursor at the time the event is handled. // If we don't do this, many clicks could get buffered up, and if the -- cgit v1.2.3 From f4ef763eeccccedea4b810cf5da161d346bb8f37 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 12 Mar 2014 20:01:53 +0200 Subject: MAINT-2726 FIXED confirm before sharing items flag not working if sharing a folder merged InventoryCategory processing with other objects. Removed one of explicit GiveAcceptable checks (there were three, one per step). --- indra/newview/lltooldraganddrop.cpp | 90 +++++++++++++++---------------------- 1 file changed, 37 insertions(+), 53 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 7314ab60c1..ece30d2d0a 100755 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1584,13 +1584,22 @@ static void give_inventory_cb(const LLSD& notification, const LLSD& response) const LLUUID& session_id = payload["session_id"]; const LLUUID& agent_id = payload["agent_id"]; LLViewerInventoryItem * inv_item = gInventory.getItem(payload["item_id"]); - if (NULL == inv_item) + LLViewerInventoryCategory * inv_cat = gInventory.getCategory(payload["item_id"]); + if (NULL == inv_item && NULL == inv_cat) { - llassert(NULL != inv_item); + llassert( FALSE ); return; } - - if (LLGiveInventory::doGiveInventoryItem(agent_id, inv_item, session_id)) + bool successfully_shared; + if (inv_item) + { + successfully_shared = LLGiveInventory::doGiveInventoryItem(agent_id, inv_item, session_id); + } + else + { + successfully_shared = LLGiveInventory::doGiveInventoryCategory(agent_id, inv_cat, session_id); + } + if (successfully_shared) { if ("avatarpicker" == payload["d&d_dest"].asString()) { @@ -1600,8 +1609,8 @@ static void give_inventory_cb(const LLSD& notification, const LLSD& response) } } -static void show_item_sharing_confirmation(const std::string name, - LLViewerInventoryItem* inv_item, +static void show_object_sharing_confirmation(const std::string name, + LLInventoryObject* inv_item, const LLSD& dest, const LLUUID& dest_agent, const LLUUID& session_id = LLUUID::null) @@ -1611,32 +1620,28 @@ static void show_item_sharing_confirmation(const std::string name, llassert(NULL != inv_item); return; } - if(gInventory.getItem(inv_item->getUUID()) - && LLGiveInventory::isInventoryGiveAcceptable(inv_item)) - { - LLSD substitutions; - substitutions["RESIDENTS"] = name; - substitutions["ITEMS"] = inv_item->getName(); - LLSD payload; - payload["agent_id"] = dest_agent; - payload["item_id"] = inv_item->getUUID(); - payload["session_id"] = session_id; - payload["d&d_dest"] = dest.asString(); - LLNotificationsUtil::add("ShareItemsConfirmation", substitutions, payload, &give_inventory_cb); - } + LLSD substitutions; + substitutions["RESIDENTS"] = name; + substitutions["ITEMS"] = inv_item->getName(); + LLSD payload; + payload["agent_id"] = dest_agent; + payload["item_id"] = inv_item->getUUID(); + payload["session_id"] = session_id; + payload["d&d_dest"] = dest.asString(); + LLNotificationsUtil::add("ShareItemsConfirmation", substitutions, payload, &give_inventory_cb); } static void get_name_cb(const LLUUID& id, const std::string& full_name, - LLViewerInventoryItem* inv_item, + LLInventoryObject* inv_obj, const LLSD& dest, const LLUUID& dest_agent) { - show_item_sharing_confirmation(full_name, - inv_item, - dest, - id, - LLUUID::null); + show_object_sharing_confirmation(full_name, + inv_obj, + dest, + id, + LLUUID::null); } // function used as drag-and-drop handler for simple agent give inventory requests @@ -1662,10 +1667,11 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_ case DAD_GESTURE: case DAD_CALLINGCARD: case DAD_MESH: + case DAD_CATEGORY: { - LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data; - if(gInventory.getItem(inv_item->getUUID()) - && LLGiveInventory::isInventoryGiveAcceptable(inv_item)) + LLInventoryObject* inv_obj = (LLInventoryObject*)cargo_data; + if(gInventory.getCategory(inv_obj->getUUID()) || (gInventory.getItem(inv_obj->getUUID()) + && LLGiveInventory::isInventoryGiveAcceptable(dynamic_cast(inv_obj)))) { // *TODO: get multiple object transfers working *accept = ACCEPT_YES_COPY_SINGLE; @@ -1682,40 +1688,18 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_ // Otherwise set up a callback to show the dialog when the name arrives. if (gCacheName->getFullName(dest_agent, fullname)) { - show_item_sharing_confirmation(fullname, inv_item, dest, dest_agent, LLUUID::null); + show_object_sharing_confirmation(fullname, inv_obj, dest, dest_agent, LLUUID::null); } else { - gCacheName->get(dest_agent, false, boost::bind(&get_name_cb, _1, _2, inv_item, dest, dest_agent)); + gCacheName->get(dest_agent, false, boost::bind(&get_name_cb, _1, _2, inv_obj, dest, dest_agent)); } return true; } // If an IM session with destination agent is found item offer will be logged in this session. - show_item_sharing_confirmation(session->mName, inv_item, dest, dest_agent, session_id); - } - } - else - { - // It's not in the user's inventory (it's probably - // in an object's contents), so disallow dragging - // it here. You can't give something you don't - // yet have. - *accept = ACCEPT_NO; - } - break; - } - case DAD_CATEGORY: - { - LLViewerInventoryCategory* inv_cat = (LLViewerInventoryCategory*)cargo_data; - if( gInventory.getCategory( inv_cat->getUUID() ) ) - { - // *TODO: get multiple object transfers working - *accept = ACCEPT_YES_COPY_SINGLE; - if(drop) - { - LLGiveInventory::doGiveInventoryCategory(dest_agent, inv_cat, session_id); + show_object_sharing_confirmation(session->mName, inv_obj, dest, dest_agent, session_id); } } else -- cgit v1.2.3 From da2fc5b6f6458add830182195ae533e4328822fc Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Fri, 14 Mar 2014 11:55:24 +0200 Subject: MAINT-3821 FIXED Call setUseUsernames on start up. --- indra/newview/llstartup.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra') diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index d5f8a1e46e..a5fdb72f9b 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2822,6 +2822,7 @@ void LLStartUp::initNameCache() // capabilities for display name lookup LLAvatarNameCache::initClass(false,gSavedSettings.getBOOL("UsePeopleAPI")); LLAvatarNameCache::setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames")); + LLAvatarNameCache::setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); } void LLStartUp::cleanupNameCache() -- cgit v1.2.3 From 09d1c27d4f78c78d949b6a3d896d6f58df2dfc06 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Fri, 14 Mar 2014 12:21:25 +0200 Subject: MAINT-3822 FIXED Show busy mode message only once for each im session. --- indra/newview/llagent.cpp | 1 + indra/newview/llimview.cpp | 33 +++++++++++++++++++++++++++++++++ indra/newview/llimview.h | 8 ++++++++ indra/newview/llviewermessage.cpp | 13 +++++++++---- 4 files changed, 51 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index f150ceda67..7a93a95ebf 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -1466,6 +1466,7 @@ void LLAgent::setDoNotDisturb(bool pIsDoNotDisturb) { LLDoNotDisturbNotificationStorage::getInstance()->updateNotifications(); } + gIMMgr->updateDNDMessageStatus(); } //----------------------------------------------------------------------------- diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 70ffdc14ff..d55922af93 100755 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -409,6 +409,7 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& mOtherParticipantIsAvatar(true), mStartCallOnInitialize(false), mStartedAsIMCall(voice), + mIsDNDsend(false), mAvatarNameCacheConnection() { // set P2P type by default @@ -3306,6 +3307,38 @@ bool LLIMMgr::isVoiceCall(const LLUUID& session_id) return im_session->mStartedAsIMCall; } +void LLIMMgr::updateDNDMessageStatus() +{ + if (LLIMModel::getInstance()->mId2SessionMap.empty()) return; + + std::map::const_iterator it = LLIMModel::getInstance()->mId2SessionMap.begin(); + for (; it != LLIMModel::getInstance()->mId2SessionMap.end(); ++it) + { + LLIMModel::LLIMSession* session = (*it).second; + + if (session->isP2P()) + { + setDNDMessageSent(session->mSessionID,false); + } + } +} + +bool LLIMMgr::isDNDMessageSend(const LLUUID& session_id) +{ + LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id); + if (!im_session) return false; + + return im_session->mIsDNDsend; +} + +void LLIMMgr::setDNDMessageSent(const LLUUID& session_id, bool is_send) +{ + LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(session_id); + if (!im_session) return; + + im_session->mIsDNDsend = is_send; +} + void LLIMMgr::addNotifiedNonFriendSessionID(const LLUUID& session_id) { mNotifiedNonFriendSessions.insert(session_id); diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index da6039a3ae..4270304de9 100755 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -140,6 +140,8 @@ public: bool mHasOfflineMessage; + bool mIsDNDsend; + private: void onAdHocNameCache(const LLAvatarName& av_name); @@ -443,6 +445,12 @@ public: bool isVoiceCall(const LLUUID& session_id); + void updateDNDMessageStatus(); + + bool isDNDMessageSend(const LLUUID& session_id); + + void setDNDMessageSent(const LLUUID& session_id, bool is_send); + void addNotifiedNonFriendSessionID(const LLUUID& session_id); bool isNonFriendSessionNotified(const LLUUID& session_id); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index df5c7d5c2e..160f924f3f 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -2409,10 +2409,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) && from_id.notNull() //not a system message && to_id.notNull()) //not global message { - // return a standard "do not disturb" message, but only do it to online IM - // (i.e. not other auto responses and not store-and-forward IM) - - send_do_not_disturb_message(msg, from_id, session_id); // now store incoming IM in chat history @@ -2433,6 +2429,15 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) region_id, position, true); + + if (!gIMMgr->isDNDMessageSend(session_id)) + { + // return a standard "do not disturb" message, but only do it to online IM + // (i.e. not other auto responses and not store-and-forward IM) + send_do_not_disturb_message(msg, from_id, session_id); + gIMMgr->setDNDMessageSent(session_id, true); + } + } else if (from_id.isNull()) { -- cgit v1.2.3 From 559a0229a16ada062a3a5204507adde9a1e70748 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Fri, 14 Mar 2014 16:48:46 +0200 Subject: MAINT-2325 FIXED For sale mark is visible partially in Place profile --- indra/newview/skins/default/xui/en/panel_place_profile.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml index 308acf0c0c..66588ce94e 100755 --- a/indra/newview/skins/default/xui/en/panel_place_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml @@ -220,7 +220,7 @@ -- cgit v1.2.3 From d9a3eb063271abeec6b437730328fe4a6b1b81f2 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Mon, 17 Mar 2014 11:39:22 +0200 Subject: MAINT-2176 FIXED Maturity icon is added --- indra/newview/llpanelplaceprofile.cpp | 5 +++++ indra/newview/llpanelplaceprofile.h | 1 + indra/newview/skins/default/xui/en/panel_place_profile.xml | 10 +++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index 14b5d9af47..3b8acdca90 100755 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -129,6 +129,7 @@ BOOL LLPanelPlaceProfile::postBuild() mEstateNameText = getChild("estate_name"); mEstateRatingText = getChild("estate_rating"); + mEstateRatingIcon = getChild("estate_rating_icon"); mEstateOwnerText = getChild("estate_owner"); mCovenantText = getChild("covenant"); @@ -201,6 +202,7 @@ void LLPanelPlaceProfile::resetLocation() mEstateNameText->setValue(loading); mEstateRatingText->setValue(loading); + mEstateRatingIcon->setValue(loading); mEstateOwnerText->setValue(loading); mCovenantText->setValue(loading); @@ -348,6 +350,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, mParcelRatingIcon->setValue(icon_m); mRegionRatingIcon->setValue(icon_m); + mEstateRatingIcon->setValue(icon_m); break; case SIM_ACCESS_ADULT: @@ -355,6 +358,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, mParcelRatingIcon->setValue(icon_r); mRegionRatingIcon->setValue(icon_r); + mEstateRatingIcon->setValue(icon_r); break; default: @@ -362,6 +366,7 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, mParcelRatingIcon->setValue(icon_pg); mRegionRatingIcon->setValue(icon_pg); + mEstateRatingIcon->setValue(icon_pg); } std::string rating = LLViewerRegion::accessToString(sim_access); diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h index f4c6145881..ff24938b9c 100755 --- a/indra/newview/llpanelplaceprofile.h +++ b/indra/newview/llpanelplaceprofile.h @@ -103,6 +103,7 @@ private: LLTextBox* mEstateNameText; LLTextBox* mEstateRatingText; + LLIconCtrl* mEstateRatingIcon; LLTextBox* mEstateOwnerText; LLTextEditor* mCovenantText; diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml index 66588ce94e..30239d6d01 100755 --- a/indra/newview/skins/default/xui/en/panel_place_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml @@ -762,11 +762,19 @@ top_pad="5" value="Rating:" width="80" /> + -- cgit v1.2.3 From abf5d5b36083d4f1d94674e456750838ae683157 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Fri, 14 Mar 2014 21:15:18 +0200 Subject: MAINT-3426 FIXED Searching inventory for "online" no longer returns online friends calling cards in search results. --- indra/newview/llinventorybridge.cpp | 42 +++++++++++++++++++++++++++++++++++++ indra/newview/llinventorybridge.h | 1 + 2 files changed, 43 insertions(+) (limited to 'indra') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 44943d8722..101b16b027 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4708,6 +4708,10 @@ public: virtual void changed(U32 mask) { mBridgep->refreshFolderViewItem(); + if (mask & LLFriendObserver::ONLINE) + { + mBridgep->checkSearchBySuffixChanges(); + } } protected: LLCallingCardBridge* mBridgep; @@ -4742,6 +4746,44 @@ void LLCallingCardBridge::refreshFolderViewItem() } } +void LLCallingCardBridge::checkSearchBySuffixChanges() +{ + if (!mDisplayName.empty()) + { + // changes in mDisplayName are processed by rename function and here it will be always same + // suffixes are also of fixed length, and we are processing change of one at a time, + // so it should be safe to use length (note: mSearchableName is capitalized) + S32 old_length = mSearchableName.length(); + S32 new_length = mDisplayName.length() + getLabelSuffix().length(); + if (old_length == new_length) + { + return; + } + mSearchableName.assign(mDisplayName); + mSearchableName.append(getLabelSuffix()); + LLStringUtil::toUpper(mSearchableName); + if (new_lengthgetFilterSubString()) == std::string::npos) + { + // string no longer contains substring + // we either have to update all parents manually or restart filter. + // dirtyFilter will not work here due to obsolete descendants' generations + getInventoryFilter()->setModified(LLFolderViewFilter::FILTER_MORE_RESTRICTIVE); + } + } + else + { + if (getInventoryFilter()) + { + // mSearchableName became longer, we gained additional suffix and need to repeat filter check. + dirtyFilter(); + } + } + } +} + // virtual void LLCallingCardBridge::performAction(LLInventoryModel* model, std::string action) { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index bc875e8f37..b29235260b 100755 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -419,6 +419,7 @@ public: void* cargo_data, std::string& tooltip_msg); void refreshFolderViewItem(); + void checkSearchBySuffixChanges(); protected: LLCallingCardObserver* mObserver; }; -- cgit v1.2.3 From c73d3073040d7f9731fd94eb51499d90fad6572a Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Tue, 18 Mar 2014 11:48:14 +0200 Subject: MAINT-1744 FIXED User cannot unblock an object by selecting "Unblock" menu item from object's pop-up menu --- indra/newview/lltoolpie.cpp | 12 +----------- indra/newview/skins/default/xui/en/menu_object.xml | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 17 deletions(-) (limited to 'indra') diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index 1c362c18e0..a09a2739e8 100755 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -1671,17 +1671,7 @@ BOOL LLToolPie::handleRightClickPick() { name = node->mName; } - std::string mute_msg; - if (LLMuteList::getInstance()->isMuted(object->getID(), name)) - { - mute_msg = LLTrans::getString("UnmuteObject"); - } - else - { - mute_msg = LLTrans::getString("MuteObject2"); - } - - gMenuHolder->getChild("Object Mute")->setValue(mute_msg); + gMenuObject->show(x, y); showVisualContextMenuEffect(); diff --git a/indra/newview/skins/default/xui/en/menu_object.xml b/indra/newview/skins/default/xui/en/menu_object.xml index 52ab7da515..5c98a98d3d 100755 --- a/indra/newview/skins/default/xui/en/menu_object.xml +++ b/indra/newview/skins/default/xui/en/menu_object.xml @@ -130,16 +130,23 @@ function="Object.ReportAbuse" /> - + - + - + + + + Date: Tue, 18 Mar 2014 17:11:39 +0200 Subject: MAINT-2578 FIXED Resident can add nonexistent resident to IM or add-hoc conference in "Choose resident" floater --- indra/newview/llfloateravatarpicker.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index c0afb72cff..1b0e73409b 100755 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -795,7 +795,7 @@ bool LLFloaterAvatarPicker::isSelectBtnEnabled() { bool ret_val = visibleItemsSelected(); - if ( ret_val && mOkButtonValidateSignal.num_slots() ) + if ( ret_val ) { std::string acvtive_panel_name; LLScrollListCtrl* list = NULL; @@ -826,7 +826,7 @@ bool LLFloaterAvatarPicker::isSelectBtnEnabled() getSelectedAvatarData(list, avatar_ids, avatar_names); if (avatar_ids.size() >= 1) { - ret_val = mOkButtonValidateSignal(avatar_ids); + ret_val = mOkButtonValidateSignal.num_slots()?mOkButtonValidateSignal(avatar_ids):true; } else { -- cgit v1.2.3 From f023c677782168cdd48af8e897900f0dfef9fba8 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Tue, 18 Mar 2014 14:05:41 -0500 Subject: MAINT-3832 Make color pickers actually apply result immediately when "apply immediately" is checked. --- indra/newview/llcolorswatch.h | 3 +++ indra/newview/llfloatercolorpicker.cpp | 14 ++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llcolorswatch.h b/indra/newview/llcolorswatch.h index 5bdd1712d2..b3b6cfe32d 100755 --- a/indra/newview/llcolorswatch.h +++ b/indra/newview/llcolorswatch.h @@ -59,6 +59,7 @@ public: Optional alpha_background_image; Optional cancel_callback; Optional select_callback; + Optional preview_callback; Optional border_color; Optional label_width; Optional label_height; @@ -87,6 +88,7 @@ public: void setCanApplyImmediately(BOOL apply) { mCanApplyImmediately = apply; } void setOnCancelCallback(commit_callback_t cb) { mOnCancelCallback = cb; } void setOnSelectCallback(commit_callback_t cb) { mOnSelectCallback = cb; } + void setPreviewCallback(commit_callback_t cb) { mPreviewCallback = cb; } void setFallbackImageName(const std::string& name) { mFallbackImageName = name; } void showPicker(BOOL take_focus); @@ -112,6 +114,7 @@ protected: BOOL mCanApplyImmediately; commit_callback_t mOnCancelCallback; commit_callback_t mOnSelectCallback; + commit_callback_t mPreviewCallback; S32 mLabelWidth; S32 mLabelHeight; diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index a03425649f..7ba7660f19 100755 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -347,6 +347,11 @@ void LLFloaterColorPicker::setCurRgb ( F32 curRIn, F32 curGIn, F32 curBIn ) curG = curGIn; curB = curBIn; + if (mApplyImmediateCheck->get()) + { + LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE ); + } + // update corresponding HSL values and LLColor3(curRIn, curGIn, curBIn).calcHSL(&curH, &curS, &curL); @@ -374,6 +379,11 @@ void LLFloaterColorPicker::setCurHsl ( F32 curHIn, F32 curSIn, F32 curLIn ) // update corresponding RGB values and hslToRgb ( curH, curS, curL, curR, curG, curB ); + + if (mApplyImmediateCheck->get()) + { + LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE ); + } } ////////////////////////////////////////////////////////////////////////////// @@ -463,10 +473,6 @@ void LLFloaterColorPicker::onImmediateCheck( LLUICtrl* ctrl, void* data) void LLFloaterColorPicker::onColorSelect( const LLTextureEntry& te ) { setCurRgb(te.getColor().mV[VRED], te.getColor().mV[VGREEN], te.getColor().mV[VBLUE]); - if (mApplyImmediateCheck->get()) - { - LLColorSwatchCtrl::onColorChanged ( getSwatch (), LLColorSwatchCtrl::COLOR_CHANGE ); - } } void LLFloaterColorPicker::onMouseCaptureLost() -- cgit v1.2.3 From 1ab9f19f82a84a109cf429998f423986268801f6 Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Wed, 19 Mar 2014 12:05:56 +0200 Subject: MAINT-3838 FIXED Get escaped uri for location link. --- indra/newview/llviewermenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 59e98fc882..ab9551ad17 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7825,7 +7825,7 @@ void handle_report_bug(const LLSD& param) replace["[ENVIRONMENT]"] = LLURI::escape(LLAppViewer::instance()->getViewerInfoString()); LLSLURL location_url; LLAgentUI::buildSLURL(location_url); - replace["[LOCATION]"] = location_url.getSLURLString(); + replace["[LOCATION]"] = LLURI::escape(location_url.getSLURLString()); LLUIString file_bug_url = gSavedSettings.getString("ReportBugURL"); file_bug_url.setArgs(replace); -- cgit v1.2.3 From e9266f6f063584c86b9f7eb4ab83549868f148ba Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 31 Mar 2014 16:38:31 +0300 Subject: MAINT-1696 FIXED "Owner" name is not clickable in "Place Profile" dialog if region is group owned --- indra/newview/llpanelplaceprofile.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index e501486ecb..d3a7f9bb75 100755 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -483,8 +483,9 @@ void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel, gCacheName->getGroup(parcel->getGroupID(), boost::bind(&LLPanelPlaceInfo::onNameCache, mRegionGroupText, _2)); - gCacheName->getGroup(parcel->getGroupID(), - boost::bind(&LLPanelPlaceInfo::onNameCache, mParcelOwner, _2)); + std::string owner = + LLSLURL("group", parcel->getGroupID(), "inspect").getSLURLString(); + mParcelOwner->setText(owner); } else { -- cgit v1.2.3 From 33e28d6223e4f27c9b8e5a563e749979dad3a1fd Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 9 Apr 2014 17:06:19 -0700 Subject: MAINT-2034 : Terrain texture changes caused by changing texture elevation ranges or terraforming can not be seen until after relog or teleporting out and back to the region --- indra/newview/llviewerregion.cpp | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index a271690349..7d16a9664b 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1523,40 +1523,69 @@ void LLViewerRegion::unpackRegionHandshake() { LLUUID tmp_id; + bool changed = false; + + // Get the 4 textures for land msg->getUUID("RegionInfo", "TerrainDetail0", tmp_id); + changed |= (tmp_id != compp->getDetailTextureID(0)); compp->setDetailTextureID(0, tmp_id); + msg->getUUID("RegionInfo", "TerrainDetail1", tmp_id); + changed |= (tmp_id != compp->getDetailTextureID(1)); compp->setDetailTextureID(1, tmp_id); + msg->getUUID("RegionInfo", "TerrainDetail2", tmp_id); + changed |= (tmp_id != compp->getDetailTextureID(2)); compp->setDetailTextureID(2, tmp_id); + msg->getUUID("RegionInfo", "TerrainDetail3", tmp_id); + changed |= (tmp_id != compp->getDetailTextureID(3)); compp->setDetailTextureID(3, tmp_id); + // Get the start altitude and range values for land textures F32 tmp_f32; msg->getF32("RegionInfo", "TerrainStartHeight00", tmp_f32); + changed |= (tmp_f32 != compp->getStartHeight(0)); compp->setStartHeight(0, tmp_f32); + msg->getF32("RegionInfo", "TerrainStartHeight01", tmp_f32); + changed |= (tmp_f32 != compp->getStartHeight(1)); compp->setStartHeight(1, tmp_f32); + msg->getF32("RegionInfo", "TerrainStartHeight10", tmp_f32); + changed |= (tmp_f32 != compp->getStartHeight(2)); compp->setStartHeight(2, tmp_f32); + msg->getF32("RegionInfo", "TerrainStartHeight11", tmp_f32); + changed |= (tmp_f32 != compp->getStartHeight(3)); compp->setStartHeight(3, tmp_f32); + msg->getF32("RegionInfo", "TerrainHeightRange00", tmp_f32); + changed |= (tmp_f32 != compp->getHeightRange(0)); compp->setHeightRange(0, tmp_f32); + msg->getF32("RegionInfo", "TerrainHeightRange01", tmp_f32); + changed |= (tmp_f32 != compp->getHeightRange(1)); compp->setHeightRange(1, tmp_f32); + msg->getF32("RegionInfo", "TerrainHeightRange10", tmp_f32); + changed |= (tmp_f32 != compp->getHeightRange(2)); compp->setHeightRange(2, tmp_f32); + msg->getF32("RegionInfo", "TerrainHeightRange11", tmp_f32); + changed |= (tmp_f32 != compp->getHeightRange(3)); compp->setHeightRange(3, tmp_f32); // If this is an UPDATE (params already ready, we need to regenerate // all of our terrain stuff, by if (compp->getParamsReady()) { - //this line creates frame stalls on region crossing and removing it appears to have no effect - //getLand().dirtyAllPatches(); + // Update if the land changed + if (changed) + { + getLand().dirtyAllPatches(); + } } else { -- cgit v1.2.3 From e10d5238d651f46b6efbf6eb5dbee3e0a755adec Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Mon, 28 Apr 2014 11:48:11 +0300 Subject: MAINT-3957 FIXED Group owner issue --- indra/newview/llpanelgrouproles.cpp | 24 ++++++++++++++---------- indra/newview/llpanelgrouproles.h | 3 +++ 2 files changed, 17 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 256f12a796..2fcaa5666e 100755 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -427,7 +427,7 @@ void LLPanelGroupRoles::setGroupID(const LLUUID& id) if(mSubTabContainer) mSubTabContainer->selectTab(1); - + group_roles_tab->mFirstOpen = TRUE; activate(); } @@ -1825,7 +1825,7 @@ LLPanelGroupRolesSubTab::LLPanelGroupRolesSubTab() mMemberVisibleCheck(NULL), mDeleteRoleButton(NULL), mCreateRoleButton(NULL), - + mFirstOpen(TRUE), mHasRoleChange(FALSE) { } @@ -1927,6 +1927,7 @@ void LLPanelGroupRolesSubTab::deactivate() LL_DEBUGS() << "LLPanelGroupRolesSubTab::deactivate()" << LL_ENDL; LLPanelGroupSubTab::deactivate(); + mFirstOpen = FALSE; } bool LLPanelGroupRolesSubTab::needsApply(std::string& mesg) @@ -1950,7 +1951,7 @@ bool LLPanelGroupRolesSubTab::apply(std::string& mesg) LL_DEBUGS() << "LLPanelGroupRolesSubTab::apply()" << LL_ENDL; saveRoleChanges(true); - + mFirstOpen = FALSE; LLGroupMgr::getInstance()->sendGroupRoleChanges(mGroupID); notifyObservers(); @@ -2087,14 +2088,17 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc) } } - if (!gdatap || !gdatap->isMemberDataComplete()) - { - LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); - } - - if (!gdatap || !gdatap->isRoleMemberDataComplete()) + if(!mFirstOpen) { - LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID); + if (!gdatap || !gdatap->isMemberDataComplete()) + { + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); + } + + if (!gdatap || !gdatap->isRoleMemberDataComplete()) + { + LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID); + } } if ((GC_ROLE_MEMBER_DATA == gc || GC_MEMBER_DATA == gc) diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index 26f1dff007..052f1d2071 100755 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -268,6 +268,9 @@ public: void saveRoleChanges(bool select_saved_role); virtual void setGroupID(const LLUUID& id); + + BOOL mFirstOpen; + protected: void handleActionCheck(LLUICtrl* ctrl, bool force); LLSD createRoleItem(const LLUUID& role_id, std::string name, std::string title, S32 members); -- cgit v1.2.3 From efc9422d1b87f2ccf191acde107652102ebf95d0 Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Thu, 29 May 2014 03:24:13 +0300 Subject: MAINT-3351 FIXED Misleading failure message when user is successfully removed from a group's Owners role --- indra/newview/llgroupmgr.cpp | 5 +++++ indra/newview/llgroupmgr.h | 2 ++ indra/newview/llpanelgroup.cpp | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+) (limited to 'indra') diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 83ce2b0483..081f47df41 100755 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -611,6 +611,11 @@ void LLGroupMgrGroupData::recalcAgentPowers(const LLUUID& agent_id) } } +bool LLGroupMgrGroupData::isSingleMemberNotOwner() +{ + return mMembers.size() == 1 && !mMembers.begin()->second->isOwner(); +} + bool packRoleUpdateMessageBlock(LLMessageSystem* msg, const LLUUID& group_id, const LLUUID& role_id, diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index 9e1c1eec90..2b4c9700be 100755 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -254,6 +254,8 @@ public: bool isRoleMemberDataComplete() { return mRoleMemberDataComplete; } bool isGroupPropertiesDataComplete() { return mGroupPropertiesDataComplete; } + bool isSingleMemberNotOwner(); + F32 getAccessTime() const { return mAccessTime; } void setAccessed(); diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index bf332d1ca7..f4aab6bd4e 100755 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -49,6 +49,7 @@ #include "llpanelgroupnotices.h" #include "llpanelgroupgeneral.h" +#include "llpanelgrouproles.h" #include "llaccordionctrltab.h" #include "llaccordionctrl.h" @@ -275,6 +276,7 @@ void LLPanelGroup::onBtnApply(void* user_data) { LLPanelGroup* self = static_cast(user_data); self->apply(); + self->refreshData(); } void LLPanelGroup::onBtnGroupCallClicked(void* user_data) @@ -497,6 +499,22 @@ bool LLPanelGroup::apply(LLPanelGroupTab* tab) { //we skip refreshing group after ew manually apply changes since its very annoying //for those who are editing group + + LLPanelGroupRoles * roles_tab = dynamic_cast(tab); + if (roles_tab) + { + LLGroupMgr* gmgrp = LLGroupMgr::getInstance(); + LLGroupMgrGroupData* gdatap = gmgrp->getGroupData(roles_tab->getGroupID()); + + // allow refresh only for one specific case: + // there is only one member in group and it is not owner + // it's a wrong situation and need refresh panels from server + if (gdatap && gdatap->isSingleMemberNotOwner()) + { + return true; + } + } + mSkipRefresh = TRUE; return true; } -- cgit v1.2.3 From f0eb544148456f05bd1c6390542192911df32364 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 4 Jun 2014 18:38:01 +0300 Subject: MAINT-3386 FIXED [vwr] Banned Agents list does not show newly-banned residents --- indra/newview/llgroupmgr.cpp | 38 ++++++++++++++++++++++++++++++----- indra/newview/llgroupmgr.h | 5 +++-- indra/newview/llpanelgroupbulkban.cpp | 2 +- 3 files changed, 37 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 081f47df41..0801568a93 100755 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -1866,12 +1866,20 @@ void LLGroupMgr::sendGroupMemberEjects(const LLUUID& group_id, class GroupBanDataResponder : public LLHTTPClient::Responder { public: - GroupBanDataResponder() {} + GroupBanDataResponder(const LLUUID& gropup_id, BOOL force_refresh=false); virtual ~GroupBanDataResponder() {} virtual void result(const LLSD& pContent); virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); +private: + LLUUID mGroupID; + BOOL mForceRefresh; }; +GroupBanDataResponder::GroupBanDataResponder(const LLUUID& gropup_id, BOOL force_refresh) : + mGroupID(gropup_id), + mForceRefresh(force_refresh) +{} + void GroupBanDataResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) { LL_WARNS("GrpMgr") << "Error receiving group member data [status:" @@ -1880,12 +1888,32 @@ void GroupBanDataResponder::errorWithContent(U32 pStatus, const std::string& pRe void GroupBanDataResponder::result(const LLSD& content) { - LLGroupMgr::processGroupBanRequest(content); + if ( content.size()) + { + if (content.has("ban_list")) + { + // group data received + LLGroupMgr::processGroupBanRequest(content); + } + // no group data received, this is either CREATE or DELETE operation + // complete confirmation. Local data may be obsolete. + else if (mForceRefresh) + { + // providing mGroupId and not extracting it from content since it is not + // included into CREATE and DELETE responses + LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID); + } + } + else + { + LL_WARNS("GrpMgr") << "No group member data received." << LL_ENDL; + return; + } } void LLGroupMgr::sendGroupBanRequest( EBanRequestType request_type, const LLUUID& group_id, - EBanRequestAction ban_action, /* = BAN_NO_ACTION */ + U32 ban_action, /* = BAN_NO_ACTION */ const std::vector ban_list) /* = std::vector() */ { LLViewerRegion* currentRegion = gAgent.getRegion(); @@ -1911,7 +1939,7 @@ void LLGroupMgr::sendGroupBanRequest( EBanRequestType request_type, cap_url += "?group_id=" + group_id.asString(); LLSD body = LLSD::emptyMap(); - body["ban_action"] = ban_action; + body["ban_action"] = (LLSD::Integer)(ban_action & ~BAN_UPDATE); // Add our list of potential banned residents to the list body["ban_ids"] = LLSD::emptyArray(); LLSD ban_entry; @@ -1923,7 +1951,7 @@ void LLGroupMgr::sendGroupBanRequest( EBanRequestType request_type, body["ban_ids"].append(ban_entry); } - LLHTTPClient::ResponderPtr grp_ban_responder = new GroupBanDataResponder(); + LLHTTPClient::ResponderPtr grp_ban_responder = new GroupBanDataResponder(group_id, ban_action & BAN_UPDATE); switch(request_type) { case REQUEST_GET: diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index 2b4c9700be..970d6d5a2d 100755 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -356,7 +356,8 @@ public: { BAN_NO_ACTION = 0, BAN_CREATE = 1, - BAN_DELETE = 2 + BAN_DELETE = 2, + BAN_UPDATE = 4 }; public: @@ -395,7 +396,7 @@ public: static void sendGroupBanRequest(EBanRequestType request_type, const LLUUID& group_id, - EBanRequestAction ban_action = BAN_NO_ACTION, + U32 ban_action = BAN_NO_ACTION, const uuid_vec_t ban_list = uuid_vec_t()); static void processGroupBanRequest(const LLSD& content); diff --git a/indra/newview/llpanelgroupbulkban.cpp b/indra/newview/llpanelgroupbulkban.cpp index 5b9dc21f20..0b57233f47 100644 --- a/indra/newview/llpanelgroupbulkban.cpp +++ b/indra/newview/llpanelgroupbulkban.cpp @@ -136,7 +136,7 @@ void LLPanelGroupBulkBan::submit() return; } - LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mImplementation->mGroupID, LLGroupMgr::BAN_CREATE, banned_agent_list); + LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mImplementation->mGroupID, LLGroupMgr::BAN_CREATE | LLGroupMgr::BAN_UPDATE, banned_agent_list); LLGroupMgr::getInstance()->sendGroupMemberEjects(mImplementation->mGroupID, banned_agent_list); //then close -- cgit v1.2.3 From a0b31c3145b25c1267954dd42d2afa916e5fa046 Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Fri, 6 Jun 2014 07:41:01 +0300 Subject: MAINT-3389 FIXED [vwr] No visual feedback if you try to ban an already banned agent. --- indra/newview/llpanelgroupbulkban.cpp | 25 ++++++++++++++++++++++ .../skins/default/xui/en/panel_group_bulk_ban.xml | 4 ++++ 2 files changed, 29 insertions(+) (limited to 'indra') diff --git a/indra/newview/llpanelgroupbulkban.cpp b/indra/newview/llpanelgroupbulkban.cpp index 0b57233f47..a31396737d 100644 --- a/indra/newview/llpanelgroupbulkban.cpp +++ b/indra/newview/llpanelgroupbulkban.cpp @@ -48,6 +48,7 @@ #include "lluictrlfactory.h" #include "llviewerwindow.h" +#include LLPanelGroupBulkBan::LLPanelGroupBulkBan(const LLUUID& group_id) : LLPanelGroupBulk(group_id) { @@ -136,6 +137,30 @@ void LLPanelGroupBulkBan::submit() return; } + LLGroupMgrGroupData * group_datap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID); + if (group_datap) + { + BOOST_FOREACH(const LLGroupMgrGroupData::ban_list_t::value_type& group_ban_pair, group_datap->mBanList) + { + const LLUUID& group_ban_agent_id = group_ban_pair.first; + if (std::find(banned_agent_list.begin(), banned_agent_list.end(), group_ban_agent_id) != banned_agent_list.end()) + { + // Fail! + LLAvatarName av_name; + LLAvatarNameCache::get(group_ban_agent_id, &av_name); + + LLStringUtil::format_map_t string_args; + string_args["[RESIDENT]"] = av_name.getDisplayName(); + + LLSD msg; + msg["MESSAGE"] = getString("already_banned", string_args); + LLNotificationsUtil::add("GenericAlert", msg); + (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData); + return; + } + } + } + LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mImplementation->mGroupID, LLGroupMgr::BAN_CREATE | LLGroupMgr::BAN_UPDATE, banned_agent_list); LLGroupMgr::getInstance()->sendGroupMemberEjects(mImplementation->mGroupID, banned_agent_list); 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 index 8dd2719926..43449df1fd 100644 --- a/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml +++ b/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml @@ -15,6 +15,10 @@ name="ban_selection_too_large"> Group bans not sent: too many Residents selected. Group bans are limited to 100 per request. + + Group Invitations not sent: resident '[RESIDENT]' already banned. + Date: Tue, 10 Jun 2014 20:11:30 +0300 Subject: Import llpanelgroupinvite from viewer_lion --- indra/newview/llpanelgroupinvite.cpp | 685 +++++++++++++++++++++++++++-------- indra/newview/llpanelgroupinvite.h | 29 +- 2 files changed, 543 insertions(+), 171 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index f3833ed6e4..a9a3c686a6 100755 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -26,8 +26,6 @@ #include "llviewerprecompiledheaders.h" #include "llpanelgroupinvite.h" -#include "llpanelgroupbulk.h" -#include "llpanelgroupbulkimpl.h" #include "llagent.h" #include "llavatarnamecache.h" @@ -47,221 +45,203 @@ #include "lluictrlfactory.h" #include "llviewerwindow.h" - -bool invite_owner_callback(LLHandle panel_handle, const LLSD& notification, const LLSD& response) +class LLPanelGroupInvite::impl { - 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) +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; + std::set mInviteeIDs; + + void (*mCloseCallback)(void* data); + + void* mCloseCallbackUserData; + + boost::signals2::connection mAvatarNameCacheConnection; +}; + + +LLPanelGroupInvite::impl::impl(const LLUUID& group_id): + mGroupID( group_id ), + mLoadingText (), + mInvitees ( NULL ), + mRoleNames( NULL ), + mOKButton ( NULL ), + mRemoveButton( NULL ), + mGroupName( NULL ), + mConfirmedOwnerInvite( false ), + mCloseCallback( NULL ), + mCloseCallbackUserData( NULL ), + mAvatarNameCacheConnection() { - // Pass on construction of this panel to the control factory. - buildFromFile( "panel_group_invite.xml"); } -void LLPanelGroupInvite::clear() +LLPanelGroupInvite::impl::~impl() { - LLPanelGroupBulk::clear(); - - if(mImplementation->mRoleNames) + if (mAvatarNameCacheConnection.connected()) { - mImplementation->mRoleNames->clear(); - mImplementation->mRoleNames->removeall(); - mImplementation->mRoleNames->setCurrentByID(LLUUID::null); + mAvatarNameCacheConnection.disconnect(); } } -void LLPanelGroupInvite::update() -{ - LLPanelGroupBulk::update(); - - if(mImplementation->mRoleNames) - { - LLUUID store_selected_role = mImplementation->mRoleNames->getCurrentID(); - mImplementation->mRoleNames->clear(); - mImplementation->mRoleNames->removeall(); - mImplementation->mRoleNames->setCurrentByID(LLUUID::null); - - if(!mPendingRoleDataUpdate && !mPendingMemberDataUpdate) - { - ////////////////////////////////////////////////////////////////////////// - // Add role names - addRoleNames(); - //////////////////////////////////////////////////////////////////////////// - mImplementation->mRoleNames->setCurrentByID(store_selected_role); - } - else - { - mImplementation->mRoleNames->add(mImplementation->mLoadingText, LLUUID::null, ADD_BOTTOM); - } - - } -} +const S32 MAX_GROUP_INVITES = 100; // Max invites per request. 100 to match server cap. -BOOL LLPanelGroupInvite::postBuild() +void LLPanelGroupInvite::impl::addUsers(const std::vector& names, + const uuid_vec_t& agent_ids) { - BOOL recurse = TRUE; + std::string name; + LLUUID id; - 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 ) + if (names.size() + mInviteeIDs.size() > MAX_GROUP_INVITES) { - mImplementation->mBulkAgentList->setCommitOnSelectionChange(TRUE); - mImplementation->mBulkAgentList->setCommitCallback(LLPanelGroupBulkImpl::callbackSelect, mImplementation); + // Fail! Show a warning and don't add any names. + LLSD msg; + msg["MESSAGE"] = mTooManySelected; + LLNotificationsUtil::add("GenericAlert", msg); + return; } - LLButton* button = getChild("add_button", recurse); - if ( button ) + for (S32 i = 0; i < (S32)names.size(); i++) { - // default to opening avatarpicker automatically - // (*impl::callbackClickAdd)((void*)this); - button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickAdd, this); - } + name = names[i]; + id = agent_ids[i]; - mImplementation->mRemoveButton = - getChild("remove_button", recurse); - if ( mImplementation->mRemoveButton ) - { - mImplementation->mRemoveButton->setClickedCallback(LLPanelGroupBulkImpl::callbackClickRemove, mImplementation); - mImplementation->mRemoveButton->setEnabled(FALSE); - } + // Make sure this agent isn't already in the list. + if (mInviteeIDs.find(id) != mInviteeIDs.end()) + { + continue; + } - mImplementation->mOKButton = getChild("invite_button", recurse); - if ( mImplementation->mOKButton ) - { - mImplementation->mOKButton->setClickedCallback(LLPanelGroupInvite::callbackClickSubmit, this); - mImplementation->mOKButton->setEnabled(FALSE); - } + //add the name to the names list + LLSD row; + row["id"] = id; + row["columns"][0]["value"] = name; - button = getChild("cancel_button", recurse); - if ( button ) - { - button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickCancel, mImplementation); + mInvitees->addElement(row); + mInviteeIDs.insert(id); } - - 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::submit() +void LLPanelGroupInvite::impl::submitInvitations() { std::map role_member_pairs; - LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID); - if(!gdatap) - { - LL_WARNS("Groups") << "Unable to get group data for group " << mImplementation->mGroupID << LL_ENDL; - return; - } + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); // Default to everyone role. LLUUID role_id = LLUUID::null; - if (mImplementation->mRoleNames) + if (mRoleNames) { - role_id = mImplementation->mRoleNames->getCurrentID(); - - //LLUUID t_ownerUUID = gdatap->mOwnerRole; - //bool t_confirmInvite = mImplementation->mConfirmedOwnerInvite; - + role_id = mRoleNames->getCurrentID(); + // owner role: display confirmation and wait for callback - if ((role_id == gdatap->mOwnerRole) && (!mImplementation->mConfirmedOwnerInvite)) + if ((role_id == gdatap->mOwnerRole) && (!mConfirmedOwnerInvite)) { LLSD args; - args["MESSAGE"] = mImplementation->mOwnerWarning; - LLNotificationsUtil::add( "GenericAlertYesCancel", - args, - LLSD(), - boost::bind(invite_owner_callback, - this->getHandle(), - _1, _2)); + args["MESSAGE"] = mOwnerWarning; + LLNotificationsUtil::add("GenericAlertYesCancel", args, LLSD(), boost::bind(&LLPanelGroupInvite::impl::inviteOwnerCallback, this, _1, _2)); return; // we'll be called again if user confirms } } bool already_in_group = false; //loop over the users - std::vector items = mImplementation->mBulkAgentList->getAllData(); + std::vector items = mInvitees->getAllData(); for (std::vector::iterator iter = items.begin(); - iter != items.end(); ++iter) + iter != items.end(); ++iter) { LLScrollListItem* item = *iter; - if(LLGroupActions::isAvatarMemberOfGroup(mImplementation->mGroupID, item->getUUID())) + if(LLGroupActions::isAvatarMemberOfGroup(mGroupID, item->getUUID())) { already_in_group = true; continue; } role_member_pairs[item->getUUID()] = role_id; } - - if (role_member_pairs.size() > LLPanelGroupBulkImpl::MAX_GROUP_INVITES) + + if (role_member_pairs.size() > MAX_GROUP_INVITES) { // Fail! LLSD msg; - msg["MESSAGE"] = mImplementation->mTooManySelected; + msg["MESSAGE"] = mTooManySelected; LLNotificationsUtil::add("GenericAlert", msg); - (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData); + (*mCloseCallback)(mCloseCallbackUserData); return; } - LLGroupMgr::getInstance()->sendGroupMemberInvites(mImplementation->mGroupID, role_member_pairs); - + LLGroupMgr::getInstance()->sendGroupMemberInvites(mGroupID, role_member_pairs); + if(already_in_group) { LLSD msg; - msg["MESSAGE"] = mImplementation->mAlreadyInGroup; + msg["MESSAGE"] = mAlreadyInGroup; LLNotificationsUtil::add("GenericAlert", msg); } //then close - (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData); + (*mCloseCallback)(mCloseCallbackUserData); } -void LLPanelGroupInvite::addRoleNames() +bool LLPanelGroupInvite::impl::inviteOwnerCallback(const LLSD& notification, const LLSD& response) { - LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID); - if(!gdatap) + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + + switch(option) { - return; + 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::member_list_t::iterator agent_iter = gdatap->mMembers.find(gAgent.getID()); + +void LLPanelGroupInvite::impl::addRoleNames(LLGroupMgrGroupData* gdatap) +{ + 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() ) @@ -271,7 +251,7 @@ void LLPanelGroupInvite::addRoleNames() //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 && mImplementation->mRoleNames) + if ( member_data && mRoleNames) { //if the user is the owner then we add //all of the roles in the group @@ -280,11 +260,11 @@ void LLPanelGroupInvite::addRoleNames() //else if they have the limited add to roles power //we add every role the user is in //else we just add to everyone - bool is_owner = member_data->isOwner(); - 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); + 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); LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.begin(); LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end(); @@ -299,18 +279,401 @@ void LLPanelGroupInvite::addRoleNames() // 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 ) { - mImplementation->mRoleNames->add(rd.mRoleName, - role_id, - ADD_BOTTOM); + 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; + + std::vector::iterator iter; + for(iter = selection.begin(); iter != selection.end(); ++iter) + { + mInviteeIDs.erase( (*iter)->getUUID() ); + } + + // Remove all selected invitees. + mInvitees->deleteSelectedItems(); + mRemoveButton->setEnabled(FALSE); +} + +// static +void LLPanelGroupInvite::impl::callbackSelect( + LLUICtrl* ctrl, void* userdata) +{ + impl* selfp = (impl*) userdata; + if ( selfp ) selfp->handleSelection(); +} + +void LLPanelGroupInvite::impl::handleSelection() +{ + // Check if there is anything selected. + std::vector 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); + mImplementation->mInviteeIDs.clear(); +} + +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 b87a5883b8..9f7b5ae9be 100755 --- a/indra/newview/llpanelgroupinvite.h +++ b/indra/newview/llpanelgroupinvite.h @@ -27,27 +27,36 @@ #define LL_LLPANELGROUPINVITE_H #include "llpanel.h" -#include "llpanelgroupbulk.h" #include "lluuid.h" class LLAvatarName; -class LLPanelGroupInvite : public LLPanelGroupBulk +class LLPanelGroupInvite +: public LLPanel { public: LLPanelGroupInvite(const LLUUID& group_id); - ~LLPanelGroupInvite() {}; + ~LLPanelGroupInvite(); - virtual void clear(); - virtual void update(); + 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 BOOL postBuild(); + void setCloseCallback(void (*close_callback)(void*), void* data); - static void callbackClickSubmit(void* userdata); - virtual void submit(); + virtual void draw(); + virtual BOOL postBuild(); +protected: + class impl; + impl* mImplementation; -private: - void addRoleNames(); + BOOL mPendingUpdate; + LLUUID mStoreSelected; + void updateLists(); }; #endif -- cgit v1.2.3 From dc44604484294d49c4821282315d826972481e6c Mon Sep 17 00:00:00 2001 From: andreylproductengine Date: Thu, 10 Apr 2014 07:05:34 +0300 Subject: MAINT-4133 FIXED Import llpanelgroupinvite.cpp from viewer_lion to voorhees_groupban: import of changes for MAINT-3846. --- indra/newview/llpanelgroupinvite.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index a9a3c686a6..bb4bfb2f96 100755 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -260,7 +260,7 @@ void LLPanelGroupInvite::impl::addRoleNames(LLGroupMgrGroupData* gdatap) //else if they have the limited add to roles power //we add every role the user is in //else we just add to everyone - bool is_owner = member_data->isInRole(gdatap->mOwnerRole); + bool is_owner = member_data->isOwner(); bool can_assign_any = gAgent.hasPowerInGroup(mGroupID, GP_ROLE_ASSIGN_MEMBER); bool can_assign_limited = gAgent.hasPowerInGroup(mGroupID, @@ -579,7 +579,7 @@ void LLPanelGroupInvite::updateLists() { waiting = true; } - if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete()) + if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete() && gdatap->isRoleMemberDataComplete()) { if ( mImplementation->mRoleNames ) { @@ -607,6 +607,7 @@ void LLPanelGroupInvite::updateLists() { LLGroupMgr::getInstance()->sendGroupPropertiesRequest(mImplementation->mGroupID); LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mImplementation->mGroupID); + LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mImplementation->mGroupID); LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mImplementation->mGroupID); } mPendingUpdate = TRUE; -- cgit v1.2.3 From c1cd375517c50cb697ef4babd56526f3162420b1 Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Fri, 11 Apr 2014 16:18:32 +0300 Subject: MAINT-3698 Typo is fixed --- indra/newview/skins/default/xui/en/floater_report_abuse.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml index 24f95950d8..3912daad05 100755 --- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml @@ -241,7 +241,7 @@ name="Indecency__Inappropriate_avatar_name" value="59" /> Date: Fri, 11 Apr 2014 16:49:58 +0300 Subject: MAINT-3698 Typo is fixed --- indra/newview/skins/default/xui/en/floater_report_abuse.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml index 3912daad05..c50c8c02fe 100755 --- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml +++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml @@ -241,7 +241,7 @@ name="Indecency__Inappropriate_avatar_name" value="59" /> Date: Tue, 29 Apr 2014 14:23:21 -0700 Subject: changed memory log frequency to 30 seconds to improve data gathering --- indra/newview/app_settings/settings.xml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e23ebd21be..37352d5e98 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6129,16 +6129,16 @@ 0 MemoryLogFrequency - - Comment - Seconds between display of Memory in log (0 for never) - Persist - 1 - Type - F32 - Value - 600.0 - + + Comment + Seconds between display of Memory in log (0 for never) + Persist + 1 + Type + F32 + Value + 30.0 + MemoryPrivatePoolEnabled Comment -- cgit v1.2.3 From 2834c7968de9efc81d3c7db8a9c2b5cd2f16d6a3 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Tue, 29 Apr 2014 14:24:00 -0700 Subject: MAINT-3975 FIX Group Invitation window omits ? button for listed residents (INTEREST LIST RC only) --- indra/llui/lltooltip.cpp | 3 ++- indra/newview/skins/default/xui/en/panel_group_invite.xml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 5e1f12996e..7f2224870d 100755 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -477,7 +477,8 @@ void LLToolTipMgr::show(const std::string& msg) void LLToolTipMgr::show(const LLToolTip::Params& params) { if (!params.styled_message.isProvided() - && (!params.message.isProvided() || params.message().empty())) return; + && (!params.message.isProvided() || params.message().empty()) + && !params.image.isProvided()) return; // fill in default tooltip params from tool_tip.xml LLToolTip::Params params_with_defaults(params); diff --git a/indra/newview/skins/default/xui/en/panel_group_invite.xml b/indra/newview/skins/default/xui/en/panel_group_invite.xml index 124c0596c3..f47ed992ca 100755 --- a/indra/newview/skins/default/xui/en/panel_group_invite.xml +++ b/indra/newview/skins/default/xui/en/panel_group_invite.xml @@ -76,7 +76,7 @@ Choose what Role to assign them to: Date: Wed, 4 Jun 2014 13:01:58 +0300 Subject: MAINT-4113 FIXED Get total contribution as sum of parcels' billable area. --- indra/newview/llpanelgrouplandmoney.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp index 106f6c25f1..506c31c22a 100755 --- a/indra/newview/llpanelgrouplandmoney.cpp +++ b/indra/newview/llpanelgrouplandmoney.cpp @@ -421,27 +421,14 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg) msg->getUUID("QueryData", "OwnerID", owner_id, 0); msg->getUUID("TransactionData", "TransactionID", trans_id); + S32 total_contribution; if(owner_id.isNull()) { // special block which has total contribution ++first_block; - - S32 total_contribution; + msg->getS32("QueryData", "ActualArea", total_contribution, 0); mPanel.getChild("total_contributed_land_value")->setTextArg("[AREA]", llformat("%d", total_contribution)); - - S32 committed; - msg->getS32("QueryData", "BillableArea", committed, 0); - mPanel.getChild("total_land_in_use_value")->setTextArg("[AREA]", llformat("%d", committed)); - - S32 available = total_contribution - committed; - mPanel.getChild("land_available_value")->setTextArg("[AREA]", llformat("%d", available)); - - if ( mGroupOverLimitTextp && mGroupOverLimitIconp ) - { - mGroupOverLimitIconp->setVisible(available < 0); - mGroupOverLimitTextp->setVisible(available < 0); - } } if ( trans_id != mTransID ) return; @@ -460,7 +447,8 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg) std::string sim_name; std::string land_sku; std::string land_type; - + S32 committed = 0; + for(S32 i = first_block; i < count; ++i) { msg->getUUID("QueryData", "OwnerID", owner_id, i); @@ -489,6 +477,9 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg) S32 region_y = llround(global_y) % REGION_WIDTH_UNITS; std::string location = sim_name + llformat(" (%d, %d)", region_x, region_y); std::string area; + committed+=billable_area; + + if(billable_area == actual_area) { area = llformat("%d", billable_area); @@ -525,6 +516,16 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg) mGroupParcelsp->addElement(row); } + + mPanel.getChild("total_land_in_use_value")->setTextArg("[AREA]", llformat("%d", committed)); + + S32 available = total_contribution - committed; + mPanel.getChild("land_available_value")->setTextArg("[AREA]", llformat("%d", available)); + if ( mGroupOverLimitTextp && mGroupOverLimitIconp ) + { + mGroupOverLimitIconp->setVisible(available < 0); + mGroupOverLimitTextp->setVisible(available < 0); + } } } -- cgit v1.2.3 From 739f4954b165bd993f8dfaf0636b7a29c228e091 Mon Sep 17 00:00:00 2001 From: Stinson Linden Date: Fri, 6 Jun 2014 22:35:59 +0100 Subject: Correcting a build error. --- indra/newview/llpanelgrouplandmoney.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp index 506c31c22a..375c54479d 100755 --- a/indra/newview/llpanelgrouplandmoney.cpp +++ b/indra/newview/llpanelgrouplandmoney.cpp @@ -421,7 +421,7 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg) msg->getUUID("QueryData", "OwnerID", owner_id, 0); msg->getUUID("TransactionData", "TransactionID", trans_id); - S32 total_contribution; + S32 total_contribution = 0; if(owner_id.isNull()) { // special block which has total contribution -- cgit v1.2.3 From 47a5e1c751bb8dfccef65ee841749d8209106c99 Mon Sep 17 00:00:00 2001 From: Stinson Linden Date: Thu, 5 Jun 2014 23:15:43 +0100 Subject: MAINT-4009: Ensuring that the local bitmaps are cleaned up on app exit. --- indra/newview/llappviewer.cpp | 5 ++++- indra/newview/lllocalbitmaps.cpp | 6 ++++++ indra/newview/lllocalbitmaps.h | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 1c38adb879..42f56fff32 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -100,6 +100,7 @@ #include "llspellcheck.h" #include "llscenemonitor.h" #include "llavatarrenderinfoaccountant.h" +#include "lllocalbitmaps.h" // Linden library includes #include "llavatarnamecache.h" @@ -1758,7 +1759,9 @@ bool LLAppViewer::cleanup() #if 0 // this seems to get us stuck in an infinite loop... gTransferManager.cleanup(); #endif - + + LLLocalBitmapMgr::cleanupClass(); + // Note: this is where gWorldMap used to be deleted. // Note: this is where gHUDManager used to be deleted. diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 1948475530..e78e0233d7 100755 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -824,6 +824,12 @@ LLLocalBitmapMgr::~LLLocalBitmapMgr() { } +void LLLocalBitmapMgr::cleanupClass() +{ + std::for_each(sBitmapList.begin(), sBitmapList.end(), DeletePointer()); + sBitmapList.clear(); +} + bool LLLocalBitmapMgr::addUnit() { bool add_successful = false; diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h index 47c077dcab..a15ea10801 100755 --- a/indra/newview/lllocalbitmaps.h +++ b/indra/newview/lllocalbitmaps.h @@ -117,6 +117,7 @@ class LLLocalBitmapMgr ~LLLocalBitmapMgr(); public: + static void cleanupClass(); static bool addUnit(); static void delUnit(LLUUID tracking_id); -- cgit v1.2.3 From bde6023286c899c99104b16181203f7b58819333 Mon Sep 17 00:00:00 2001 From: Stinson Linden Date: Fri, 6 Jun 2014 19:28:18 +0100 Subject: MAINT-4137: Correcting some poorly written CPP code that could potentially lead to problems in the future. --- indra/newview/lllocalbitmaps.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index e78e0233d7..92587a911a 100755 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -190,7 +190,7 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate) { // decode is successful, we can safely proceed. LLUUID old_id = LLUUID::null; - if (!(optional_firstupdate == UT_FIRSTUSE) && !mWorldID.isNull()) + if ((optional_firstupdate != UT_FIRSTUSE) && !mWorldID.isNull()) { old_id = mWorldID; } @@ -206,7 +206,7 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate) gTextureList.addImage(texture); - if (!optional_firstupdate == UT_FIRSTUSE) + if (optional_firstupdate != UT_FIRSTUSE) { // seek out everything old_id uses and replace it with mWorldID replaceIDs(old_id, mWorldID); -- cgit v1.2.3 From 61f3bf8a4799016f6a50007314816cddb1dff030 Mon Sep 17 00:00:00 2001 From: Stinson Linden Date: Fri, 6 Jun 2014 19:30:41 +0100 Subject: MAINT-4137: Correcting a potential crash. This change should fix the most probable location of a callstack being reported by the crash reporter. However, there is no reproduction yet, so hard to test whether this actually patches the crash occcurrence. --- indra/newview/lllocalbitmaps.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 92587a911a..6d1a240ce5 100755 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -213,8 +213,11 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate) // remove old_id from gimagelist LLViewerFetchedTexture* image = gTextureList.findImage(old_id); - gTextureList.deleteImage(image); - image->unref(); + if (image != NULL) + { + gTextureList.deleteImage(image); + image->unref(); + } } mUpdateRetries = LL_LOCAL_UPDATE_RETRIES; -- cgit v1.2.3 From 086b2c0448584c3a3c5fc320f9f6ba20e613d974 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Sat, 7 Jun 2014 16:02:30 -0700 Subject: MAINT-4001 : Make Received Items not movable (protected), consolidate Received Items folders which may have been moved --- indra/llinventory/llfoldertype.cpp | 2 +- indra/newview/llsidepanelinventory.cpp | 12 +++++++----- indra/newview/llviewerfoldertype.cpp | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) (limited to 'indra') diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp index 8b568ea560..5f8aaae20b 100755 --- a/indra/llinventory/llfoldertype.cpp +++ b/indra/llinventory/llfoldertype.cpp @@ -92,7 +92,7 @@ LLFolderDictionary::LLFolderDictionary() addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", TRUE)); - addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", FALSE)); + addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE)); addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", FALSE)); addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE)); diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 2556714792..4970eec636 100755 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -257,12 +257,9 @@ void LLSidepanelInventory::updateInbox() // // Track inbox folder changes // - - const bool do_not_create_folder = false; - - const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder); + const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, true); - // Set up observer to listen for creation of inbox if at least one of them doesn't exist + // Set up observer to listen for creation of inbox if it doesn't exist if (inbox_id.isNull()) { observeInboxCreation(); @@ -270,6 +267,11 @@ void LLSidepanelInventory::updateInbox() // Set up observer for inbox changes, if we have an inbox already else { + // Consolidate Received items + // We shouldn't have to do that but with a client/server system relying on a "well known folder" convention, + // things can get messy and conventions broken. This call puts everything back together in its right place. + gInventory.consolidateForType(inbox_id, LLFolderType::FT_INBOX); + // Enable the display of the inbox if it exists enableInbox(true); diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index 4237ffd295..66e900c405 100644 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -136,7 +136,7 @@ LLViewerFolderDictionary::LLViewerFolderDictionary() addEntry(LLFolderType::FT_MESH, new ViewerFolderEntry("Meshes", "Inv_SysOpen", "Inv_SysClosed", FALSE, true)); bool boxes_invisible = !gSavedSettings.getBOOL("InventoryOutboxMakeVisible"); - addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible)); + addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Received Items", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible)); addEntry(LLFolderType::FT_OUTBOX, new ViewerFolderEntry("Merchant Outbox", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible)); addEntry(LLFolderType::FT_BASIC_ROOT, new ViewerFolderEntry("Basic Root", "Inv_SysOpen", "Inv_SysClosed", FALSE, true)); -- cgit v1.2.3 From 4bcf2079f15a09d40f1d7aa61b2768cc54dc427a Mon Sep 17 00:00:00 2001 From: Aura Linden Date: Mon, 9 Jun 2014 10:28:18 -0700 Subject: Fix for maint-3154 alt-zoom zooms way out --- indra/newview/llagentcamera.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra') diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index d1dfbe3315..7b0496ea45 100755 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -913,6 +913,8 @@ void LLAgentCamera::cameraZoomIn(const F32 fraction) F32 max_distance = llmin(mDrawDistance - DIST_FUDGE, LLWorld::getInstance()->getRegionWidthInMeters() - DIST_FUDGE ); + max_distance = llmin(max_distance, current_distance * 4.f); //Scaled max relative to current distance. MAINT-3154 + if (new_distance > max_distance) { new_distance = max_distance; -- cgit v1.2.3 From a92dbb592b338f48f7b75b68a9da511dc95279f9 Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Wed, 11 Jun 2014 20:24:25 +0300 Subject: MAINT-4133 FIXED Import llpanelgroupinvite.cpp from viewer_lion to voorhees_groupban. --- indra/newview/llpanelgroupinvite.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index bb4bfb2f96..236ad861a5 100755 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -655,7 +655,7 @@ BOOL LLPanelGroupInvite::postBuild() } mImplementation->mOKButton = - getChild("ok_button", recurse); + getChild("invite_button", recurse); if ( mImplementation->mOKButton ) { mImplementation->mOKButton->setClickedCallback(impl::callbackClickOK, mImplementation); -- cgit v1.2.3 From f924175da0acbb8a8884fff0740d416da9c2489c Mon Sep 17 00:00:00 2001 From: "maxim@mnikolenko" Date: Wed, 18 Jun 2014 13:00:18 +0300 Subject: MAINT-3186 FIXED Disable menu items if group or ad-hoc chat is in multiselection --- indra/newview/llfloaterimcontainer.cpp | 20 ++++++++++++++++++++ .../skins/default/xui/en/menu_conversation.xml | 1 + 2 files changed, 21 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index ebb44561da..a0df37b309 100755 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1271,6 +1271,22 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata) uuid_vec_t uuids; getParticipantUUIDs(uuids); + + //If there is group or ad-hoc chat in multiselection, everything needs to be disabled + if(uuids.size() > 1) + { + const std::set selectedItems = mConversationsRoot->getSelectionList(); + LLConversationItem * conversationItem; + for(std::set::const_iterator it = selectedItems.begin(); it != selectedItems.end(); ++it) + { + conversationItem = static_cast((*it)->getViewModelItem()); + if((conversationItem->getType() == LLConversationItem::CONV_SESSION_GROUP) || (conversationItem->getType() == LLConversationItem::CONV_SESSION_AD_HOC)) + { + return false; + } + } + } + if ("conversation_log" == item) { return gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0; @@ -1375,6 +1391,10 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v else if ("can_call" == item) { return LLAvatarActions::canCall(); + } + else if ("can_open_voice_conversation" == item) + { + return is_single_select && LLAvatarActions::canCall(); } else if ("can_zoom_in" == item) { diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index 31b1d091ee..f5a493c064 100755 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -17,6 +17,7 @@ layout="topleft" name="open_voice_conversation"> + Date: Thu, 19 Jun 2014 17:38:39 +0300 Subject: MAINT-4174 FIXED "Ban Resident(s)" button in Banned residents tab is active for members without ban permissions, after viewing 'Banned Residents' tab in a group where they do have ban permissions --- indra/newview/llpanelgrouproles.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 2fcaa5666e..b21e1747b3 100755 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -2875,10 +2875,7 @@ void LLPanelGroupBanListSubTab::activate() mBanList->deselectAllItems(); mDeleteBanButton->setEnabled(FALSE); - if (gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS)) - { - mCreateBanButton->setEnabled(TRUE); - } + mCreateBanButton->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS)); // BAKER: Should I really request everytime activate() is called? // Perhaps I should only do it on a force refresh, or if an action on the list happens... -- cgit v1.2.3 From a7db93cb698d81ea5005ed4be453fbddd65e0cc0 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Thu, 19 Jun 2014 21:23:14 +0300 Subject: MAINT-4182 FIXED The group ban list always appears empty --- indra/newview/llgroupmgr.cpp | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) (limited to 'indra') diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 61c3bbb13a..50e3ab6dd8 100755 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -1868,8 +1868,8 @@ class GroupBanDataResponder : public LLHTTPClient::Responder public: GroupBanDataResponder(const LLUUID& gropup_id, BOOL force_refresh=false); virtual ~GroupBanDataResponder() {} - virtual void result(const LLSD& pContent); - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent); + virtual void httpSuccess(); + virtual void httpFailure(); private: LLUUID mGroupID; BOOL mForceRefresh; @@ -1880,34 +1880,27 @@ GroupBanDataResponder::GroupBanDataResponder(const LLUUID& gropup_id, BOOL force mForceRefresh(force_refresh) {} -void GroupBanDataResponder::errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& pContent) +void GroupBanDataResponder::httpFailure() { LL_WARNS("GrpMgr") << "Error receiving group member data [status:" - << pStatus << "]: " << pContent << LL_ENDL; + << mStatus << "]: " << mContent << LL_ENDL; } -void GroupBanDataResponder::result(const LLSD& content) +void GroupBanDataResponder::httpSuccess() { - if ( content.size()) + if ( mContent.size()) { - if (content.has("ban_list")) + if (mContent.has("ban_list")) { - // group data received - LLGroupMgr::processGroupBanRequest(content); - } - // no group data received, this is either CREATE or DELETE operation - // complete confirmation. Local data may be obsolete. - else if (mForceRefresh) - { - // providing mGroupId and not extracting it from content since it is not - // included into CREATE and DELETE responses - LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID); + // group ban data received + LLGroupMgr::processGroupBanRequest(mContent); + mForceRefresh = false; } } - else + if (mForceRefresh) { - LL_WARNS("GrpMgr") << "No group member data received." << LL_ENDL; - return; + // no ban data received, refreshing data after successful operation + LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID); } } -- cgit v1.2.3 From 845b80a3864093ebed940551d91441e45e4b50b9 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 23 Jun 2014 13:25:17 +0300 Subject: MAINT-4182 Cleaning up --- indra/newview/llgroupmgr.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'indra') diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 50e3ab6dd8..98036f3a20 100755 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -1888,16 +1888,12 @@ void GroupBanDataResponder::httpFailure() void GroupBanDataResponder::httpSuccess() { - if ( mContent.size()) + if (mContent.has("ban_list")) { - if (mContent.has("ban_list")) - { - // group ban data received - LLGroupMgr::processGroupBanRequest(mContent); - mForceRefresh = false; - } + // group ban data received + LLGroupMgr::processGroupBanRequest(mContent); } - if (mForceRefresh) + else if (mForceRefresh) { // no ban data received, refreshing data after successful operation LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_GET, mGroupID); -- cgit v1.2.3 From be2f4ecdb4135256e3e513370614c1626e5a1354 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Mon, 23 Jun 2014 18:39:53 +0300 Subject: MAINT-4175 FIXED [Group Bans] When banning a list of multiple avatars, if an already banned avatar is included in the list, no avatars are added to the ban list and those avatars already group members are not ejected from the group. --- indra/newview/llpanelgroupbulkban.cpp | 78 ++++++++++++++++++---- indra/newview/llpanelgroupbulkimpl.h | 2 + .../skins/default/xui/en/panel_group_bulk_ban.xml | 26 ++++++-- 3 files changed, 90 insertions(+), 16 deletions(-) (limited to 'indra') diff --git a/indra/newview/llpanelgroupbulkban.cpp b/indra/newview/llpanelgroupbulkban.cpp index a31396737d..3499b45949 100644 --- a/indra/newview/llpanelgroupbulkban.cpp +++ b/indra/newview/llpanelgroupbulkban.cpp @@ -31,6 +31,7 @@ #include "llagent.h" #include "llavatarnamecache.h" +#include "llavataractions.h" #include "llfloateravatarpicker.h" #include "llbutton.h" #include "llcallingcard.h" @@ -100,6 +101,8 @@ BOOL LLPanelGroupBulkBan::postBuild() } mImplementation->mTooManySelected = getString("ban_selection_too_large"); + mImplementation->mBanNotPermitted = getString("ban_not_permitted"); + mImplementation->mCannotBanYourself = getString("cant_ban_yourself"); update(); return TRUE; @@ -117,6 +120,15 @@ void LLPanelGroupBulkBan::callbackClickSubmit(void* userdata) void LLPanelGroupBulkBan::submit() { + if (!gAgent.hasPowerInGroup(mImplementation->mGroupID, GP_GROUP_BAN_ACCESS)) + { + // Fail! Agent no longer have ban rights. + LLSD msg; + msg["MESSAGE"] = mImplementation->mBanNotPermitted; + LLNotificationsUtil::add("GenericAlert", msg); + (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData); + return; + } std::vector banned_agent_list; std::vector agents = mImplementation->mBulkAgentList->getAllData(); std::vector::iterator iter = agents.begin(); @@ -137,32 +149,74 @@ void LLPanelGroupBulkBan::submit() return; } + // remove already banned users and yourself from request. + std::vector banned_avatar_names; + bool banning_self = FALSE; + std::vector::iterator conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), gAgent.getID()); + if (conflict != banned_agent_list.end()) + { + banned_agent_list.erase(conflict); + banning_self = TRUE; + } LLGroupMgrGroupData * group_datap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID); if (group_datap) { BOOST_FOREACH(const LLGroupMgrGroupData::ban_list_t::value_type& group_ban_pair, group_datap->mBanList) { const LLUUID& group_ban_agent_id = group_ban_pair.first; - if (std::find(banned_agent_list.begin(), banned_agent_list.end(), group_ban_agent_id) != banned_agent_list.end()) + std::vector::iterator conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), group_ban_agent_id); + if (conflict != banned_agent_list.end()) { - // Fail! LLAvatarName av_name; LLAvatarNameCache::get(group_ban_agent_id, &av_name); + banned_avatar_names.push_back(av_name); - LLStringUtil::format_map_t string_args; - string_args["[RESIDENT]"] = av_name.getDisplayName(); - - LLSD msg; - msg["MESSAGE"] = getString("already_banned", string_args); - LLNotificationsUtil::add("GenericAlert", msg); - (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData); - return; + banned_agent_list.erase(conflict); + if (banned_agent_list.size() == 0) + { + break; + } } } } - LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mImplementation->mGroupID, LLGroupMgr::BAN_CREATE | LLGroupMgr::BAN_UPDATE, banned_agent_list); - LLGroupMgr::getInstance()->sendGroupMemberEjects(mImplementation->mGroupID, banned_agent_list); + if (banned_agent_list.size() != 0) + { + LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mImplementation->mGroupID, LLGroupMgr::BAN_CREATE | LLGroupMgr::BAN_UPDATE, banned_agent_list); + LLGroupMgr::getInstance()->sendGroupMemberEjects(mImplementation->mGroupID, banned_agent_list); + } + + // building notification + if (banned_avatar_names.size() > 0 || banning_self) + { + std::string reasons; + if(banned_avatar_names.size() > 0) + { + std::string names_string; + LLAvatarActions::buildResidentsString(banned_avatar_names, names_string); + LLStringUtil::format_map_t reason_args; + reason_args["[RESIDENTS]"] = names_string; + reasons = "\n " + getString("residents_already_banned", reason_args); + } + + if(banning_self) + { + reasons += "\n " + mImplementation->mCannotBanYourself; + } + + LLStringUtil::format_map_t msg_args; + msg_args["[REASONS]"] = reasons; + LLSD msg; + if (banned_agent_list.size() == 0) + { + msg["MESSAGE"] = getString("ban_failed", msg_args); + } + else + { + msg["MESSAGE"] = getString("partial_ban", msg_args); + } + LLNotificationsUtil::add("GenericAlert", msg); + } //then close (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData); diff --git a/indra/newview/llpanelgroupbulkimpl.h b/indra/newview/llpanelgroupbulkimpl.h index 0bc834d67e..585b48c68f 100644 --- a/indra/newview/llpanelgroupbulkimpl.h +++ b/indra/newview/llpanelgroupbulkimpl.h @@ -74,6 +74,8 @@ public: std::string mLoadingText; std::string mTooManySelected; + std::string mBanNotPermitted; + std::string mCannotBanYourself; std::set mInviteeIDs; 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 index 43449df1fd..31989f2e16 100644 --- a/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml +++ b/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml @@ -15,10 +15,28 @@ name="ban_selection_too_large"> Group bans not sent: too many Residents selected. Group bans are limited to 100 per request. - - Group Invitations not sent: resident '[RESIDENT]' already banned. - + + Group ban not sent: you do not have 'Manage ban list' ability. + + + Some group bans were not sent: +[REASONS] + + + Group bans were not sent: +[REASONS] + + + - The following resident(s) are already banned: [RESIDENTS]. + + + - You cannot ban yourself from a group. + Date: Mon, 23 Jun 2014 23:10:23 -0500 Subject: MAINT-2980 Up texture memory slider cap to 4096MB. Make "Texture Memory" default to 1/3rd of video memory. Add description on debug setting and tooltip to explain why. --- indra/newview/app_settings/settings.xml | 2 +- indra/newview/llfloaterhardwaresettings.cpp | 15 ------------ indra/newview/llfloaterhardwaresettings.h | 2 -- indra/newview/llviewertexture.cpp | 2 +- indra/newview/llviewertexturelist.cpp | 28 +++++++--------------- .../default/xui/en/floater_hardware_settings.xml | 5 ++-- 6 files changed, 13 insertions(+), 41 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6081729687..a2a8cf989d 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11862,7 +11862,7 @@ TextureMemory Comment - Amount of memory to use for textures in MB (0 = autodetect) + Amount of memory to use for textures in MB (0 = autodetect). Defaults to 1/3 of video memory to allow room for render targets, vertex buffers, 3D accelerated desktops, and over allocation. Persist 1 Type diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp index f267a2e7b3..035eb307c2 100755 --- a/indra/newview/llfloaterhardwaresettings.cpp +++ b/indra/newview/llfloaterhardwaresettings.cpp @@ -87,16 +87,6 @@ void LLFloaterHardwareSettings::refresh() refreshEnabledState(); } -void LLFloaterHardwareSettings::onSetVRAM() -{ - S32 vram = childGetValue("GraphicsCardTextureMemory").asInteger(); - - //give the texture system plenty of leeway to avoid swapping - vram /= 3; - - gSavedSettings.setS32("TextureMemory", vram); -} - void LLFloaterHardwareSettings::refreshEnabledState() { F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); @@ -105,11 +95,6 @@ void LLFloaterHardwareSettings::refreshEnabledState() getChild("GraphicsCardTextureMemory")->setMinValue(min_tex_mem.value()); getChild("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem.value()); - S32 vram = gSavedSettings.getS32("TextureMemory"); - vram = vram*3; - - getChild("GraphicsCardTextureMemory")->setValue(vram); - getChild("GraphicsCardTextureMemory")->setCommitCallback(boost::bind(&LLFloaterHardwareSettings::onSetVRAM, this)); if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") || !gGLManager.mHasVertexBufferObject) { diff --git a/indra/newview/llfloaterhardwaresettings.h b/indra/newview/llfloaterhardwaresettings.h index 63d86d5667..626771b1d2 100755 --- a/indra/newview/llfloaterhardwaresettings.h +++ b/indra/newview/llfloaterhardwaresettings.h @@ -64,8 +64,6 @@ public: /// don't apply the changed values void cancel(); - void onSetVRAM(); - /// refresh the enabled values void refreshEnabledState(); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index ba89aafc84..e16caf167d 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -64,7 +64,7 @@ // extern const S32Megabytes gMinVideoRam(32); -const S32Megabytes gMaxVideoRam(512); +const S32Megabytes gMaxVideoRam(4096); // statics diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 2209b24ca7..9f862b4f97 100755 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1275,21 +1275,15 @@ S32Megabytes LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, fl { S32Megabytes max_texmem; if (gGLManager.mVRAM != 0) - { - // Treat any card with < 32 MB (shudder) as having 32 MB - // - it's going to be swapping constantly regardless + { //use detected amount of vram as maximum S32Megabytes max_vram(gGLManager.mVRAM); - if(!get_recommended && gGLManager.mIsATI) - { - //shrink the availabe vram for ATI cards because some of them do not handel texture swapping well. - max_vram = max_vram * 0.75f; - } - - max_vram = llmax(max_vram, getMinVideoRamSetting()); max_texmem = max_vram; - if (!get_recommended) - max_texmem *= 2; + + if (get_recommended) + { //recommend 1/3rd of total video memory for textures + max_texmem /= 3; + } } else { @@ -1309,15 +1303,9 @@ S32Megabytes LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, fl LL_WARNS() << "VRAM amount not detected, defaulting to " << max_texmem << " MB" << LL_ENDL; } - S32Megabytes system_ram = gSysMemory.getPhysicalMemoryClamped(); // In MB - //LL_INFOS() << "*** DETECTED " << system_ram << " MB of system memory." << LL_ENDL; - max_texmem = llmin(max_texmem, (S32Megabytes)(system_ram)); - - // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise + // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise max_texmem = llmin(max_texmem, (S32Megabytes) (mem_multiplier * max_texmem)); - max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), gMaxVideoRam); - return max_texmem; } @@ -1341,7 +1329,7 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32Megabytes mem) mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting(false, mem_multiplier)); if (mem != cur_mem) { - gSavedSettings.setS32("TextureMemory", mem.value()/3); + gSavedSettings.setS32("TextureMemory", mem.value()); return; //listener will re-enter this function } diff --git a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml index 05594c2d86..40d54233e8 100755 --- a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml @@ -157,16 +157,17 @@ Date: Wed, 25 Jun 2014 20:09:33 +0300 Subject: MAINT-4178 FIXED [Group Bans] The viewer allows you to attempt to ban when the ban list already contains 500 entries, which fails. --- indra/newview/llgroupmgr.h | 2 + indra/newview/llpanelgroupbulkban.cpp | 55 ++++++++++++++++++---- indra/newview/llpanelgroupbulkban.h | 2 + indra/newview/llpanelgroupbulkimpl.h | 1 + indra/newview/llpanelgrouproles.cpp | 33 ++++++++++++- indra/newview/llpanelgrouproles.h | 2 + .../skins/default/xui/en/panel_group_bulk_ban.xml | 38 +++++++++------ .../skins/default/xui/en/panel_group_roles.xml | 13 +++++ 8 files changed, 119 insertions(+), 27 deletions(-) (limited to 'indra') diff --git a/indra/newview/llgroupmgr.h b/indra/newview/llgroupmgr.h index 970d6d5a2d..2e94e8d9a0 100755 --- a/indra/newview/llgroupmgr.h +++ b/indra/newview/llgroupmgr.h @@ -49,6 +49,8 @@ enum LLGroupChange GC_ALL }; +const U32 GB_MAX_BANNED_AGENTS = 500; + class LLGroupMgrObserver { public: diff --git a/indra/newview/llpanelgroupbulkban.cpp b/indra/newview/llpanelgroupbulkban.cpp index 3499b45949..cf1f0bc32f 100644 --- a/indra/newview/llpanelgroupbulkban.cpp +++ b/indra/newview/llpanelgroupbulkban.cpp @@ -102,6 +102,7 @@ BOOL LLPanelGroupBulkBan::postBuild() mImplementation->mTooManySelected = getString("ban_selection_too_large"); mImplementation->mBanNotPermitted = getString("ban_not_permitted"); + mImplementation->mBanLimitFail = getString("ban_limit_fail"); mImplementation->mCannotBanYourself = getString("cant_ban_yourself"); update(); @@ -122,13 +123,23 @@ void LLPanelGroupBulkBan::submit() { if (!gAgent.hasPowerInGroup(mImplementation->mGroupID, GP_GROUP_BAN_ACCESS)) { - // Fail! Agent no longer have ban rights. + // Fail! Agent no longer have ban rights. Permissions could have changed after button was pressed. LLSD msg; msg["MESSAGE"] = mImplementation->mBanNotPermitted; LLNotificationsUtil::add("GenericAlert", msg); (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData); return; } + LLGroupMgrGroupData * group_datap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID); + if (group_datap && group_datap->mBanList.size() >= GB_MAX_BANNED_AGENTS) + { + // Fail! Size limit exceeded. List could have updated after button was pressed. + LLSD msg; + msg["MESSAGE"] = mImplementation->mBanLimitFail; + LLNotificationsUtil::add("GenericAlert", msg); + (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData); + return; + } std::vector banned_agent_list; std::vector agents = mImplementation->mBulkAgentList->getAllData(); std::vector::iterator iter = agents.begin(); @@ -138,8 +149,8 @@ void LLPanelGroupBulkBan::submit() 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) + const S32 MAX_BANS_PER_REQUEST = 100; // Max bans per request. 100 to match server cap. + if (banned_agent_list.size() > MAX_BANS_PER_REQUEST) { // Fail! LLSD msg; @@ -151,6 +162,7 @@ void LLPanelGroupBulkBan::submit() // remove already banned users and yourself from request. std::vector banned_avatar_names; + std::vector out_of_limit_names; bool banning_self = FALSE; std::vector::iterator conflict = std::find(banned_agent_list.begin(), banned_agent_list.end(), gAgent.getID()); if (conflict != banned_agent_list.end()) @@ -158,7 +170,6 @@ void LLPanelGroupBulkBan::submit() banned_agent_list.erase(conflict); banning_self = TRUE; } - LLGroupMgrGroupData * group_datap = LLGroupMgr::getInstance()->getGroupData(mImplementation->mGroupID); if (group_datap) { BOOST_FOREACH(const LLGroupMgrGroupData::ban_list_t::value_type& group_ban_pair, group_datap->mBanList) @@ -178,8 +189,23 @@ void LLPanelGroupBulkBan::submit() } } } + // this check should always be the last one before we send the request. + // Otherwise we have a possibility of cutting more then we need to. + if (banned_agent_list.size() > GB_MAX_BANNED_AGENTS - group_datap->mBanList.size()) + { + std::vector::iterator exeedes_limit = banned_agent_list.begin() + GB_MAX_BANNED_AGENTS - group_datap->mBanList.size(); + for (std::vector::iterator itor = exeedes_limit ; + itor != banned_agent_list.end(); ++itor) + { + LLAvatarName av_name; + LLAvatarNameCache::get(*itor, &av_name); + out_of_limit_names.push_back(av_name); + } + banned_agent_list.erase(exeedes_limit,banned_agent_list.end()); + } } + // sending request and ejecting members if (banned_agent_list.size() != 0) { LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mImplementation->mGroupID, LLGroupMgr::BAN_CREATE | LLGroupMgr::BAN_UPDATE, banned_agent_list); @@ -187,16 +213,12 @@ void LLPanelGroupBulkBan::submit() } // building notification - if (banned_avatar_names.size() > 0 || banning_self) + if (banned_avatar_names.size() > 0 || banning_self || out_of_limit_names.size() > 0) { std::string reasons; if(banned_avatar_names.size() > 0) { - std::string names_string; - LLAvatarActions::buildResidentsString(banned_avatar_names, names_string); - LLStringUtil::format_map_t reason_args; - reason_args["[RESIDENTS]"] = names_string; - reasons = "\n " + getString("residents_already_banned", reason_args); + reasons = "\n " + buildResidentsArgument(banned_avatar_names, "residents_already_banned"); } if(banning_self) @@ -204,6 +226,11 @@ void LLPanelGroupBulkBan::submit() reasons += "\n " + mImplementation->mCannotBanYourself; } + if(out_of_limit_names.size() > 0) + { + reasons += "\n " + buildResidentsArgument(out_of_limit_names, "ban_limit_reached"); + } + LLStringUtil::format_map_t msg_args; msg_args["[REASONS]"] = reasons; LLSD msg; @@ -222,3 +249,11 @@ void LLPanelGroupBulkBan::submit() (*(mImplementation->mCloseCallback))(mImplementation->mCloseCallbackUserData); } +std::string LLPanelGroupBulkBan::buildResidentsArgument(std::vector avatar_names, const std::string &format) +{ + std::string names_string; + LLAvatarActions::buildResidentsString(avatar_names, names_string); + LLStringUtil::format_map_t args; + args["[RESIDENTS]"] = names_string; + return getString(format, args); +} diff --git a/indra/newview/llpanelgroupbulkban.h b/indra/newview/llpanelgroupbulkban.h index 0684f365a0..9060d275f9 100644 --- a/indra/newview/llpanelgroupbulkban.h +++ b/indra/newview/llpanelgroupbulkban.h @@ -42,6 +42,8 @@ public: static void callbackClickSubmit(void* userdata); virtual void submit(); +private: + std::string buildResidentsArgument(std::vector avatar_names, const std::string &format); }; #endif // LL_LLPANELGROUPBULKBAN_H diff --git a/indra/newview/llpanelgroupbulkimpl.h b/indra/newview/llpanelgroupbulkimpl.h index 585b48c68f..d3a48e5a9a 100644 --- a/indra/newview/llpanelgroupbulkimpl.h +++ b/indra/newview/llpanelgroupbulkimpl.h @@ -75,6 +75,7 @@ public: std::string mLoadingText; std::string mTooManySelected; std::string mBanNotPermitted; + std::string mBanLimitFail; std::string mCannotBanYourself; std::set mInviteeIDs; diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index b21e1747b3..68022ef343 100755 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -2844,8 +2844,9 @@ BOOL LLPanelGroupBanListSubTab::postBuildSubTab(LLView* root) mCreateBanButton = parent->getChild("ban_create", recurse); mDeleteBanButton = parent->getChild("ban_delete", recurse); mRefreshBanListButton = parent->getChild("ban_refresh", recurse); + mBanCountText = parent->getChild("ban_count", recurse); - if(!mBanList || !mCreateBanButton || !mDeleteBanButton || !mRefreshBanListButton) + if(!mBanList || !mCreateBanButton || !mDeleteBanButton || !mRefreshBanListButton || !mBanCountText) return FALSE; mBanList->setCommitOnSelectionChange(TRUE); @@ -2860,6 +2861,8 @@ BOOL LLPanelGroupBanListSubTab::postBuildSubTab(LLView* root) mRefreshBanListButton->setClickedCallback(onRefreshBanList, this); mRefreshBanListButton->setEnabled(FALSE); + setBanCount(0); + mBanList->setOnNameListCompleteCallback(boost::bind(&LLPanelGroupBanListSubTab::onBanListCompleted, this, _1)); populateBanList(); @@ -2875,7 +2878,18 @@ void LLPanelGroupBanListSubTab::activate() mBanList->deselectAllItems(); mDeleteBanButton->setEnabled(FALSE); - mCreateBanButton->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS)); + LLGroupMgrGroupData * group_datap = LLGroupMgr::getInstance()->getGroupData(mGroupID); + if (group_datap) + { + mCreateBanButton->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS) && + group_datap->mBanList.size() < GB_MAX_BANNED_AGENTS); + setBanCount(group_datap->mBanList.size()); + } + else + { + mCreateBanButton->setEnabled(FALSE); + setBanCount(0); + } // BAKER: Should I really request everytime activate() is called? // Perhaps I should only do it on a force refresh, or if an action on the list happens... @@ -2993,6 +3007,10 @@ void LLPanelGroupBanListSubTab::handleDeleteBanEntry() // the button anymore until we reselect another entry. mDeleteBanButton->setEnabled(FALSE); } + + // update ban-count related elements + mCreateBanButton->setEnabled(TRUE); + setBanCount(gdatap->mBanList.size()); LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mGroupID, LLGroupMgr::BAN_DELETE, ban_ids); } @@ -3021,6 +3039,14 @@ void LLPanelGroupBanListSubTab::onBanListCompleted(bool isComplete) } } +void LLPanelGroupBanListSubTab::setBanCount(U32 ban_count) +{ + LLStringUtil::format_map_t args; + args["[COUNT]"] = llformat("%d", ban_count); + args["[LIMIT]"] = llformat("%d", GB_MAX_BANNED_AGENTS); + mBanCountText->setText(getString("ban_count_template", args)); +} + void LLPanelGroupBanListSubTab::populateBanList() { LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); @@ -3060,6 +3086,9 @@ void LLPanelGroupBanListSubTab::populateBanList() } mRefreshBanListButton->setEnabled(TRUE); + mCreateBanButton->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_GROUP_BAN_ACCESS) && + gdatap->mBanList.size() < GB_MAX_BANNED_AGENTS); + setBanCount(gdatap->mBanList.size()); } void LLPanelGroupBanListSubTab::setGroupID(const LLUUID& id) diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index 052f1d2071..b9697a1d3a 100755 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -347,6 +347,7 @@ public: void onBanListCompleted(bool isComplete); protected: + void setBanCount(U32 ban_count); void populateBanList(); public: @@ -357,6 +358,7 @@ protected: LLButton* mCreateBanButton; LLButton* mDeleteBanButton; LLButton* mRefreshBanListButton; + LLTextBase* mBanCountText; }; 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 index 31989f2e16..509dcf354e 100644 --- a/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml +++ b/indra/newview/skins/default/xui/en/panel_group_bulk_ban.xml @@ -15,28 +15,36 @@ name="ban_selection_too_large"> Group bans not sent: too many Residents selected. Group bans are limited to 100 per request. - - Group ban not sent: you do not have 'Manage ban list' ability. - - + + Group ban not sent: your group have reached limit of allowed ban records. + + - Some group bans were not sent: + Some group bans were not sent: [REASONS] - - + - Group bans were not sent: + Group bans were not sent: [REASONS] - - + - - The following resident(s) are already banned: [RESIDENTS]. - - + + - Ban limit reached, following agents not banned: [RESIDENTS]. + + - - You cannot ban yourself from a group. - + - You cannot ban yourself from a group. + Any resident on the ban list will be unable to join the group. + + Ban count: [COUNT]/[LIMIT] + + + Date: Mon, 30 Jun 2014 19:54:28 -0500 Subject: MAINT-2980 Fix for AMD cards reporting system ram + vram for dedicated vram -- use WMI instead of DxDiag to get dedicated video memory. --- indra/llwindow/lldxhardware.cpp | 178 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 173 insertions(+), 5 deletions(-) (limited to 'indra') diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp index ba5bc8fcfb..e7afef63f8 100755 --- a/indra/llwindow/lldxhardware.cpp +++ b/indra/llwindow/lldxhardware.cpp @@ -34,9 +34,12 @@ #include #undef INITGUID +#include + #include #include "lldxhardware.h" + #include "llerror.h" #include "llstring.h" @@ -53,11 +56,160 @@ LLDXHardware gDXHardware; #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } -std::string get_string(IDxDiagContainer *containerp, WCHAR *wszPropName) +typedef BOOL ( WINAPI* PfnCoSetProxyBlanket )( IUnknown* pProxy, DWORD dwAuthnSvc, DWORD dwAuthzSvc, + OLECHAR* pServerPrincName, DWORD dwAuthnLevel, DWORD dwImpLevel, + RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities ); + +HRESULT GetVideoMemoryViaWMI( WCHAR* strInputDeviceID, DWORD* pdwAdapterRam ) { HRESULT hr; + bool bGotMemory = false; + HRESULT hrCoInitialize = S_OK; + IWbemLocator* pIWbemLocator = nullptr; + IWbemServices* pIWbemServices = nullptr; + BSTR pNamespace = nullptr; + + *pdwAdapterRam = 0; + hrCoInitialize = CoInitialize( 0 ); + + hr = CoCreateInstance( CLSID_WbemLocator, + nullptr, + CLSCTX_INPROC_SERVER, + IID_IWbemLocator, + ( LPVOID* )&pIWbemLocator ); +#ifdef PRINTF_DEBUGGING + if( FAILED( hr ) ) wprintf( L"WMI: CoCreateInstance failed: 0x%0.8x\n", hr ); +#endif + + if( SUCCEEDED( hr ) && pIWbemLocator ) + { + // Using the locator, connect to WMI in the given namespace. + pNamespace = SysAllocString( L"\\\\.\\root\\cimv2" ); + + hr = pIWbemLocator->ConnectServer( pNamespace, nullptr, nullptr, 0L, + 0L, nullptr, nullptr, &pIWbemServices ); +#ifdef PRINTF_DEBUGGING + if( FAILED( hr ) ) wprintf( L"WMI: pIWbemLocator->ConnectServer failed: 0x%0.8x\n", hr ); +#endif + if( SUCCEEDED( hr ) && pIWbemServices != 0 ) + { + HINSTANCE hinstOle32 = nullptr; + + hinstOle32 = LoadLibraryW( L"ole32.dll" ); + if( hinstOle32 ) + { + PfnCoSetProxyBlanket pfnCoSetProxyBlanket = nullptr; + + pfnCoSetProxyBlanket = ( PfnCoSetProxyBlanket )GetProcAddress( hinstOle32, "CoSetProxyBlanket" ); + if( pfnCoSetProxyBlanket != 0 ) + { + // Switch security level to IMPERSONATE. + pfnCoSetProxyBlanket( pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, nullptr, + RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, 0 ); + } + + FreeLibrary( hinstOle32 ); + } + + IEnumWbemClassObject* pEnumVideoControllers = nullptr; + BSTR pClassName = nullptr; + + pClassName = SysAllocString( L"Win32_VideoController" ); + + hr = pIWbemServices->CreateInstanceEnum( pClassName, 0, + nullptr, &pEnumVideoControllers ); +#ifdef PRINTF_DEBUGGING + if( FAILED( hr ) ) wprintf( L"WMI: pIWbemServices->CreateInstanceEnum failed: 0x%0.8x\n", hr ); +#endif + + if( SUCCEEDED( hr ) && pEnumVideoControllers ) + { + IWbemClassObject* pVideoControllers[10] = {0}; + DWORD uReturned = 0; + BSTR pPropName = nullptr; + + // Get the first one in the list + pEnumVideoControllers->Reset(); + hr = pEnumVideoControllers->Next( 5000, // timeout in 5 seconds + 10, // return the first 10 + pVideoControllers, + &uReturned ); +#ifdef PRINTF_DEBUGGING + if( FAILED( hr ) ) wprintf( L"WMI: pEnumVideoControllers->Next failed: 0x%0.8x\n", hr ); + if( uReturned == 0 ) wprintf( L"WMI: pEnumVideoControllers uReturned == 0\n" ); +#endif + + VARIANT var; + if( SUCCEEDED( hr ) ) + { + bool bFound = false; + for( UINT iController = 0; iController < uReturned; iController++ ) + { + if ( !pVideoControllers[iController] ) + continue; + + pPropName = SysAllocString( L"PNPDeviceID" ); + hr = pVideoControllers[iController]->Get( pPropName, 0L, &var, nullptr, nullptr ); +#ifdef PRINTF_DEBUGGING + if( FAILED( hr ) ) + wprintf( L"WMI: pVideoControllers[iController]->Get PNPDeviceID failed: 0x%0.8x\n", hr ); +#endif + if( SUCCEEDED( hr ) ) + { + if( wcsstr( var.bstrVal, strInputDeviceID ) != 0 ) + bFound = true; + } + VariantClear( &var ); + if( pPropName ) SysFreeString( pPropName ); + + if( bFound ) + { + pPropName = SysAllocString( L"AdapterRAM" ); + hr = pVideoControllers[iController]->Get( pPropName, 0L, &var, nullptr, nullptr ); +#ifdef PRINTF_DEBUGGING + if( FAILED( hr ) ) + wprintf( L"WMI: pVideoControllers[iController]->Get AdapterRAM failed: 0x%0.8x\n", + hr ); +#endif + if( SUCCEEDED( hr ) ) + { + bGotMemory = true; + *pdwAdapterRam = var.ulVal; + } + VariantClear( &var ); + if( pPropName ) SysFreeString( pPropName ); + break; + } + SAFE_RELEASE( pVideoControllers[iController] ); + } + } + } + + if( pClassName ) + SysFreeString( pClassName ); + SAFE_RELEASE( pEnumVideoControllers ); + } + + if( pNamespace ) + SysFreeString( pNamespace ); + SAFE_RELEASE( pIWbemServices ); + } + + SAFE_RELEASE( pIWbemLocator ); + + if( SUCCEEDED( hrCoInitialize ) ) + CoUninitialize(); + + if( bGotMemory ) + return S_OK; + else + return E_FAIL; +} + +void get_wstring(IDxDiagContainer* containerp, WCHAR* wszPropName, WCHAR* wszPropValue, int outputSize) +{ + HRESULT hr; VARIANT var; - WCHAR wszPropValue[256]; VariantInit( &var ); hr = containerp->GetProp(wszPropName, &var ); @@ -76,13 +228,19 @@ std::string get_string(IDxDiagContainer *containerp, WCHAR *wszPropName) wcscpy( wszPropValue, (var.boolVal) ? L"true" : L"false" ); /* Flawfinder: ignore */ break; case VT_BSTR: - wcsncpy( wszPropValue, var.bstrVal, 255 ); /* Flawfinder: ignore */ - wszPropValue[255] = 0; + wcsncpy( wszPropValue, var.bstrVal, outputSize-1 ); /* Flawfinder: ignore */ + wszPropValue[outputSize-1] = 0; break; } } // Clear the variant (this is needed to free BSTR memory) VariantClear( &var ); +} + +std::string get_string(IDxDiagContainer *containerp, WCHAR *wszPropName) +{ + WCHAR wszPropValue[256]; + get_wstring(containerp, wszPropName, wszPropValue, 256); return utf16str_to_utf8str(wszPropValue); } @@ -361,8 +519,18 @@ BOOL LLDXHardware::getInfo(BOOL vram_only) goto LCleanup; } - // Get the English VRAM string + DWORD vram = 0; + + WCHAR deviceID[512]; + + get_wstring(device_containerp, L"szDeviceID", deviceID, 512); + + if (SUCCEEDED(GetVideoMemoryViaWMI(deviceID, &vram))) { + mVRAM = vram/(1024*1024); + } + else + { // Get the English VRAM string std::string ram_str = get_string(device_containerp, L"szDisplayMemoryEnglish"); // We don't need the device any more -- cgit v1.2.3 From b51f81e7fedb8e5a94ccc4a911a7b0f75b9290ae Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 30 Jun 2014 19:59:01 -0500 Subject: MAINT-2980 Fix for mac cutting texture memory in half (now that we're cutting texture memory to default to 1/3rd of installed ram, pre-cutting is redundant). --- indra/newview/featuretable_mac.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra') diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index a2d68eb550..628a96e988 100755 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -1,4 +1,4 @@ -version 36 +version 37 // The version number above should be implemented IF AND ONLY IF some // change has been made that is sufficiently important to justify // resetting the graphics preferences of all users to the recommended @@ -60,7 +60,7 @@ WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 -RenderTextureMemoryMultiple 1 0.5 +RenderTextureMemoryMultiple 1 1 RenderCompressTextures 1 1 RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 1 @@ -522,7 +522,7 @@ list ATI_Mobility_Radeon_9600 Disregard96DefaultDrawDistance 1 0 list NVIDIA_GeForce_8600 -RenderTextureMemoryMultiple 1 0.375 +RenderTextureMemoryMultiple 1 1 RenderUseImpostors 0 0 UseOcclusion 0 0 -- cgit v1.2.3 From 70c2472e427c2d58edd857d298ea9f1fbe4bd41f Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Wed, 2 Jul 2014 16:57:07 +0300 Subject: MAINT-4203 FIXED [Group Bans] Member list shows newly banned ex-residents --- indra/newview/llpanelgrouproles.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'indra') diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index 68022ef343..47f2c94cd1 100755 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -1330,6 +1330,15 @@ void LLPanelGroupMembersSubTab::activate() update(GC_ALL); mActivated = true; } + else + { + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID); + // Members can be removed outside of this tab, checking changes + if (!gdatap || (gdatap->isMemberDataComplete() && gdatap->mMembers.size() != mMembersList->getItemCount())) + { + update(GC_MEMBER_DATA); + } + } } void LLPanelGroupMembersSubTab::deactivate() -- cgit v1.2.3 From 770a0a2dea0bd503f88b35d3d440208bcd303e54 Mon Sep 17 00:00:00 2001 From: Dave Parks Date: Mon, 7 Jul 2014 10:28:54 -0500 Subject: MAINT-2980 Back out most changes related to upping the 512MB texture cap to unblock RC. --- indra/newview/app_settings/settings.xml | 2 +- indra/newview/llviewertexture.cpp | 2 +- indra/newview/llviewertexturelist.cpp | 35 +++++++++++++++------- .../default/xui/en/floater_hardware_settings.xml | 4 +-- 4 files changed, 29 insertions(+), 14 deletions(-) (limited to 'indra') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 3c39c021ca..12db188620 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11873,7 +11873,7 @@ TextureMemory Comment - Amount of memory to use for textures in MB (0 = autodetect). Defaults to 1/3 of video memory to allow room for render targets, vertex buffers, 3D accelerated desktops, and over allocation. + Amount of memory to use for textures in MB (0 = autodetect) Persist 1 Type diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index e16caf167d..ba89aafc84 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -64,7 +64,7 @@ // extern const S32Megabytes gMinVideoRam(32); -const S32Megabytes gMaxVideoRam(4096); +const S32Megabytes gMaxVideoRam(512); // statics diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 9f862b4f97..b98726900f 100755 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -1275,37 +1275,52 @@ S32Megabytes LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, fl { S32Megabytes max_texmem; if (gGLManager.mVRAM != 0) - { //use detected amount of vram as maximum + { + // Treat any card with < 32 MB (shudder) as having 32 MB + // - it's going to be swapping constantly regardless S32Megabytes max_vram(gGLManager.mVRAM); - max_texmem = max_vram; - - if (get_recommended) - { //recommend 1/3rd of total video memory for textures - max_texmem /= 3; + if(gGLManager.mIsATI) + { + //shrink the availabe vram for ATI cards because some of them do not handel texture swapping well. + max_vram = max_vram * 0.75f; } + + max_vram = llmax(max_vram, getMinVideoRamSetting()); + max_texmem = max_vram; + if (!get_recommended) + max_texmem *= 2; } else { if (!get_recommended) { - max_texmem = (S32Megabytes) 2048; + max_texmem = (S32Megabytes)512; } else if (gSavedSettings.getBOOL("NoHardwareProbe")) //did not do hardware detection at startup { - max_texmem = (S32Megabytes) 2048; + max_texmem = (S32Megabytes)512; } else { - max_texmem = (S32Megabytes) 512; + max_texmem = (S32Megabytes)128; } LL_WARNS() << "VRAM amount not detected, defaulting to " << max_texmem << " MB" << LL_ENDL; } - // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise + S32Megabytes system_ram = gSysMemory.getPhysicalMemoryClamped(); // In MB + //LL_INFOS() << "*** DETECTED " << system_ram << " MB of system memory." << LL_ENDL; + if (get_recommended) + max_texmem = llmin(max_texmem, system_ram/2); + else + max_texmem = llmin(max_texmem, system_ram); + + // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise max_texmem = llmin(max_texmem, (S32Megabytes) (mem_multiplier * max_texmem)); + max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), gMaxVideoRam); + return max_texmem; } diff --git a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml index 40d54233e8..9deb0d2030 100755 --- a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml @@ -155,9 +155,9 @@ tool_tip="Compresses textures in video memory, allowing for higher resolution textures to be loaded at the cost of some color quality." width="315" /> Date: Wed, 9 Jul 2014 14:26:16 -0400 Subject: MAINT-4216 FIX --- indra/newview/llappearancemgr.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'indra') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 6797dab839..9451a30341 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1341,15 +1341,15 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, LLNotificationsUtil::add("CannotWearTrash"); return false; } - else if (gInventory.isObjectDescendentOf(item_to_wear->getUUID(), LLAppearanceMgr::instance().getCOF())) // EXT-84911 + else if (isLinkedInCOF(item_to_wear->getUUID())) // EXT-84911 { return false; } switch (item_to_wear->getType()) { - case LLAssetType::AT_CLOTHING: - if (gAgentWearables.areWearablesLoaded()) + case LLAssetType::AT_CLOTHING: + if (gAgentWearables.areWearablesLoaded()) { if (!cb && do_update) { @@ -1367,7 +1367,8 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, addCOFItemLink(item_to_wear, cb); } break; - case LLAssetType::AT_BODYPART: + + case LLAssetType::AT_BODYPART: // TODO: investigate wearables may not be loaded at this point EXT-8231 // Remove the existing wearables of the same type. @@ -1379,10 +1380,12 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, } addCOFItemLink(item_to_wear, cb); break; - case LLAssetType::AT_OBJECT: + + case LLAssetType::AT_OBJECT: rez_attachment(item_to_wear, NULL, replace); break; - default: return false;; + + default: return false;; } return true; -- cgit v1.2.3 From 3b5b6e35c4f1d5412349766deff7bf573ac1a301 Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Sat, 12 Jul 2014 02:51:27 +0300 Subject: fixing merge conficts --- indra/newview/llnamelistctrl.cpp | 5 +++-- indra/newview/llnamelistctrl.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'indra') diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp index c0bf763437..54e4c6c1da 100755 --- a/indra/newview/llnamelistctrl.cpp +++ b/indra/newview/llnamelistctrl.cpp @@ -64,8 +64,7 @@ LLNameListCtrl::LLNameListCtrl(const LLNameListCtrl::Params& p) mNameColumnIndex(p.name_column.column_index), mNameColumn(p.name_column.column_name), mAllowCallingCardDrop(p.allow_calling_card_drop), - mShortNames(p.short_names) - mAvatarNameCacheConnection(), + mShortNames(p.short_names), mPendingLookupsRemaining(0) {} @@ -337,6 +336,8 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow( it->second.disconnect(); } mAvatarNameCacheConnections.erase(it); + } + mAvatarNameCacheConnections[id] = LLAvatarNameCache::get(id,boost::bind(&LLNameListCtrl::onAvatarNameCache,this, _1, _2, suffix, item->getHandle())); if(mPendingLookupsRemaining <= 0) { diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index ae74ca2cbc..2c40eeaaca 100755 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -168,6 +168,7 @@ private: BOOL mAllowCallingCardDrop; bool mShortNames; // display name only, no SLID typedef std::map avatar_name_cache_connection_map_t; + avatar_name_cache_connection_map_t mAvatarNameCacheConnections; S32 mPendingLookupsRemaining; namelist_complete_signal_t mNameListCompleteSignal; -- cgit v1.2.3 From b4df05d21af49ab7195b77d44fb0e53b070e79bd Mon Sep 17 00:00:00 2001 From: Mnikolenko ProductEngine Date: Mon, 14 Jul 2014 12:31:16 +0300 Subject: MAINT-4226 Group ban option is added to participant menu in Group chat. --- indra/newview/llconversationmodel.cpp | 9 +++ indra/newview/llconversationmodel.h | 2 + indra/newview/llfloaterimcontainer.cpp | 87 ++++++++++++++++++++++ indra/newview/llfloaterimcontainer.h | 4 + .../skins/default/xui/en/menu_conversation.xml | 8 ++ 5 files changed, 110 insertions(+) (limited to 'indra') diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 74b77f760d..6e32ce60ec 100755 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -51,6 +51,7 @@ LLConversationItem::LLConversationItem(std::string display_name, const LLUUID& u mConvType(CONV_UNKNOWN), mLastActiveTime(0.0), mDisplayModeratorOptions(false), + mDisplayGroupBanOptions(false), mAvatarNameCacheConnection() { } @@ -63,6 +64,7 @@ LLConversationItem::LLConversationItem(const LLUUID& uuid, LLFolderViewModelInte mConvType(CONV_UNKNOWN), mLastActiveTime(0.0), mDisplayModeratorOptions(false), + mDisplayGroupBanOptions(false), mAvatarNameCacheConnection() { } @@ -75,6 +77,7 @@ LLConversationItem::LLConversationItem(LLFolderViewModelInterface& root_view_mod mConvType(CONV_UNKNOWN), mLastActiveTime(0.0), mDisplayModeratorOptions(false), + mDisplayGroupBanOptions(false), mAvatarNameCacheConnection() { } @@ -159,6 +162,12 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32 items.push_back(std::string("ModerateVoiceMute")); items.push_back(std::string("ModerateVoiceUnmute")); } + + if ((getType() != CONV_SESSION_1_ON_1) && mDisplayGroupBanOptions) + { + items.push_back(std::string("Group Ban Separator")); + items.push_back(std::string("BanMember")); + } } } diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index dc74506c53..56e1a26709 100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h @@ -143,6 +143,7 @@ protected: bool mNeedsRefresh; // Flag signaling to the view that something changed for this item F64 mLastActiveTime; bool mDisplayModeratorOptions; + bool mDisplayGroupBanOptions; boost::signals2::connection mAvatarNameCacheConnection; }; @@ -206,6 +207,7 @@ public: void dumpDebugData(); void setModeratorOptionsVisible(bool visible) { mDisplayModeratorOptions = visible; } void setDisplayModeratorRole(bool displayRole); + void setGroupBanVisible(bool visible) { mDisplayGroupBanOptions = visible; } private: void onAvatarNameCache(const LLAvatarName& av_name); // callback used by fetchAvatarName diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index a0df37b309..8ebe268d81 100755 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -532,6 +532,7 @@ void LLFloaterIMContainer::draw() { LLConversationItemParticipant* participant_model = dynamic_cast(*current_participant_model); participant_model->setModeratorOptionsVisible(isGroupModerator() && participant_model->getUUID() != gAgentID); + participant_model->setGroupBanVisible(haveAbilityToBan() && participant_model->getUUID() != gAgentID); current_participant_model++; } @@ -1150,6 +1151,10 @@ void LLFloaterIMContainer::doToParticipants(const std::string& command, uuid_vec { toggleAllowTextChat(userID); } + else if ("ban_member" == command) + { + banSelectedMember(userID); + } } else if (selectedIDS.size() > 1) { @@ -1407,6 +1412,10 @@ bool LLFloaterIMContainer::enableContextMenuItem(const std::string& item, uuid_v else if ("can_offer_teleport" == item) { return LLAvatarActions::canOfferTeleport(uuids); + } + else if ("can_ban_member" == item) + { + return canBanSelectedMember(single_id); } else if (("can_moderate_voice" == item) || ("can_allow_text_chat" == item) || ("can_mute" == item) || ("can_unmute" == item)) { @@ -1830,6 +1839,84 @@ bool LLFloaterIMContainer::isGroupModerator() return false; } +bool LLFloaterIMContainer::haveAbilityToBan() +{ + LLSpeakerMgr * speaker_manager = getSpeakerMgrForSelectedParticipant(); + if (NULL == speaker_manager) + { + LL_WARNS() << "Speaker manager is missing" << LL_ENDL; + return false; + } + LLUUID group_uuid = speaker_manager->getSessionID(); + + return gAgent.isInGroup(group_uuid) && gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS); +} + +bool LLFloaterIMContainer::canBanSelectedMember(const LLUUID& participant_uuid) +{ + LLSpeakerMgr * speaker_manager = getSpeakerMgrForSelectedParticipant(); + if (NULL == speaker_manager) + { + LL_WARNS() << "Speaker manager is missing" << LL_ENDL; + return false; + } + LLUUID group_uuid = speaker_manager->getSessionID(); + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_uuid); + if(!gdatap) + { + LL_WARNS("Groups") << "Unable to get group data for group " << group_uuid << LL_ENDL; + return false; + } + + LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid)); + LLGroupMemberData* member_data = (*mi).second; + // Is the member an owner? + if ( member_data && member_data->isInRole(gdatap->mOwnerRole) ) + { + return false; + } + if( gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER) && + gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS) ) + { + return true; + } + + return false; +} + +void LLFloaterIMContainer::banSelectedMember(const LLUUID& participant_uuid) +{ + LLSpeakerMgr * speaker_manager = getSpeakerMgrForSelectedParticipant(); + if (NULL == speaker_manager) + { + LL_WARNS() << "Speaker manager is missing" << LL_ENDL; + return; + } + + LLUUID group_uuid = speaker_manager->getSessionID(); + LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_uuid); + if(!gdatap) + { + LL_WARNS("Groups") << "Unable to get group data for group " << group_uuid << LL_ENDL; + return; + } + std::vector ids; + ids.push_back(participant_uuid); + + LLGroupBanData ban_data; + gdatap->createBanEntry(participant_uuid, ban_data); + LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, group_uuid, LLGroupMgr::BAN_CREATE, ids); + LLGroupMgr::getInstance()->sendGroupMemberEjects(group_uuid, ids); + LLGroupMgr::getInstance()->sendGroupMembersRequest(group_uuid); + LLSD args; + std::string name; + gCacheName->getFullName(participant_uuid, name); + args["AVATAR_NAME"] = name; + args["GROUP_NAME"] = gdatap->mName; + LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args)); + +} + void LLFloaterIMContainer::moderateVoice(const std::string& command, const LLUUID& userID) { if (!gAgent.getRegion()) return; diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index f6d973b9b3..5ea9fd399b 100755 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -167,12 +167,16 @@ private: LLSpeaker * getSpeakerOfSelectedParticipant(LLSpeakerMgr * speaker_managerp); LLSpeakerMgr * getSpeakerMgrForSelectedParticipant(); bool isGroupModerator(); + bool haveAbilityToBan(); + bool canBanSelectedMember(const LLUUID& participant_uuid); + LLUUID getGroupUIIDForSelectedParticipant(); bool isMuted(const LLUUID& avatar_id); void moderateVoice(const std::string& command, const LLUUID& userID); void moderateVoiceAllParticipants(bool unmute); void moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute); void toggleAllowTextChat(const LLUUID& participant_uuid); void toggleMute(const LLUUID& participant_id, U32 flags); + void banSelectedMember(const LLUUID& participant_uuid); void openNearbyChat(); bool isParticipantListExpanded(); diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index f5a493c064..ed362b36e5 100755 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -214,4 +214,12 @@ + + + + + -- cgit v1.2.3 From 0f22bcdff029ba7c420ec04ce992251ab1d4be6f Mon Sep 17 00:00:00 2001 From: maksymsproductengine Date: Wed, 16 Jul 2014 02:16:48 +0300 Subject: MAINT-4263 FIXED Viewer crashes after right click on group in Conversations. --- indra/newview/llfloaterimcontainer.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'indra') diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 8ebe268d81..be8195b5ee 100755 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -1868,13 +1868,24 @@ bool LLFloaterIMContainer::canBanSelectedMember(const LLUUID& participant_uuid) return false; } + if (!gdatap->mMembers.size()) + { + return false; + } + LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid)); + if (mi == gdatap->mMembers.end()) + { + return false; + } + LLGroupMemberData* member_data = (*mi).second; // Is the member an owner? if ( member_data && member_data->isInRole(gdatap->mOwnerRole) ) { return false; } + if( gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER) && gAgent.hasPowerInGroup(group_uuid, GP_GROUP_BAN_ACCESS) ) { -- cgit v1.2.3 From 9f5fc6efbd3f3e4418372425734372b5a9bb5d35 Mon Sep 17 00:00:00 2001 From: andreykproductengine Date: Thu, 17 Jul 2014 20:30:35 +0300 Subject: MAINT-4241 FIXED [Group Bans] Ban member(s) button is not greyed out for banning group owners. Viewer gives message that you ejected group owner. --- indra/newview/llgroupmgr.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 98036f3a20..56e671d902 100755 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -2154,6 +2154,22 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) online_status, is_owner); + LLGroupMemberData* member_old = group_datap->mMembers[member_id]; + if (member_old && group_datap->mRoleMemberDataComplete) + { + LLGroupMemberData::role_list_t::iterator rit = member_old->roleBegin(); + LLGroupMemberData::role_list_t::iterator end = member_old->roleEnd(); + + for ( ; rit != end; ++rit) + { + data->addRole((*rit).first,(*rit).second); + } + } + else + { + group_datap->mRoleMemberDataComplete = false; + } + group_datap->mMembers[member_id] = data; } @@ -2173,7 +2189,7 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content) group_datap->mMemberDataComplete = true; group_datap->mMemberRequestID.setNull(); // Make the role-member data request - if (group_datap->mPendingRoleMemberRequest) + if (group_datap->mPendingRoleMemberRequest || !group_datap->mRoleMemberDataComplete) { group_datap->mPendingRoleMemberRequest = false; LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(group_id); -- cgit v1.2.3 From 532433674c9553636af9ea8d433b9da6d6fae587 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 21 Jul 2014 14:35:27 -0400 Subject: increment viewer version to 3.7.13 --- indra/newview/VIEWER_VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index f7e5aa84c2..214b521fe2 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -3.7.12 +3.7.13 -- cgit v1.2.3 From 1346949e4d601e8c945fa30593ba1d405e9ed80d Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Mon, 4 Aug 2014 14:41:11 -0400 Subject: increment viewer version to 3.7.14 --- indra/newview/VIEWER_VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra') diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 214b521fe2..35c6ac5179 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -3.7.13 +3.7.14 -- cgit v1.2.3